mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 07:51:31 -04:00
Merge tag 'memory-controller-drv-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers
Memory controller drivers for v7.1 1. TegraMC: - Few fixes for older issues - missing clock on Tegra264, missing enabling of DLL for Tegra30 and Tegra124. - Simplify the code in a few places. - Rework handling interrupts on different variants and add support for error logging on Tegra 264. 2. Drop Baikal SoC bt1-l2-ctl driver, because SoC support is being removed tree-wide. * tag 'memory-controller-drv-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl: memory: tegra: Add MC error logging support for Tegra264 memory: tegra: Prepare for supporting multiple intmask registers memory: tegra: Group SoC specific fields memory: tegra: Add support for multiple IRQs memory: tegra: Group register and fields memory: tegra: Group error handling related registers memory: tegra-mc: Use %pe format memory: tegra-mc: Simplify printing PTR_ERR with dev_err_probe memory: tegra-mc: Drop tegra_mc_setup_latency_allowance() return value memory: renesas-rpc-if: Simplify printing PTR_ERR with dev_err_probe memory: brcmstb_memc: Expand LPDDR4 check to cover for LPDDR5 dt-bindings: cache: bt1-l2-ctl: Remove unused bindings memory: bt1-l2-ctl: Remove not-going-to-be-supported code for Baikal SoC memory: tegra30-emc: Fix dll_change check memory: tegra124-emc: Fix dll_change check memory: tegra: Add support for DBB clock on Tegra264 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/cache/baikal,bt1-l2-ctl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Baikal-T1 L2-cache Control Block
|
||||
|
||||
maintainers:
|
||||
- Serge Semin <fancer.lancer@gmail.com>
|
||||
|
||||
description: |
|
||||
By means of the System Controller Baikal-T1 SoC exposes a few settings to
|
||||
tune the MIPS P5600 CM2 L2 cache performance up. In particular it's possible
|
||||
to change the Tag, Data and Way-select RAM access latencies. Baikal-T1
|
||||
L2-cache controller block is responsible for the tuning. Its DT node is
|
||||
supposed to be a child of the system controller.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: baikal,bt1-l2-ctl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
baikal,l2-ws-latency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Cycles of latency for Way-select RAM accesses
|
||||
default: 0
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
baikal,l2-tag-latency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Cycles of latency for Tag RAM accesses
|
||||
default: 0
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
baikal,l2-data-latency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Cycles of latency for Data RAM accesses
|
||||
default: 1
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
examples:
|
||||
- |
|
||||
l2@1f04d028 {
|
||||
compatible = "baikal,bt1-l2-ctl";
|
||||
reg = <0x1f04d028 0x004>;
|
||||
|
||||
baikal,l2-ws-latency = <1>;
|
||||
baikal,l2-tag-latency = <1>;
|
||||
baikal,l2-data-latency = <2>;
|
||||
};
|
||||
...
|
||||
@@ -64,17 +64,6 @@ config BRCMSTB_MEMC
|
||||
controller and specifically control the Self Refresh Power Down
|
||||
(SRPD) inactivity timeout.
|
||||
|
||||
config BT1_L2_CTL
|
||||
bool "Baikal-T1 CM2 L2-RAM Cache Control Block"
|
||||
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Baikal-T1 CPU is based on the MIPS P5600 Warrior IP-core. The CPU
|
||||
resides Coherency Manager v2 with embedded 1MB L2-cache. It's
|
||||
possible to tune the L2 cache performance up by setting the data,
|
||||
tags and way-select latencies of RAM access. This driver provides a
|
||||
dt properties-based and sysfs interface for it.
|
||||
|
||||
config TI_AEMIF
|
||||
tristate "Texas Instruments AEMIF driver"
|
||||
depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST
|
||||
|
||||
@@ -11,7 +11,6 @@ obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
|
||||
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
|
||||
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
|
||||
obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o
|
||||
obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o
|
||||
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
|
||||
obj-$(CONFIG_TI_EMIF) += emif.o
|
||||
obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#define REG_MEMC_CNTRLR_CONFIG 0x00
|
||||
#define CNTRLR_CONFIG_LPDDR4_SHIFT 5
|
||||
#define CNTRLR_CONFIG_LPDDR5_SHIFT 6
|
||||
#define CNTRLR_CONFIG_MASK 0xf
|
||||
#define REG_MEMC_SRPD_CFG_21 0x20
|
||||
#define REG_MEMC_SRPD_CFG_20 0x34
|
||||
@@ -34,14 +35,15 @@ struct brcmstb_memc {
|
||||
u32 srpd_offset;
|
||||
};
|
||||
|
||||
static int brcmstb_memc_uses_lpddr4(struct brcmstb_memc *memc)
|
||||
static int brcmstb_memc_uses_lpddr45(struct brcmstb_memc *memc)
|
||||
{
|
||||
void __iomem *config = memc->ddr_ctrl + REG_MEMC_CNTRLR_CONFIG;
|
||||
u32 reg;
|
||||
|
||||
reg = readl_relaxed(config) & CNTRLR_CONFIG_MASK;
|
||||
|
||||
return reg == CNTRLR_CONFIG_LPDDR4_SHIFT;
|
||||
return reg == CNTRLR_CONFIG_LPDDR4_SHIFT ||
|
||||
reg == CNTRLR_CONFIG_LPDDR5_SHIFT;
|
||||
}
|
||||
|
||||
static int brcmstb_memc_srpd_config(struct brcmstb_memc *memc,
|
||||
@@ -95,7 +97,7 @@ static ssize_t srpd_store(struct device *dev, struct device_attribute *attr,
|
||||
* dynamic tuning process will also get affected by the inactivity
|
||||
* timeout, thus making it non functional.
|
||||
*/
|
||||
if (brcmstb_memc_uses_lpddr4(memc))
|
||||
if (brcmstb_memc_uses_lpddr45(memc))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = kstrtouint(buf, 10, &val);
|
||||
|
||||
@@ -1,323 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
|
||||
*
|
||||
* Authors:
|
||||
* Serge Semin <Sergey.Semin@baikalelectronics.ru>
|
||||
*
|
||||
* Baikal-T1 CM2 L2-cache Control Block driver.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#define L2_CTL_REG 0x028
|
||||
#define L2_CTL_DATA_STALL_FLD 0
|
||||
#define L2_CTL_DATA_STALL_MASK GENMASK(1, L2_CTL_DATA_STALL_FLD)
|
||||
#define L2_CTL_TAG_STALL_FLD 2
|
||||
#define L2_CTL_TAG_STALL_MASK GENMASK(3, L2_CTL_TAG_STALL_FLD)
|
||||
#define L2_CTL_WS_STALL_FLD 4
|
||||
#define L2_CTL_WS_STALL_MASK GENMASK(5, L2_CTL_WS_STALL_FLD)
|
||||
#define L2_CTL_SET_CLKRATIO BIT(13)
|
||||
#define L2_CTL_CLKRATIO_LOCK BIT(31)
|
||||
|
||||
#define L2_CTL_STALL_MIN 0
|
||||
#define L2_CTL_STALL_MAX 3
|
||||
#define L2_CTL_STALL_SET_DELAY_US 1
|
||||
#define L2_CTL_STALL_SET_TOUT_US 1000
|
||||
|
||||
/*
|
||||
* struct l2_ctl - Baikal-T1 L2 Control block private data.
|
||||
* @dev: Pointer to the device structure.
|
||||
* @sys_regs: Baikal-T1 System Controller registers map.
|
||||
*/
|
||||
struct l2_ctl {
|
||||
struct device *dev;
|
||||
|
||||
struct regmap *sys_regs;
|
||||
};
|
||||
|
||||
/*
|
||||
* enum l2_ctl_stall - Baikal-T1 L2-cache-RAM stall identifier.
|
||||
* @L2_WSSTALL: Way-select latency.
|
||||
* @L2_TAGSTALL: Tag latency.
|
||||
* @L2_DATASTALL: Data latency.
|
||||
*/
|
||||
enum l2_ctl_stall {
|
||||
L2_WS_STALL,
|
||||
L2_TAG_STALL,
|
||||
L2_DATA_STALL
|
||||
};
|
||||
|
||||
/*
|
||||
* struct l2_ctl_device_attribute - Baikal-T1 L2-cache device attribute.
|
||||
* @dev_attr: Actual sysfs device attribute.
|
||||
* @id: L2-cache stall field identifier.
|
||||
*/
|
||||
struct l2_ctl_device_attribute {
|
||||
struct device_attribute dev_attr;
|
||||
enum l2_ctl_stall id;
|
||||
};
|
||||
|
||||
#define to_l2_ctl_dev_attr(_dev_attr) \
|
||||
container_of(_dev_attr, struct l2_ctl_device_attribute, dev_attr)
|
||||
|
||||
#define L2_CTL_ATTR_RW(_name, _prefix, _id) \
|
||||
struct l2_ctl_device_attribute l2_ctl_attr_##_name = \
|
||||
{ __ATTR(_name, 0644, _prefix##_show, _prefix##_store), _id }
|
||||
|
||||
static int l2_ctl_get_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 *val)
|
||||
{
|
||||
u32 data = 0;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(l2->sys_regs, L2_CTL_REG, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (id) {
|
||||
case L2_WS_STALL:
|
||||
*val = FIELD_GET(L2_CTL_WS_STALL_MASK, data);
|
||||
break;
|
||||
case L2_TAG_STALL:
|
||||
*val = FIELD_GET(L2_CTL_TAG_STALL_MASK, data);
|
||||
break;
|
||||
case L2_DATA_STALL:
|
||||
*val = FIELD_GET(L2_CTL_DATA_STALL_MASK, data);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l2_ctl_set_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 val)
|
||||
{
|
||||
u32 mask = 0, data = 0;
|
||||
int ret;
|
||||
|
||||
val = clamp_val(val, L2_CTL_STALL_MIN, L2_CTL_STALL_MAX);
|
||||
|
||||
switch (id) {
|
||||
case L2_WS_STALL:
|
||||
data = FIELD_PREP(L2_CTL_WS_STALL_MASK, val);
|
||||
mask = L2_CTL_WS_STALL_MASK;
|
||||
break;
|
||||
case L2_TAG_STALL:
|
||||
data = FIELD_PREP(L2_CTL_TAG_STALL_MASK, val);
|
||||
mask = L2_CTL_TAG_STALL_MASK;
|
||||
break;
|
||||
case L2_DATA_STALL:
|
||||
data = FIELD_PREP(L2_CTL_DATA_STALL_MASK, val);
|
||||
mask = L2_CTL_DATA_STALL_MASK;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data |= L2_CTL_SET_CLKRATIO;
|
||||
mask |= L2_CTL_SET_CLKRATIO;
|
||||
|
||||
ret = regmap_update_bits(l2->sys_regs, L2_CTL_REG, mask, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_read_poll_timeout(l2->sys_regs, L2_CTL_REG, data,
|
||||
data & L2_CTL_CLKRATIO_LOCK,
|
||||
L2_CTL_STALL_SET_DELAY_US,
|
||||
L2_CTL_STALL_SET_TOUT_US);
|
||||
}
|
||||
|
||||
static void l2_ctl_clear_data(void *data)
|
||||
{
|
||||
struct l2_ctl *l2 = data;
|
||||
struct platform_device *pdev = to_platform_device(l2->dev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static struct l2_ctl *l2_ctl_create_data(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct l2_ctl *l2;
|
||||
int ret;
|
||||
|
||||
l2 = devm_kzalloc(dev, sizeof(*l2), GFP_KERNEL);
|
||||
if (!l2)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = devm_add_action(dev, l2_ctl_clear_data, l2);
|
||||
if (ret) {
|
||||
dev_err(dev, "Can't add L2 CTL data clear action\n");
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
l2->dev = dev;
|
||||
platform_set_drvdata(pdev, l2);
|
||||
|
||||
return l2;
|
||||
}
|
||||
|
||||
static int l2_ctl_find_sys_regs(struct l2_ctl *l2)
|
||||
{
|
||||
l2->sys_regs = syscon_node_to_regmap(l2->dev->of_node->parent);
|
||||
if (IS_ERR(l2->sys_regs)) {
|
||||
dev_err(l2->dev, "Couldn't get L2 CTL register map\n");
|
||||
return PTR_ERR(l2->sys_regs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l2_ctl_of_parse_property(struct l2_ctl *l2, enum l2_ctl_stall id,
|
||||
const char *propname)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 data;
|
||||
|
||||
if (!of_property_read_u32(l2->dev->of_node, propname, &data)) {
|
||||
ret = l2_ctl_set_latency(l2, id, data);
|
||||
if (ret)
|
||||
dev_err(l2->dev, "Invalid value of '%s'\n", propname);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int l2_ctl_of_parse(struct l2_ctl *l2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = l2_ctl_of_parse_property(l2, L2_WS_STALL, "baikal,l2-ws-latency");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = l2_ctl_of_parse_property(l2, L2_TAG_STALL, "baikal,l2-tag-latency");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return l2_ctl_of_parse_property(l2, L2_DATA_STALL,
|
||||
"baikal,l2-data-latency");
|
||||
}
|
||||
|
||||
static ssize_t l2_ctl_latency_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr);
|
||||
struct l2_ctl *l2 = dev_get_drvdata(dev);
|
||||
u32 data;
|
||||
int ret;
|
||||
|
||||
ret = l2_ctl_get_latency(l2, devattr->id, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_emit(buf, "%u\n", data);
|
||||
}
|
||||
|
||||
static ssize_t l2_ctl_latency_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr);
|
||||
struct l2_ctl *l2 = dev_get_drvdata(dev);
|
||||
u32 data;
|
||||
int ret;
|
||||
|
||||
if (kstrtouint(buf, 0, &data) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = l2_ctl_set_latency(l2, devattr->id, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static L2_CTL_ATTR_RW(l2_ws_latency, l2_ctl_latency, L2_WS_STALL);
|
||||
static L2_CTL_ATTR_RW(l2_tag_latency, l2_ctl_latency, L2_TAG_STALL);
|
||||
static L2_CTL_ATTR_RW(l2_data_latency, l2_ctl_latency, L2_DATA_STALL);
|
||||
|
||||
static struct attribute *l2_ctl_sysfs_attrs[] = {
|
||||
&l2_ctl_attr_l2_ws_latency.dev_attr.attr,
|
||||
&l2_ctl_attr_l2_tag_latency.dev_attr.attr,
|
||||
&l2_ctl_attr_l2_data_latency.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(l2_ctl_sysfs);
|
||||
|
||||
static void l2_ctl_remove_sysfs(void *data)
|
||||
{
|
||||
struct l2_ctl *l2 = data;
|
||||
|
||||
device_remove_groups(l2->dev, l2_ctl_sysfs_groups);
|
||||
}
|
||||
|
||||
static int l2_ctl_init_sysfs(struct l2_ctl *l2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = device_add_groups(l2->dev, l2_ctl_sysfs_groups);
|
||||
if (ret) {
|
||||
dev_err(l2->dev, "Failed to create L2 CTL sysfs nodes\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(l2->dev, l2_ctl_remove_sysfs, l2);
|
||||
if (ret)
|
||||
dev_err(l2->dev, "Can't add L2 CTL sysfs remove action\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int l2_ctl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct l2_ctl *l2;
|
||||
int ret;
|
||||
|
||||
l2 = l2_ctl_create_data(pdev);
|
||||
if (IS_ERR(l2))
|
||||
return PTR_ERR(l2);
|
||||
|
||||
ret = l2_ctl_find_sys_regs(l2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = l2_ctl_of_parse(l2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = l2_ctl_init_sysfs(l2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id l2_ctl_of_match[] = {
|
||||
{ .compatible = "baikal,bt1-l2-ctl" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, l2_ctl_of_match);
|
||||
|
||||
static struct platform_driver l2_ctl_driver = {
|
||||
.probe = l2_ctl_probe,
|
||||
.driver = {
|
||||
.name = "bt1-l2-ctl",
|
||||
.of_match_table = l2_ctl_of_match
|
||||
}
|
||||
};
|
||||
module_platform_driver(l2_ctl_driver);
|
||||
|
||||
MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
|
||||
MODULE_DESCRIPTION("Baikal-T1 L2-cache driver");
|
||||
@@ -1005,11 +1005,9 @@ static int rpcif_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(rpc->base);
|
||||
rpc->info = of_device_get_match_data(dev);
|
||||
rpc->regmap = devm_regmap_init(dev, NULL, rpc, rpc->info->regmap_config);
|
||||
if (IS_ERR(rpc->regmap)) {
|
||||
dev_err(dev, "failed to init regmap for rpcif, error %ld\n",
|
||||
PTR_ERR(rpc->regmap));
|
||||
return PTR_ERR(rpc->regmap);
|
||||
}
|
||||
if (IS_ERR(rpc->regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(rpc->regmap),
|
||||
"failed to init regmap for rpcif\n");
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
|
||||
rpc->dirmap = devm_ioremap_resource(dev, res);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -56,6 +56,23 @@ static const struct of_device_id tegra_mc_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
|
||||
|
||||
const struct tegra_mc_regs tegra20_mc_regs = {
|
||||
.cfg_channel_enable = 0xdf8,
|
||||
.err_status = 0x08,
|
||||
.err_add = 0x0c,
|
||||
.err_add_hi = 0x11fc,
|
||||
.err_vpr_status = 0x654,
|
||||
.err_vpr_add = 0x658,
|
||||
.err_sec_status = 0x67c,
|
||||
.err_sec_add = 0x680,
|
||||
.err_mts_status = 0x9b0,
|
||||
.err_mts_add = 0x9b4,
|
||||
.err_gen_co_status = 0xc00,
|
||||
.err_gen_co_add = 0xc04,
|
||||
.err_route_status = 0x9c0,
|
||||
.err_route_add = 0x9c4,
|
||||
};
|
||||
|
||||
static void tegra_mc_devm_action_put_device(void *data)
|
||||
{
|
||||
struct tegra_mc *mc = data;
|
||||
@@ -381,12 +398,16 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count);
|
||||
|
||||
const irq_handler_t tegra30_mc_irq_handlers[] = {
|
||||
tegra30_mc_handle_irq
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_114_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_124_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_132_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
|
||||
static void tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
|
||||
{
|
||||
unsigned long long tick;
|
||||
unsigned int i;
|
||||
@@ -414,8 +435,6 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
|
||||
|
||||
/* latch new values */
|
||||
mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_one_timing(struct tegra_mc *mc,
|
||||
@@ -509,32 +528,24 @@ int tegra30_mc_probe(struct tegra_mc *mc)
|
||||
int err;
|
||||
|
||||
mc->clk = devm_clk_get_optional(mc->dev, "mc");
|
||||
if (IS_ERR(mc->clk)) {
|
||||
dev_err(mc->dev, "failed to get MC clock: %ld\n", PTR_ERR(mc->clk));
|
||||
return PTR_ERR(mc->clk);
|
||||
}
|
||||
if (IS_ERR(mc->clk))
|
||||
return dev_err_probe(mc->dev, PTR_ERR(mc->clk),
|
||||
"failed to get MC clock\n");
|
||||
|
||||
/* ensure that debug features are disabled */
|
||||
mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG);
|
||||
|
||||
err = tegra_mc_setup_latency_allowance(mc);
|
||||
if (err < 0) {
|
||||
dev_err(mc->dev, "failed to setup latency allowance: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
tegra_mc_setup_latency_allowance(mc);
|
||||
|
||||
err = tegra_mc_setup_timings(mc);
|
||||
if (err < 0) {
|
||||
dev_err(mc->dev, "failed to setup timings: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
return dev_err_probe(mc->dev, err, "failed to setup timings\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct tegra_mc_ops tegra30_mc_ops = {
|
||||
.probe = tegra30_mc_probe,
|
||||
.handle_irq = tegra30_mc_handle_irq,
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -575,9 +586,9 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
|
||||
}
|
||||
|
||||
/* mask all interrupts to avoid flooding */
|
||||
status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask;
|
||||
status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
|
||||
} else {
|
||||
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
|
||||
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
@@ -600,37 +611,37 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
|
||||
|
||||
switch (intmask) {
|
||||
case MC_INT_DECERR_VPR:
|
||||
status_reg = MC_ERR_VPR_STATUS;
|
||||
addr_reg = MC_ERR_VPR_ADR;
|
||||
status_reg = mc->soc->regs->err_vpr_status;
|
||||
addr_reg = mc->soc->regs->err_vpr_add;
|
||||
break;
|
||||
|
||||
case MC_INT_SECERR_SEC:
|
||||
status_reg = MC_ERR_SEC_STATUS;
|
||||
addr_reg = MC_ERR_SEC_ADR;
|
||||
status_reg = mc->soc->regs->err_sec_status;
|
||||
addr_reg = mc->soc->regs->err_sec_add;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_MTS:
|
||||
status_reg = MC_ERR_MTS_STATUS;
|
||||
addr_reg = MC_ERR_MTS_ADR;
|
||||
status_reg = mc->soc->regs->err_mts_status;
|
||||
addr_reg = mc->soc->regs->err_mts_add;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_GENERALIZED_CARVEOUT:
|
||||
status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS;
|
||||
addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR;
|
||||
status_reg = mc->soc->regs->err_gen_co_status;
|
||||
addr_reg = mc->soc->regs->err_gen_co_add;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_ROUTE_SANITY:
|
||||
status_reg = MC_ERR_ROUTE_SANITY_STATUS;
|
||||
addr_reg = MC_ERR_ROUTE_SANITY_ADR;
|
||||
status_reg = mc->soc->regs->err_route_status;
|
||||
addr_reg = mc->soc->regs->err_route_add;
|
||||
break;
|
||||
|
||||
default:
|
||||
status_reg = MC_ERR_STATUS;
|
||||
addr_reg = MC_ERR_ADR;
|
||||
status_reg = mc->soc->regs->err_status;
|
||||
addr_reg = mc->soc->regs->err_add;
|
||||
|
||||
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
||||
if (mc->soc->has_addr_hi_reg)
|
||||
addr_hi_reg = MC_ERR_ADR_HI;
|
||||
addr_hi_reg = mc->soc->regs->err_add_hi;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -647,9 +658,12 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
|
||||
addr = mc_ch_readl(mc, channel, addr_hi_reg);
|
||||
else
|
||||
addr = mc_readl(mc, addr_hi_reg);
|
||||
} else {
|
||||
} else if (mc->soc->mc_addr_hi_mask) {
|
||||
addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
|
||||
MC_ERR_STATUS_ADR_HI_MASK);
|
||||
mc->soc->mc_addr_hi_mask);
|
||||
} else {
|
||||
dev_err_ratelimited(mc->dev, "Unable to determine high address!");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
addr <<= 32;
|
||||
}
|
||||
@@ -674,11 +688,11 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
type = (value & MC_ERR_STATUS_TYPE_MASK) >>
|
||||
type = (value & mc->soc->mc_err_status_type_mask) >>
|
||||
MC_ERR_STATUS_TYPE_SHIFT;
|
||||
desc = tegra_mc_error_names[type];
|
||||
desc = tegra20_mc_error_names[type];
|
||||
|
||||
switch (value & MC_ERR_STATUS_TYPE_MASK) {
|
||||
switch (value & mc->soc->mc_err_status_type_mask) {
|
||||
case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE:
|
||||
perm[0] = ' ';
|
||||
perm[1] = '[';
|
||||
@@ -744,9 +758,10 @@ const char *const tegra_mc_status_names[32] = {
|
||||
[16] = "MTS carveout violation",
|
||||
[17] = "Generalized carveout violation",
|
||||
[20] = "Route Sanity error",
|
||||
[21] = "GIC_MSI error",
|
||||
};
|
||||
|
||||
const char *const tegra_mc_error_names[8] = {
|
||||
const char *const tegra20_mc_error_names[8] = {
|
||||
[2] = "EMEM decode error",
|
||||
[3] = "TrustZone violation",
|
||||
[4] = "Carveout violation",
|
||||
@@ -883,7 +898,7 @@ static void tegra_mc_num_channel_enabled(struct tegra_mc *mc)
|
||||
unsigned int i;
|
||||
u32 value;
|
||||
|
||||
value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE);
|
||||
value = mc_ch_readl(mc, 0, mc->soc->regs->cfg_channel_enable);
|
||||
if (value <= 0) {
|
||||
mc->num_channels = mc->soc->num_channels;
|
||||
return;
|
||||
@@ -935,25 +950,32 @@ static int tegra_mc_probe(struct platform_device *pdev)
|
||||
|
||||
tegra_mc_num_channel_enabled(mc);
|
||||
|
||||
if (mc->soc->ops && mc->soc->ops->handle_irq) {
|
||||
mc->irq = platform_get_irq(pdev, 0);
|
||||
if (mc->irq < 0)
|
||||
return mc->irq;
|
||||
if (mc->soc->handle_irq) {
|
||||
unsigned int i;
|
||||
|
||||
WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
|
||||
|
||||
if (mc->soc->num_channels)
|
||||
mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask,
|
||||
MC_INTMASK);
|
||||
else
|
||||
mc_writel(mc, mc->soc->intmask, MC_INTMASK);
|
||||
for (i = 0; i < mc->soc->num_interrupts; i++) {
|
||||
int irq;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0,
|
||||
dev_name(&pdev->dev), mc);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
|
||||
err);
|
||||
return err;
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, irq, mc->soc->handle_irq[i], 0,
|
||||
dev_name(&pdev->dev), mc);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->soc->num_intmasks; i++) {
|
||||
if (mc->soc->num_channels)
|
||||
mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmasks[i].mask,
|
||||
mc->soc->intmasks[i].reg);
|
||||
else
|
||||
mc_writel(mc, mc->soc->intmasks[i].mask, mc->soc->intmasks[i].reg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,8 +993,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
|
||||
if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU) && mc->soc->smmu) {
|
||||
mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
|
||||
if (IS_ERR(mc->smmu)) {
|
||||
dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
|
||||
PTR_ERR(mc->smmu));
|
||||
dev_err(&pdev->dev, "failed to probe SMMU: %pe\n", mc->smmu);
|
||||
mc->smmu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_TEGRA_MC_H
|
||||
@@ -13,15 +13,36 @@
|
||||
#include <soc/tegra/mc.h>
|
||||
|
||||
#define MC_INTSTATUS 0x00
|
||||
/* Bit field of MC_INTSTATUS register */
|
||||
#define MC_INT_DECERR_EMEM BIT(6)
|
||||
#define MC_INT_INVALID_GART_PAGE BIT(7)
|
||||
#define MC_INT_SECURITY_VIOLATION BIT(8)
|
||||
#define MC_INT_ARBITRATION_EMEM BIT(9)
|
||||
#define MC_INT_INVALID_SMMU_PAGE BIT(10)
|
||||
#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11)
|
||||
#define MC_INT_DECERR_VPR BIT(12)
|
||||
#define MC_INT_SECERR_SEC BIT(13)
|
||||
#define MC_INT_DECERR_MTS BIT(16)
|
||||
#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17)
|
||||
#define MC_INT_DECERR_ROUTE_SANITY BIT(20)
|
||||
#define MC_INT_DECERR_ROUTE_SANITY_GIC_MSI BIT(21)
|
||||
|
||||
#define MC_INTMASK 0x04
|
||||
#define MC_ERR_STATUS 0x08
|
||||
#define MC_ERR_ADR 0x0c
|
||||
#define MC_GART_ERROR_REQ 0x30
|
||||
#define MC_EMEM_ADR_CFG 0x54
|
||||
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
|
||||
|
||||
#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
|
||||
#define MC_SECURITY_VIOLATION_STATUS 0x74
|
||||
#define MC_EMEM_ARB_CFG 0x90
|
||||
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff)
|
||||
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
|
||||
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30)
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31)
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff
|
||||
|
||||
#define MC_EMEM_ARB_TIMING_RCD 0x98
|
||||
#define MC_EMEM_ARB_TIMING_RP 0x9c
|
||||
#define MC_EMEM_ARB_TIMING_RC 0xa0
|
||||
@@ -41,60 +62,97 @@
|
||||
#define MC_EMEM_ARB_MISC1 0xdc
|
||||
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
|
||||
#define MC_EMEM_ARB_OVERRIDE 0xe8
|
||||
#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3
|
||||
|
||||
#define MC_TIMING_CONTROL_DBG 0xf8
|
||||
#define MC_TIMING_CONTROL 0xfc
|
||||
#define MC_ERR_VPR_STATUS 0x654
|
||||
#define MC_ERR_VPR_ADR 0x658
|
||||
#define MC_ERR_SEC_STATUS 0x67c
|
||||
#define MC_ERR_SEC_ADR 0x680
|
||||
#define MC_ERR_MTS_STATUS 0x9b0
|
||||
#define MC_ERR_MTS_ADR 0x9b4
|
||||
#define MC_ERR_ROUTE_SANITY_STATUS 0x9c0
|
||||
#define MC_ERR_ROUTE_SANITY_ADR 0x9c4
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
|
||||
#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8
|
||||
#define MC_GLOBAL_INTSTATUS 0xf24
|
||||
#define MC_ERR_ADR_HI 0x11fc
|
||||
#define MC_TIMING_UPDATE BIT(0)
|
||||
|
||||
#define MC_INT_DECERR_ROUTE_SANITY BIT(20)
|
||||
#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17)
|
||||
#define MC_INT_DECERR_MTS BIT(16)
|
||||
#define MC_INT_SECERR_SEC BIT(13)
|
||||
#define MC_INT_DECERR_VPR BIT(12)
|
||||
#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11)
|
||||
#define MC_INT_INVALID_SMMU_PAGE BIT(10)
|
||||
#define MC_INT_ARBITRATION_EMEM BIT(9)
|
||||
#define MC_INT_SECURITY_VIOLATION BIT(8)
|
||||
#define MC_INT_INVALID_GART_PAGE BIT(7)
|
||||
#define MC_INT_DECERR_EMEM BIT(6)
|
||||
#define MC_GLOBAL_INTSTATUS 0xf24
|
||||
|
||||
/* Bit field of MC_ERR_STATUS_0 register */
|
||||
#define MC_ERR_STATUS_RW BIT(16)
|
||||
#define MC_ERR_STATUS_SECURITY BIT(17)
|
||||
#define MC_ERR_STATUS_NONSECURE BIT(25)
|
||||
#define MC_ERR_STATUS_WRITABLE BIT(26)
|
||||
#define MC_ERR_STATUS_READABLE BIT(27)
|
||||
|
||||
#define MC_ERR_STATUS_GSC_ADR_HI_MASK 0xffff
|
||||
#define MC_ERR_STATUS_GSC_ADR_HI_SHIFT 16
|
||||
#define MC_ERR_STATUS_RT_ADR_HI_SHIFT 15
|
||||
|
||||
#define MC_ERR_STATUS_TYPE_SHIFT 28
|
||||
#define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28)
|
||||
#define MC_ERR_STATUS_TYPE_MASK (0x7 << 28)
|
||||
#define MC_ERR_STATUS_READABLE BIT(27)
|
||||
#define MC_ERR_STATUS_WRITABLE BIT(26)
|
||||
#define MC_ERR_STATUS_NONSECURE BIT(25)
|
||||
#define MC_ERR_STATUS_RT_TYPE_MASK (0xf << 28)
|
||||
#define MC_ERR_STATUS_RT_TYPE_SHIFT 28
|
||||
|
||||
#define MC_ERR_STATUS_ADR_HI_SHIFT 20
|
||||
#define MC_ERR_STATUS_ADR_HI_MASK 0x3
|
||||
#define MC_ERR_STATUS_SECURITY BIT(17)
|
||||
#define MC_ERR_STATUS_RW BIT(16)
|
||||
|
||||
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
|
||||
|
||||
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff)
|
||||
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
|
||||
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30)
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31)
|
||||
|
||||
#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3
|
||||
|
||||
#define MC_TIMING_UPDATE BIT(0)
|
||||
|
||||
#define MC_BROADCAST_CHANNEL ~0
|
||||
|
||||
/* Tegra264 specific registers */
|
||||
|
||||
/* Registers for MSS HUB */
|
||||
#define MSS_HUB_GLOBAL_INTSTATUS_0 0x6000
|
||||
#define MSS_HUBC_INTR BIT(0)
|
||||
#define MSS_HUB_GLOBAL_MASK 0x7F00
|
||||
#define MSS_HUB_GLOBAL_SHIFT 8
|
||||
|
||||
#define MSS_HUB_HUBC_INTSTATUS_0 0x6008
|
||||
#define MSS_HUB_INTRSTATUS_0 0x600c
|
||||
#define MSS_HUB_HUBC_INTMASK_0 0x6010
|
||||
#define MSS_HUB_HUBC_SCRUB_DONE_INTMASK BIT(0)
|
||||
|
||||
#define MSS_HUB_HUBC_INTPRIORITY_0 0x6014
|
||||
#define MSS_HUB_INTRMASK_0 0x6018
|
||||
#define MSS_HUB_COALESCER_ERR_INTMASK BIT(0)
|
||||
#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK BIT(1)
|
||||
#define MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK BIT(2)
|
||||
#define MSS_HUB_MSI_ERR_INTMASK BIT(3)
|
||||
#define MSS_HUB_POISON_RSP_INTMASK BIT(4)
|
||||
#define MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK BIT(5)
|
||||
#define MSS_HUB_RESERVED_PA_ERR_INTMASK BIT(6)
|
||||
|
||||
#define MSS_HUB_INTRPRIORITY_0 0x601c
|
||||
#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0 0x6020
|
||||
#define MSS_HUB_MSI_ERR_STATUS_0 0x6024
|
||||
#define MSS_HUB_POISON_RSP_STATUS_0 0x6028
|
||||
#define MSS_HUB_COALESCE_ERR_STATUS_0 0x60e0
|
||||
#define MSS_HUB_COALESCE_ERR_ADR_HI_0 0x60e4
|
||||
#define MSS_HUB_COALESCE_ERR_ADR_0 0x60e8
|
||||
#define MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0 0x638c
|
||||
#define MSS_HUB_RESERVED_PA_ERR_STATUS_0 0x6390
|
||||
#define MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0 0x63b0
|
||||
|
||||
/* Registers for channels */
|
||||
#define MC_CH_INTSTATUS_0 0x82d4
|
||||
#define MC_CH_INTMASK_0 0x82d8
|
||||
#define WCAM_ERR_INTMASK BIT(19)
|
||||
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0 0xbc74
|
||||
|
||||
/* Registers for MCF */
|
||||
#define MCF_COMMON_INTSTATUS0_0_0 0xce04
|
||||
#define MCF_INTSTATUS_0 0xce2c
|
||||
#define MCF_INTMASK_0 0xce30
|
||||
#define MCF_INTPRIORITY_0 0xce34
|
||||
|
||||
/* Registers for SBS */
|
||||
#define MSS_SBS_INTSTATUS_0 0xec08
|
||||
#define MSS_SBS_INTMASK_0 0xec0c
|
||||
#define MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK BIT(0)
|
||||
#define MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK BIT(1)
|
||||
#define MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK BIT(2)
|
||||
|
||||
/* Bit field of MC_ERR_ROUTE_SANITY_STATUS_0 register */
|
||||
#define MC_ERR_ROUTE_SANITY_RW BIT(12)
|
||||
#define MC_ERR_ROUTE_SANITY_SEC BIT(13)
|
||||
|
||||
#define ERR_GENERALIZED_APERTURE_ID_SHIFT 0
|
||||
#define ERR_GENERALIZED_APERTURE_ID_MASK 0x1F
|
||||
#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT 5
|
||||
#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK 0x1F
|
||||
|
||||
static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents)
|
||||
{
|
||||
val = val * percents;
|
||||
@@ -203,8 +261,9 @@ extern const struct tegra_mc_ops tegra186_mc_ops;
|
||||
#endif
|
||||
|
||||
irqreturn_t tegra30_mc_handle_irq(int irq, void *data);
|
||||
extern const irq_handler_t tegra30_mc_irq_handlers[1];
|
||||
extern const char * const tegra_mc_status_names[32];
|
||||
extern const char * const tegra_mc_error_names[8];
|
||||
extern const char * const tegra20_mc_error_names[8];
|
||||
|
||||
/*
|
||||
* These IDs are for internal use of Tegra ICC drivers. The ID numbers are
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
@@ -1101,6 +1101,14 @@ static const struct tegra_mc_reset tegra114_mc_resets[] = {
|
||||
TEGRA114_MC_RESET(VI, 0x200, 0x204, 17),
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra114_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
|
||||
MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra114_mc_soc = {
|
||||
.clients = tegra114_mc_clients,
|
||||
.num_clients = ARRAY_SIZE(tegra114_mc_clients),
|
||||
@@ -1108,10 +1116,14 @@ const struct tegra_mc_soc tegra114_mc_soc = {
|
||||
.atom_size = 32,
|
||||
.client_id_mask = 0x7f,
|
||||
.smmu = &tegra114_smmu_soc,
|
||||
.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
|
||||
MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra114_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra114_mc_intmasks),
|
||||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra114_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra114_mc_resets),
|
||||
.ops = &tegra30_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
|
||||
@@ -608,7 +608,7 @@ static int tegra124_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
|
||||
if ((last->emc_mode_1 & 0x1) == (timing->emc_mode_1 & 0x1))
|
||||
dll_change = DLL_CHANGE_NONE;
|
||||
else if (timing->emc_mode_1 & 0x1)
|
||||
else if (!(timing->emc_mode_1 & 0x1))
|
||||
dll_change = DLL_CHANGE_ON;
|
||||
else
|
||||
dll_change = DLL_CHANGE_OFF;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
@@ -1258,6 +1258,15 @@ static const struct tegra_smmu_soc tegra124_smmu_soc = {
|
||||
.num_asids = 128,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra124_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra124_mc_soc = {
|
||||
.clients = tegra124_mc_clients,
|
||||
.num_clients = ARRAY_SIZE(tegra124_mc_clients),
|
||||
@@ -1267,14 +1276,18 @@ const struct tegra_mc_soc tegra124_mc_soc = {
|
||||
.smmu = &tegra124_smmu_soc,
|
||||
.emem_regs = tegra124_mc_emem_regs,
|
||||
.num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs),
|
||||
.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra124_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra124_mc_intmasks),
|
||||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra124_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra124_mc_resets),
|
||||
.icc_ops = &tegra124_mc_icc_ops,
|
||||
.ops = &tegra30_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_addr_hi_mask = 0x3,
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
#endif /* CONFIG_ARCH_TEGRA_124_SOC */
|
||||
|
||||
@@ -1292,6 +1305,15 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = {
|
||||
.num_asids = 128,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra132_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra132_mc_soc = {
|
||||
.clients = tegra124_mc_clients,
|
||||
.num_clients = ARRAY_SIZE(tegra124_mc_clients),
|
||||
@@ -1299,13 +1321,17 @@ const struct tegra_mc_soc tegra132_mc_soc = {
|
||||
.atom_size = 32,
|
||||
.client_id_mask = 0x7f,
|
||||
.smmu = &tegra132_smmu_soc,
|
||||
.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra132_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra132_mc_intmasks),
|
||||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra124_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra124_mc_resets),
|
||||
.icc_ops = &tegra124_mc_icc_ops,
|
||||
.ops = &tegra30_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_addr_hi_mask = 0x3,
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
#endif /* CONFIG_ARCH_TEGRA_132_SOC */
|
||||
|
||||
@@ -22,6 +22,7 @@ struct tegra186_emc {
|
||||
struct tegra_bpmp *bpmp;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct clk *clk_dbb;
|
||||
|
||||
struct tegra186_emc_dvfs *dvfs;
|
||||
unsigned int num_dvfs;
|
||||
@@ -328,6 +329,13 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
goto put_bpmp;
|
||||
}
|
||||
|
||||
emc->clk_dbb = devm_clk_get_optional_enabled(&pdev->dev, "dbb");
|
||||
if (IS_ERR(emc->clk_dbb)) {
|
||||
err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk_dbb),
|
||||
"failed to get DBB clock\n");
|
||||
goto put_bpmp;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, emc);
|
||||
emc->dev = &pdev->dev;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2017-2025 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
@@ -174,7 +174,6 @@ const struct tegra_mc_ops tegra186_mc_ops = {
|
||||
.remove = tegra186_mc_remove,
|
||||
.resume = tegra186_mc_resume,
|
||||
.probe_device = tegra186_mc_probe_device,
|
||||
.handle_irq = tegra30_mc_handle_irq,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
|
||||
@@ -902,17 +901,30 @@ static const struct tegra_mc_client tegra186_mc_clients[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra186_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra186_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra186_mc_clients),
|
||||
.clients = tegra186_mc_clients,
|
||||
.num_address_bits = 40,
|
||||
.num_channels = 4,
|
||||
.client_id_mask = 0xff,
|
||||
.intmask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra186_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks),
|
||||
.ops = &tegra186_mc_ops,
|
||||
.ch_intmask = 0x0000000f,
|
||||
.global_intstatus_channel_shift = 0,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_addr_hi_mask = 0x3,
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2017-2021 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <soc/tegra/mc.h>
|
||||
@@ -1343,19 +1343,31 @@ static const struct tegra_mc_client tegra194_mc_clients[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra194_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT |
|
||||
MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra194_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra194_mc_clients),
|
||||
.clients = tegra194_mc_clients,
|
||||
.num_address_bits = 40,
|
||||
.num_channels = 16,
|
||||
.client_id_mask = 0xff,
|
||||
.intmask = MC_INT_DECERR_ROUTE_SANITY |
|
||||
MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra194_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra194_mc_intmasks),
|
||||
.has_addr_hi_reg = true,
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra_mc_icc_ops,
|
||||
.ch_intmask = 0x00000f00,
|
||||
.global_intstatus_channel_shift = 8,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_addr_hi_mask = 0x3,
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2012-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
@@ -695,7 +695,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
|
||||
unsigned int bit;
|
||||
|
||||
/* mask all interrupts to avoid flooding */
|
||||
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
|
||||
status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
@@ -713,7 +713,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
|
||||
value = mc_readl(mc, reg);
|
||||
|
||||
id = value & mc->soc->client_id_mask;
|
||||
desc = tegra_mc_error_names[2];
|
||||
desc = tegra20_mc_error_names[2];
|
||||
|
||||
if (value & BIT(31))
|
||||
direction = "write";
|
||||
@@ -724,7 +724,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
|
||||
value = mc_readl(mc, reg);
|
||||
|
||||
id = (value >> 1) & mc->soc->client_id_mask;
|
||||
desc = tegra_mc_error_names[2];
|
||||
desc = tegra20_mc_error_names[2];
|
||||
|
||||
if (value & BIT(0))
|
||||
direction = "write";
|
||||
@@ -736,7 +736,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
|
||||
|
||||
id = value & mc->soc->client_id_mask;
|
||||
type = (value & BIT(30)) ? 4 : 3;
|
||||
desc = tegra_mc_error_names[type];
|
||||
desc = tegra20_mc_error_names[type];
|
||||
secure = "secure ";
|
||||
|
||||
if (value & BIT(31))
|
||||
@@ -761,9 +761,20 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const irq_handler_t tegra20_mc_irq_handlers[] = {
|
||||
tegra20_mc_handle_irq
|
||||
};
|
||||
|
||||
static const struct tegra_mc_ops tegra20_mc_ops = {
|
||||
.probe = tegra20_mc_probe,
|
||||
.handle_irq = tegra20_mc_handle_irq,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra20_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
|
||||
MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra20_mc_soc = {
|
||||
@@ -771,11 +782,15 @@ const struct tegra_mc_soc tegra20_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra20_mc_clients),
|
||||
.num_address_bits = 32,
|
||||
.client_id_mask = 0x3f,
|
||||
.intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
|
||||
MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra20_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra20_mc_intmasks),
|
||||
.reset_ops = &tegra20_mc_reset_ops,
|
||||
.resets = tegra20_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra20_mc_resets),
|
||||
.icc_ops = &tegra20_mc_icc_ops,
|
||||
.ops = &tegra20_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra20_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers),
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2015-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/memory/tegra210-mc.h>
|
||||
@@ -1273,6 +1273,15 @@ static const struct tegra_mc_reset tegra210_mc_resets[] = {
|
||||
TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13),
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra210_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra210_mc_soc = {
|
||||
.clients = tegra210_mc_clients,
|
||||
.num_clients = ARRAY_SIZE(tegra210_mc_clients),
|
||||
@@ -1280,11 +1289,15 @@ const struct tegra_mc_soc tegra210_mc_soc = {
|
||||
.atom_size = 64,
|
||||
.client_id_mask = 0xff,
|
||||
.smmu = &tegra210_smmu_soc,
|
||||
.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra210_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra210_mc_intmasks),
|
||||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra210_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra210_mc_resets),
|
||||
.ops = &tegra30_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_addr_hi_mask = 0x3,
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2022-2026, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <soc/tegra/mc.h>
|
||||
@@ -1132,16 +1132,23 @@ static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
|
||||
.set = tegra234_mc_icc_set,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra234_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT |
|
||||
MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra234_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra234_mc_clients),
|
||||
.clients = tegra234_mc_clients,
|
||||
.num_address_bits = 40,
|
||||
.num_channels = 16,
|
||||
.client_id_mask = 0x1ff,
|
||||
.intmask = MC_INT_DECERR_ROUTE_SANITY |
|
||||
MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra234_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra234_mc_intmasks),
|
||||
.has_addr_hi_reg = true,
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra234_mc_icc_ops,
|
||||
@@ -1152,4 +1159,9 @@ const struct tegra_mc_soc tegra234_mc_soc = {
|
||||
* supported.
|
||||
*/
|
||||
.num_carveouts = 32,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_addr_hi_mask = 0x3,
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2025, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2025-2026, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/memory/nvidia,tegra264.h>
|
||||
@@ -188,6 +188,41 @@ static const struct tegra_mc_client tegra264_mc_clients[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const char *const tegra264_hub_error_names[32] = {
|
||||
[0] = "coalescer error",
|
||||
[1] = "SMMU BYPASS ALLOW error",
|
||||
[2] = "Illegal tbugrp_id error",
|
||||
[3] = "Malformed MSI request error",
|
||||
[4] = "Read response with poison bit error",
|
||||
[5] = "Restricted access violation error",
|
||||
[6] = "Reserved PA error",
|
||||
};
|
||||
|
||||
static const char *const tegra264_mc_error_names[4] = {
|
||||
[1] = "EMEM decode error",
|
||||
[2] = "TrustZone violation",
|
||||
[3] = "Carveout violation",
|
||||
};
|
||||
|
||||
static const char *const tegra264_rt_error_names[16] = {
|
||||
[1] = "DECERR_PARTIAL_POPULATED",
|
||||
[2] = "DECERR_SMMU_BYPASS",
|
||||
[3] = "DECERR_INVALID_MMIO",
|
||||
[4] = "DECERR_INVALID_GIC_MSI",
|
||||
[5] = "DECERR_ATOMIC_SYSRAM",
|
||||
[9] = "DECERR_REMOTE_REQ_PRE_BOOT",
|
||||
[10] = "DECERR_ISO_OVER_C2C",
|
||||
[11] = "DECERR_UNSUPPORTED_SBS_OPCODE",
|
||||
[12] = "DECERR_SBS_REQ_OVER_SISO_LL",
|
||||
};
|
||||
|
||||
/*
|
||||
* MC instance aperture mapping for hubc registers
|
||||
*/
|
||||
static const int mc_hubc_aperture_number[5] = {
|
||||
7, 8, 9, 10, 11
|
||||
};
|
||||
|
||||
/*
|
||||
* tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW
|
||||
* @src: ICC node for Memory Controller's (MC) Client
|
||||
@@ -283,6 +318,312 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus)
|
||||
{
|
||||
unsigned int bit;
|
||||
|
||||
for_each_set_bit(bit, &mcf_ch_intstatus, 32) {
|
||||
const char *client = "unknown", *desc = "NA";
|
||||
u32 status_reg, status1_reg = 0, addr_reg, addr_hi_reg = 0, err_type_mask = 0;
|
||||
u32 value, client_id, i, addr_hi_shift = 0, addr_hi_mask = 0, status1;
|
||||
u32 mc_rw_bit = MC_ERR_STATUS_RW, mc_sec_bit = MC_ERR_STATUS_SECURITY;
|
||||
phys_addr_t addr = 0;
|
||||
u8 type;
|
||||
|
||||
switch (BIT(bit)) {
|
||||
case MC_INT_DECERR_EMEM:
|
||||
case MC_INT_SECURITY_VIOLATION:
|
||||
status_reg = mc->soc->regs->err_status;
|
||||
addr_reg = mc->soc->regs->err_add;
|
||||
addr_hi_reg = mc->soc->regs->err_add_hi;
|
||||
err_type_mask = mc->soc->mc_err_status_type_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_VPR:
|
||||
status_reg = mc->soc->regs->err_vpr_status;
|
||||
addr_reg = mc->soc->regs->err_vpr_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_SECERR_SEC:
|
||||
status_reg = mc->soc->regs->err_sec_status;
|
||||
addr_reg = mc->soc->regs->err_sec_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_MTS:
|
||||
status_reg = mc->soc->regs->err_mts_status;
|
||||
addr_reg = mc->soc->regs->err_mts_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_GENERALIZED_CARVEOUT:
|
||||
status_reg = mc->soc->regs->err_gen_co_status;
|
||||
status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0;
|
||||
addr_reg = mc->soc->regs->err_gen_co_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT;
|
||||
addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_ROUTE_SANITY:
|
||||
case MC_INT_DECERR_ROUTE_SANITY_GIC_MSI:
|
||||
status_reg = mc->soc->regs->err_route_status;
|
||||
addr_reg = mc->soc->regs->err_route_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
mc_sec_bit = MC_ERR_ROUTE_SANITY_SEC;
|
||||
mc_rw_bit = MC_ERR_ROUTE_SANITY_RW;
|
||||
err_type_mask = MC_ERR_STATUS_RT_TYPE_MASK;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, channel, status_reg);
|
||||
if (addr_hi_reg) {
|
||||
addr = mc_ch_readl(mc, channel, addr_hi_reg);
|
||||
} else {
|
||||
if (!status1_reg) {
|
||||
addr = ((value >> addr_hi_shift) & addr_hi_mask);
|
||||
} else {
|
||||
status1 = mc_ch_readl(mc, channel, status1_reg);
|
||||
addr = ((status1 >> addr_hi_shift) & addr_hi_mask);
|
||||
}
|
||||
}
|
||||
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, channel, addr_reg);
|
||||
|
||||
client_id = value & mc->soc->client_id_mask;
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == client_id) {
|
||||
client = mc->soc->clients[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err_type_mask == MC_ERR_STATUS_RT_TYPE_MASK) {
|
||||
type = (value & err_type_mask) >>
|
||||
MC_ERR_STATUS_RT_TYPE_SHIFT;
|
||||
desc = tegra264_rt_error_names[type];
|
||||
} else if (err_type_mask) {
|
||||
type = (value & err_type_mask) >>
|
||||
MC_ERR_STATUS_TYPE_SHIFT;
|
||||
desc = tegra264_mc_error_names[type];
|
||||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n",
|
||||
client, value & mc_sec_bit ? "secure" : "non-secure",
|
||||
value & mc_rw_bit ? "write" : "read", &addr,
|
||||
tegra_mc_status_names[bit] ?: "unknown", desc);
|
||||
if (status1_reg)
|
||||
dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n",
|
||||
((status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT)
|
||||
& ERR_GENERALIZED_APERTURE_ID_MASK),
|
||||
((status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT)
|
||||
& ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK));
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
mc_ch_writel(mc, channel, mcf_ch_intstatus, MCF_INTSTATUS_0);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_mcf_irq(int irq, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = data;
|
||||
unsigned long common_intstat, intstatus;
|
||||
u32 slice;
|
||||
|
||||
/* Read MCF_COMMON_INTSTATUS0_0_0 from MCB block */
|
||||
common_intstat = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, MCF_COMMON_INTSTATUS0_0_0);
|
||||
if (common_intstat == 0) {
|
||||
dev_warn(mc->dev, "No interrupt in MCF\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
for_each_set_bit(slice, &common_intstat, 32) {
|
||||
/* Find out the slice number on which interrupt occurred */
|
||||
if (slice > 4) {
|
||||
dev_err(mc->dev, "Slice index out of bounds: %u\n", slice);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
intstatus = mc_ch_readl(mc, slice, MCF_INTSTATUS_0);
|
||||
if (intstatus != 0)
|
||||
mcf_log_fault(mc, slice, intstatus);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat)
|
||||
{
|
||||
unsigned int bit;
|
||||
|
||||
for_each_set_bit(bit, &hub_intstat, 32) {
|
||||
const char *client = "unknown";
|
||||
u32 client_id, status_reg, value, i;
|
||||
phys_addr_t addr = 0;
|
||||
|
||||
switch (BIT(bit)) {
|
||||
case MSS_HUB_COALESCER_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_COALESCE_ERR_STATUS_0;
|
||||
addr = mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_HI_0);
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_0);
|
||||
break;
|
||||
|
||||
case MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK:
|
||||
status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_MSI_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_MSI_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_POISON_RSP_INTMASK:
|
||||
status_reg = MSS_HUB_POISON_RSP_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_RESERVED_PA_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, hub, status_reg);
|
||||
|
||||
client_id = value & mc->soc->client_id_mask;
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == client_id) {
|
||||
client = mc->soc->clients[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n",
|
||||
client, &addr, tegra264_hub_error_names[bit] ?: "unknown",
|
||||
value);
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
mc_ch_writel(mc, hub, hub_intstat, MSS_HUB_INTRSTATUS_0);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_number)
|
||||
{
|
||||
struct tegra_mc *mc = data;
|
||||
u32 global_intstat;
|
||||
unsigned long hub_interrupt, intstat, hub;
|
||||
|
||||
/* Read MSS_HUB_GLOBAL_INTSTATUS_0 from mc_hubc_aperture_number block */
|
||||
global_intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_GLOBAL_INTSTATUS_0);
|
||||
if (global_intstat == 0) {
|
||||
dev_warn(mc->dev, "No interrupt in HUB/HUBC\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Handle interrupt from hubc */
|
||||
if (global_intstat & MSS_HUBC_INTR) {
|
||||
/* Read MSS_HUB_HUBC_INTSTATUS_0 from block mc_hubc_aperture_number */
|
||||
intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_HUBC_INTSTATUS_0);
|
||||
if (intstat != 0) {
|
||||
dev_err_ratelimited(mc->dev, "Scrubber operation status: 0x%lx\n",
|
||||
intstat);
|
||||
/* Clear hubc interrupt */
|
||||
mc_ch_writel(mc, mc_hubc_aperture_number, intstat,
|
||||
MSS_HUB_HUBC_INTSTATUS_0);
|
||||
}
|
||||
}
|
||||
|
||||
hub_interrupt = (global_intstat & MSS_HUB_GLOBAL_MASK) >> MSS_HUB_GLOBAL_SHIFT;
|
||||
/* Handle interrupt from hub */
|
||||
for_each_set_bit(hub, &hub_interrupt, 32) {
|
||||
/* Read MSS_HUB_INTRSTATUS_0 from block MCi */
|
||||
intstat = mc_ch_readl(mc, hub, MSS_HUB_INTRSTATUS_0);
|
||||
if (intstat != 0)
|
||||
hub_log_fault(mc, hub, intstat);
|
||||
}
|
||||
|
||||
/* Clear global interrupt status register */
|
||||
mc_ch_writel(mc, mc_hubc_aperture_number, global_intstat, MSS_HUB_GLOBAL_INTSTATUS_0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t handle_disp_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_system_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_vision_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_uphy_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_top_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg)
|
||||
{
|
||||
u32 intstat, i;
|
||||
|
||||
/* Iterate over all MC blocks to read INTSTATUS */
|
||||
for (i = 0; i < mc->num_channels; i++) {
|
||||
intstat = mc_ch_readl(mc, i, intstat_reg);
|
||||
if (intstat) {
|
||||
dev_err_ratelimited(mc->dev, "channel: %i status: 0x%x\n", i, intstat);
|
||||
/* Clear interrupt */
|
||||
mc_ch_writel(mc, i, intstat, intstat_reg);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t handle_sbs_irq(int irq, void *data)
|
||||
{
|
||||
return handle_generic_irq((struct tegra_mc *)data, MSS_SBS_INTSTATUS_0);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_channel_irq(int irq, void *data)
|
||||
{
|
||||
return handle_generic_irq((struct tegra_mc *)data, MC_CH_INTSTATUS_0);
|
||||
}
|
||||
|
||||
static const irq_handler_t tegra264_mc_irq_handlers[8] = {
|
||||
handle_mcf_irq, handle_disp_hub_irq, handle_vision_hub_irq,
|
||||
handle_system_hub_irq, handle_uphy_hub_irq, handle_top_hub_irq,
|
||||
handle_sbs_irq, handle_channel_irq
|
||||
};
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = {
|
||||
.xlate = tegra_mc_icc_xlate,
|
||||
.aggregate = tegra264_mc_icc_aggregate,
|
||||
@@ -290,16 +631,80 @@ static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = {
|
||||
.set = tegra264_mc_icc_set,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_regs tegra264_mc_regs = {
|
||||
.cfg_channel_enable = 0x8870,
|
||||
.err_status = 0xbc00,
|
||||
.err_add = 0xbc04,
|
||||
.err_add_hi = 0xbc08,
|
||||
.err_vpr_status = 0xbc20,
|
||||
.err_vpr_add = 0xbc24,
|
||||
.err_sec_status = 0xbc3c,
|
||||
.err_sec_add = 0xbc40,
|
||||
.err_mts_status = 0xbc5c,
|
||||
.err_mts_add = 0xbc60,
|
||||
.err_gen_co_status = 0xbc78,
|
||||
.err_gen_co_add = 0xbc7c,
|
||||
.err_route_status = 0xbc64,
|
||||
.err_route_add = 0xbc68,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra264_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MCF_INTMASK_0,
|
||||
.mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | MC_INT_DECERR_ROUTE_SANITY |
|
||||
MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_SECURITY_VIOLATION |
|
||||
MC_INT_DECERR_EMEM,
|
||||
},
|
||||
{
|
||||
.reg = MCF_INTPRIORITY_0,
|
||||
.mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | MC_INT_DECERR_ROUTE_SANITY |
|
||||
MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_SECURITY_VIOLATION |
|
||||
MC_INT_DECERR_EMEM,
|
||||
},
|
||||
{
|
||||
.reg = MSS_HUB_INTRMASK_0,
|
||||
.mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK |
|
||||
MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK |
|
||||
MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK |
|
||||
MSS_HUB_RESERVED_PA_ERR_INTMASK,
|
||||
},
|
||||
{
|
||||
.reg = MSS_HUB_INTRPRIORITY_0,
|
||||
.mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK |
|
||||
MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK |
|
||||
MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK |
|
||||
MSS_HUB_RESERVED_PA_ERR_INTMASK,
|
||||
},
|
||||
{
|
||||
.reg = MSS_HUB_HUBC_INTMASK_0,
|
||||
.mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK,
|
||||
},
|
||||
{
|
||||
.reg = MSS_HUB_HUBC_INTPRIORITY_0,
|
||||
.mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK,
|
||||
},
|
||||
{
|
||||
.reg = MSS_SBS_INTMASK_0,
|
||||
.mask = MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK |
|
||||
MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK |
|
||||
MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK,
|
||||
},
|
||||
{
|
||||
.reg = MC_CH_INTMASK_0,
|
||||
.mask = WCAM_ERR_INTMASK,
|
||||
}
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra264_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra264_mc_clients),
|
||||
.clients = tegra264_mc_clients,
|
||||
.num_address_bits = 40,
|
||||
.num_channels = 16,
|
||||
.client_id_mask = 0x1ff,
|
||||
.intmask = MC_INT_DECERR_ROUTE_SANITY |
|
||||
MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
|
||||
MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
|
||||
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra264_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra264_mc_intmasks),
|
||||
.has_addr_hi_reg = true,
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra264_mc_icc_ops,
|
||||
@@ -310,4 +715,9 @@ const struct tegra_mc_soc tegra264_mc_soc = {
|
||||
* supported.
|
||||
*/
|
||||
.num_carveouts = 32,
|
||||
.mc_addr_hi_mask = 0xff,
|
||||
.mc_err_status_type_mask = (0x3 << 28),
|
||||
.regs = &tegra264_mc_regs,
|
||||
.handle_irq = tegra264_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra264_mc_irq_handlers),
|
||||
};
|
||||
|
||||
@@ -554,14 +554,14 @@ static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
|
||||
emc->emc_cfg = readl_relaxed(emc->regs + EMC_CFG);
|
||||
emc_dbg = readl_relaxed(emc->regs + EMC_DBG);
|
||||
|
||||
if (emc->dll_on == !!(timing->emc_mode_1 & 0x1))
|
||||
if (emc->dll_on == !(timing->emc_mode_1 & 0x1))
|
||||
dll_change = DLL_CHANGE_NONE;
|
||||
else if (timing->emc_mode_1 & 0x1)
|
||||
else if (!(timing->emc_mode_1 & 0x1))
|
||||
dll_change = DLL_CHANGE_ON;
|
||||
else
|
||||
dll_change = DLL_CHANGE_OFF;
|
||||
|
||||
emc->dll_on = !!(timing->emc_mode_1 & 0x1);
|
||||
emc->dll_on = !(timing->emc_mode_1 & 0x1);
|
||||
|
||||
if (timing->data[80] && !readl_relaxed(emc->regs + EMC_ZCAL_INTERVAL))
|
||||
emc->zcal_long = true;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@@ -1384,6 +1384,14 @@ static const struct tegra_mc_icc_ops tegra30_mc_icc_ops = {
|
||||
.set = tegra30_mc_icc_set,
|
||||
};
|
||||
|
||||
static const struct tegra_mc_intmask tegra30_mc_intmasks[] = {
|
||||
{
|
||||
.reg = MC_INTMASK,
|
||||
.mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
|
||||
MC_INT_DECERR_EMEM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra30_mc_soc = {
|
||||
.clients = tegra30_mc_clients,
|
||||
.num_clients = ARRAY_SIZE(tegra30_mc_clients),
|
||||
@@ -1393,11 +1401,15 @@ const struct tegra_mc_soc tegra30_mc_soc = {
|
||||
.smmu = &tegra30_smmu_soc,
|
||||
.emem_regs = tegra30_mc_emem_regs,
|
||||
.num_emem_regs = ARRAY_SIZE(tegra30_mc_emem_regs),
|
||||
.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
|
||||
MC_INT_DECERR_EMEM,
|
||||
.intmasks = tegra30_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra30_mc_intmasks),
|
||||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra30_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra30_mc_resets),
|
||||
.icc_ops = &tegra30_mc_icc_ops,
|
||||
.ops = &tegra30_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
|
||||
.mc_err_status_type_mask = (0x7 << 28),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2014 NVIDIA Corporation
|
||||
* Copyright (C) 2014-2026 NVIDIA Corporation
|
||||
*/
|
||||
|
||||
#ifndef __SOC_TEGRA_MC_H__
|
||||
@@ -10,10 +10,11 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/tegra-icc.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct clk;
|
||||
struct device;
|
||||
@@ -164,10 +165,31 @@ struct tegra_mc_ops {
|
||||
int (*probe)(struct tegra_mc *mc);
|
||||
void (*remove)(struct tegra_mc *mc);
|
||||
int (*resume)(struct tegra_mc *mc);
|
||||
irqreturn_t (*handle_irq)(int irq, void *data);
|
||||
int (*probe_device)(struct tegra_mc *mc, struct device *dev);
|
||||
};
|
||||
|
||||
struct tegra_mc_regs {
|
||||
unsigned int cfg_channel_enable;
|
||||
unsigned int err_status;
|
||||
unsigned int err_add;
|
||||
unsigned int err_add_hi;
|
||||
unsigned int err_vpr_status;
|
||||
unsigned int err_vpr_add;
|
||||
unsigned int err_sec_status;
|
||||
unsigned int err_sec_add;
|
||||
unsigned int err_mts_status;
|
||||
unsigned int err_mts_add;
|
||||
unsigned int err_gen_co_status;
|
||||
unsigned int err_gen_co_add;
|
||||
unsigned int err_route_status;
|
||||
unsigned int err_route_add;
|
||||
};
|
||||
|
||||
struct tegra_mc_intmask {
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
struct tegra_mc_soc {
|
||||
const struct tegra_mc_client *clients;
|
||||
unsigned int num_clients;
|
||||
@@ -185,7 +207,6 @@ struct tegra_mc_soc {
|
||||
|
||||
const struct tegra_smmu_soc *smmu;
|
||||
|
||||
u32 intmask;
|
||||
u32 ch_intmask;
|
||||
u32 global_intstatus_channel_shift;
|
||||
bool has_addr_hi_reg;
|
||||
@@ -196,6 +217,14 @@ struct tegra_mc_soc {
|
||||
|
||||
const struct tegra_mc_icc_ops *icc_ops;
|
||||
const struct tegra_mc_ops *ops;
|
||||
const struct tegra_mc_regs *regs;
|
||||
|
||||
const irq_handler_t *handle_irq;
|
||||
unsigned int num_interrupts;
|
||||
unsigned int mc_addr_hi_mask;
|
||||
unsigned int mc_err_status_type_mask;
|
||||
const struct tegra_mc_intmask *intmasks;
|
||||
unsigned int num_intmasks;
|
||||
};
|
||||
|
||||
struct tegra_mc {
|
||||
@@ -206,7 +235,6 @@ struct tegra_mc {
|
||||
void __iomem *bcast_ch_regs;
|
||||
void __iomem **ch_regs;
|
||||
struct clk *clk;
|
||||
int irq;
|
||||
|
||||
const struct tegra_mc_soc *soc;
|
||||
unsigned long tick;
|
||||
@@ -256,4 +284,6 @@ tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id,
|
||||
}
|
||||
#endif
|
||||
|
||||
extern const struct tegra_mc_regs tegra20_mc_regs;
|
||||
|
||||
#endif /* __SOC_TEGRA_MC_H__ */
|
||||
|
||||
Reference in New Issue
Block a user