mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Memory controller drivers for v7.4
1. Broadcom DPFE: Fix handling kernel memory accesses with malicious or
compromised firmware and possible out-of-bounds read triggered by
buggy co-processor. Also validate firmware image contents before
processing it.
2. Renesas RPC IF: One fix for volatile register access, several
cleanups and enable autosuspend in runtime PM.
3. Several minor improvements and fixes for various drivers: TI EMIF,
Samsung Exynos5422 DMC, Nvidia Tegra264 and STM32 OMM. The fixes
seems to be effect of LLM usage, thus they were neither reproduced
nor tested, making them non-critical fixes.
4. Mediatek SMI: Add support for MT8189 SoC.
-----BEGIN PGP SIGNATURE-----
iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAmrDg/IQHGtyemtAa2Vy
bmVsLm9yZwAKCRDBN2bmhouD1xTlD/9GsjZZgJFWp9ArVIWvm7eO+g5xWJ6lNq64
rfG17tpl2hZ2JUWHJRMaCkaocX0CWGpTEUbJm4T120veRI1t1Vbz0X7mJbkeSsfn
MXlCHroA9SgMws7tbwzneaqKEPeOZ9BLsi0ulg5WMNgUeF25DWS7zFbRRPUOGlKF
pnyn/w7p32Me8PBJ118eA2ji6eSPciqNVXIQFLFZONLh1AgLjy61E8KzEzZpdHYJ
txHG47lCRPV7yQZ5RbcL1vcqn9jGNV6E++vGNH/Gcyu+EXN24VJUkOVToLedX/bL
wvZakHHBAKW8b7Y3raED5VpN0If8pgkTl2Wd/qJ/vfMkIwomLRhOtlDze/+UqDv1
0QynmM7dkDSyqdTuY0gr00undun3/U/CW/5ReufE0KwFabwzW9vz5cW3TCceXIhH
E1JvFxW5+Y6wH8kNM1sggDQr23vZ7ITkVQn1m8ooPwA0QGFCJ5yHFEY+eKkeqZMv
oijL1vrr0lSPFFzL4Rs6ApHbhxn3x3UrBQO82d18qbp8QezN9vbmTF4EmaTw1NCs
mlJ9F3d4+3vb6ME000kba6qLE6y+czjrAsW5t9Y1hQW3kUqC4CPlIQPBiA4CBPqT
BuhYEUScs6IMh9z86Ry2Tz6XnQbEwciPdPVGyZUPf8f+HCumqfTBsaAUt3ICrrTY
sxU5j3laWA==
=rtEg
-----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmrOQJYACgkQmmx57+YA
GNkKrw/+MOk02KXNJHymjGRYo16YMatA4ObQPjXcCZcNmNsMpYwH3WeyLELUmL2L
mTA9P9Cih/4mANOdFv9qaC7tkhZAVvpQwF8SCRJE4ARuIkG3UEb3D65kkPXwnLnx
on1P19/ViTkzxMj7TZwomv8yoZHl0eIFIXmYiY3/N4AFGcZczX22wdVwBEINwocw
12SuaBBYxIalGDzJeoNVxwoLEdUHdKL9lfAHS/lynObw6vJfXJBIckJWWB21h0KJ
6gNLGjlH7wwtBHGO3BhUZlDcQzm3wy751LO8PfeL8ECkkOPb7X5jRmCUsrwXcxPu
xuFYIXMZRAC+8NP2FODRaTD/HQOnPPdT0x+IJ5tL5K6pw3A1YYK8oh5zlGPNh+lN
Iq1+pJB6M4AHjQkzpoJOAN8Tol89VO3UnG1B9fWer2vA2B3jxfSPpbzzfNz2oiPq
4fcOgACrmGA1IAUS4PzBecmDOOGHtpX2oMW9yrLMTvOMUxlBksx+mqWE6YTvrPAC
ynhzVL2NTIV6j9A5CMDVOhrb6DrztL6I2bpsP1NeGewUSD8TB/1O3vhF5CMg12WK
0Qx5P9oescRK+7RjohQ3a4/1xIZFmBGCIsXlkjHuqisJeuz3icIG9x+1xpt2VkZF
13nF863CvazfYPeFCSuMEnkTUjNfshFyh0EASTt+PumTSAswTeM=
=BcV3
-----END PGP SIGNATURE-----
Merge tag 'memory-controller-drv-7.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers
Memory controller drivers for v7.4
1. Broadcom DPFE: Fix handling kernel memory accesses with malicious or
compromised firmware and possible out-of-bounds read triggered by
buggy co-processor. Also validate firmware image contents before
processing it.
2. Renesas RPC IF: One fix for volatile register access, several
cleanups and enable autosuspend in runtime PM.
3. Several minor improvements and fixes for various drivers: TI EMIF,
Samsung Exynos5422 DMC, Nvidia Tegra264 and STM32 OMM. The fixes
seems to be effect of LLM usage, thus they were neither reproduced
nor tested, making them non-critical fixes.
4. Mediatek SMI: Add support for MT8189 SoC.
* tag 'memory-controller-drv-7.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
memory: stm32_omm: fix child clock leak on set_amcr() error path
memory: emif: Remove const from min_tck allocation type
memory: mtk-smi: Add MT8189 support
dt-bindings: memory-controllers: mtk-smi: Add support for mt8189
memory: emif: fix device_node reference leak on np_ddr
memory: tegra: Refactor Tegra264 mc-err code
memory: tegra: Parameterise Tegra264 MCF slice bound
memory: tegra: Use named defines for Tegra264 MC apertures
memory: exynos5422-dmc: handle clock enable failures
memory: emif: Replace __ASSEMBLY__ with __ASSEMBLER__ in non-uapi headers
memory: brcmstb_dpfe: validate firmware section sizes
memory: renesas-rpc-if: Use runtime PM autosuspend after transfers
memory: renesas-rpc-if: Consolidate command setup register programming
memory: renesas-rpc-if: Consolidate XSPI_CDTBUF0 updates in read path
memory: renesas-rpc-if: Consolidate XSPI_CDTBUF0 updates in write path
memory: renesas-rpc-if: Move static bridge configurations out of dirmap hot paths
memory: renesas-rpc-if: Mark XSPI_CDD1BUF0 as volatile
memory: brcmstb_dpfe: Bounds check DCPU-supplied MSG_ARG_COUNT
memory: brcmstb_dpfe: Fix out-of-bounds access due to DCPU offset
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
2699c4615e
|
|
@ -16,7 +16,7 @@ description: |
|
|||
MediaTek SMI have two generations of HW architecture, here is the list
|
||||
which generation the SoCs use:
|
||||
generation 1: mt2701 and mt7623.
|
||||
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192 and mt8195.
|
||||
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8189, mt8192 and mt8195.
|
||||
|
||||
There's slight differences between the two SMI, for generation 2, the
|
||||
register which control the iommu port is at each larb's register base. But
|
||||
|
|
@ -25,6 +25,21 @@ description: |
|
|||
SMI generation 1 to transform the smi clock into emi clock domain, but that is
|
||||
not needed for SMI generation 2.
|
||||
|
||||
The smi-common connects with smi-larb and IOMMU. The maximum inputs number of
|
||||
a smi-common is 8. In SMI generation 2, the engines number may be over 8.
|
||||
In this case, we use a smi-sub-common to merge some larbs.
|
||||
The block diagram something is like:
|
||||
|
||||
IOMMU
|
||||
| |
|
||||
smi-common
|
||||
---------------------------
|
||||
| | ...
|
||||
larb0 sub-common ... <-max number is 8
|
||||
----------------
|
||||
| | ...
|
||||
larb1 larbX ... <-max number is 8
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
|
|
@ -40,6 +55,8 @@ properties:
|
|||
- mediatek,mt8186-smi-common
|
||||
- mediatek,mt8188-smi-common-vdo
|
||||
- mediatek,mt8188-smi-common-vpp
|
||||
- mediatek,mt8189-smi-common
|
||||
- mediatek,mt8189-smi-sub-common
|
||||
- mediatek,mt8192-smi-common
|
||||
- mediatek,mt8195-smi-common-vdo
|
||||
- mediatek,mt8195-smi-common-vpp
|
||||
|
|
@ -108,6 +125,7 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- mediatek,mt8189-smi-sub-common
|
||||
- mediatek,mt8195-smi-sub-common
|
||||
then:
|
||||
required:
|
||||
|
|
@ -157,6 +175,7 @@ allOf:
|
|||
- mediatek,mt6795-smi-common
|
||||
- mediatek,mt8167-smi-common
|
||||
- mediatek,mt8173-smi-common
|
||||
- mediatek,mt8189-smi-common
|
||||
|
||||
then:
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ properties:
|
|||
- mediatek,mt8183-smi-larb
|
||||
- mediatek,mt8186-smi-larb
|
||||
- mediatek,mt8188-smi-larb
|
||||
- mediatek,mt8189-smi-larb
|
||||
- mediatek,mt8192-smi-larb
|
||||
- mediatek,mt8195-smi-larb
|
||||
|
||||
|
|
@ -85,6 +86,7 @@ allOf:
|
|||
- mediatek,mt8183-smi-larb
|
||||
- mediatek,mt8186-smi-larb
|
||||
- mediatek,mt8188-smi-larb
|
||||
- mediatek,mt8189-smi-larb
|
||||
- mediatek,mt8195-smi-larb
|
||||
|
||||
then:
|
||||
|
|
@ -119,6 +121,7 @@ allOf:
|
|||
- mediatek,mt6779-smi-larb
|
||||
- mediatek,mt8186-smi-larb
|
||||
- mediatek,mt8188-smi-larb
|
||||
- mediatek,mt8189-smi-larb
|
||||
- mediatek,mt8192-smi-larb
|
||||
- mediatek,mt8195-smi-larb
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ struct brcmstb_dpfe_priv {
|
|||
void __iomem *regs;
|
||||
void __iomem *dmem;
|
||||
void __iomem *imem;
|
||||
resource_size_t regs_size;
|
||||
resource_size_t dmem_size;
|
||||
struct device *dev;
|
||||
const struct dpfe_api *dpfe_api;
|
||||
struct mutex lock;
|
||||
|
|
@ -401,9 +403,14 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
|
|||
*/
|
||||
switch (msg_type) {
|
||||
case 1:
|
||||
if (DCPU_MSG_RAM_START + offset + DRAM_VENDOR_ERROR +
|
||||
sizeof(u32) > priv->regs_size)
|
||||
goto bad_offset;
|
||||
ptr = priv->regs + DCPU_MSG_RAM_START + offset;
|
||||
break;
|
||||
case 0:
|
||||
if (offset + DRAM_VENDOR_ERROR + sizeof(u32) > priv->dmem_size)
|
||||
goto bad_offset;
|
||||
ptr = priv->dmem + offset;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -415,6 +422,12 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
|
|||
}
|
||||
|
||||
return ptr;
|
||||
|
||||
bad_offset:
|
||||
dev_err(priv->dev, "DCPU returned out-of-range offset %#x\n", offset);
|
||||
if (buf && size)
|
||||
*size = sprintf(buf, "ERROR: DCPU offset out of range\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __finalize_command(struct brcmstb_dpfe_priv *priv)
|
||||
|
|
@ -490,6 +503,8 @@ static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
|
|||
for (i = 0; i < MSG_FIELD_MAX; i++)
|
||||
result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
|
||||
chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
|
||||
if (chksum_idx >= MSG_FIELD_MAX)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Tell DCPU we are done */
|
||||
|
|
@ -518,9 +533,15 @@ static int __verify_firmware(struct init_data *init,
|
|||
const struct firmware *fw)
|
||||
{
|
||||
const struct dpfe_firmware_header *header = (void *)fw->data;
|
||||
unsigned int dmem_size, imem_size, total_size;
|
||||
unsigned int dmem_size, imem_size;
|
||||
bool is_big_endian = false;
|
||||
const u32 *chksum_ptr;
|
||||
size_t payload_size;
|
||||
|
||||
if (fw->size < sizeof(*header) + sizeof(*chksum_ptr))
|
||||
return ERR_INVALID_SIZE;
|
||||
|
||||
payload_size = fw->size - sizeof(*header) - sizeof(*chksum_ptr);
|
||||
|
||||
if (header->magic == DPFE_BE_MAGIC)
|
||||
is_big_endian = true;
|
||||
|
|
@ -539,13 +560,8 @@ static int __verify_firmware(struct init_data *init,
|
|||
if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0)
|
||||
return ERR_INVALID_SIZE;
|
||||
|
||||
/*
|
||||
* The header + the data section + the instruction section + the
|
||||
* checksum must be equal to the total firmware size.
|
||||
*/
|
||||
total_size = dmem_size + imem_size + sizeof(*header) +
|
||||
sizeof(*chksum_ptr);
|
||||
if (total_size != fw->size)
|
||||
/* The data and instruction sections must fill the payload exactly. */
|
||||
if (dmem_size > payload_size || imem_size != payload_size - dmem_size)
|
||||
return ERR_INVALID_SIZE;
|
||||
|
||||
/* The checksum comes at the very end. */
|
||||
|
|
@ -858,6 +874,7 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct brcmstb_dpfe_priv *priv;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
|
@ -869,17 +886,21 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
|
|||
mutex_init(&priv->lock);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->regs = devm_platform_ioremap_resource_byname(pdev, "dpfe-cpu");
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu");
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "couldn't map DCPU registers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
priv->regs_size = resource_size(res);
|
||||
|
||||
priv->dmem = devm_platform_ioremap_resource_byname(pdev, "dpfe-dmem");
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-dmem");
|
||||
priv->dmem = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->dmem)) {
|
||||
dev_err(dev, "Couldn't map DCPU data memory\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
priv->dmem_size = resource_size(res);
|
||||
|
||||
priv->imem = devm_platform_ioremap_resource_byname(pdev, "dpfe-imem");
|
||||
if (IS_ERR(priv->imem)) {
|
||||
|
|
|
|||
|
|
@ -922,6 +922,7 @@ static struct emif_data *of_get_memory_device_details(
|
|||
if (!emif || !pd || !dev_info) {
|
||||
dev_err(dev, "%s: Out of memory!!\n",
|
||||
__func__);
|
||||
of_node_put(np_ddr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -946,6 +947,7 @@ static struct emif_data *of_get_memory_device_details(
|
|||
pd->device_info->io_width, pd->phy_type, pd->ip_rev,
|
||||
emif->dev)) {
|
||||
dev_err(dev, "%s: invalid device data!!\n", __func__);
|
||||
of_node_put(np_ddr);
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
|
|
@ -1062,7 +1064,8 @@ static struct emif_data *get_device_details(
|
|||
}
|
||||
|
||||
if (pd->min_tck) {
|
||||
temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL);
|
||||
temp = devm_kzalloc(dev, sizeof(struct lpddr2_min_tck),
|
||||
GFP_KERNEL);
|
||||
if (temp) {
|
||||
memcpy(temp, pd->min_tck, sizeof(*pd->min_tck));
|
||||
pd->min_tck = temp;
|
||||
|
|
@ -1140,6 +1143,7 @@ static void emif_remove(struct platform_device *pdev)
|
|||
struct emif_data *emif = platform_get_drvdata(pdev);
|
||||
|
||||
emif_debugfs_exit(emif);
|
||||
of_node_put(emif->np_ddr);
|
||||
}
|
||||
|
||||
static void emif_shutdown(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@
|
|||
#define EMIF_SRAM_AM33_REG_LAYOUT 0x00000000
|
||||
#define EMIF_SRAM_AM43_REG_LAYOUT 0x00000001
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
/*
|
||||
* Structure containing shadow of important registers in EMIF
|
||||
* The calculation function fills in this structure to be later used for
|
||||
|
|
@ -603,5 +603,5 @@ void ti_emif_enter_sr(void);
|
|||
void ti_emif_exit_sr(void);
|
||||
void ti_emif_abort_sr(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* __EMIF_H */
|
||||
|
|
|
|||
|
|
@ -401,6 +401,30 @@ static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
|||
[25] = {0x01},
|
||||
};
|
||||
|
||||
static const u8 mtk_smi_larb_mt8189_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||
[0] = {0x8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,},
|
||||
[1] = {0x8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,},
|
||||
[2] = {0x7, 0x7, 0x4, 0x4, 0x1, 0x1, 0x2, 0x2, 0x7, 0x7,},
|
||||
[4] = {0x2f, 0x1e, 0x9, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x5, 0x1, 0x17,},
|
||||
[7] = {0x20, 0x2, 0x1, 0x1, 0x1, 0x4, 0x2, 0x1, 0x1, 0x2, 0x3, 0x2,
|
||||
0xa, 0xf, 0x4, 0x6, 0x5, 0x1,},
|
||||
[9] = {0x6, 0x3, 0xc, 0x6, 0x1, 0x4, 0x3, 0x1, 0x2, 0x4, 0x5, 0x2,
|
||||
0x4, 0x2, 0x3, 0xb, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||
0x1, 0x1,},
|
||||
[11] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||
0x1, 0x1, 0x1, 0xb, 0x1, 0x4, 0x6, 0x5, 0x6, 0x1, 0x5, 0x2,
|
||||
0x9, 0x5,},
|
||||
[13] = {0x2, 0x8, 0x8, 0x8, 0x4, 0x4, 0x4, 0x4, 0x4, 0xe, 0x4, 0x1,
|
||||
0x6, 0x6, 0x2,},
|
||||
[14] = {0x1, 0x1, 0x1, 0x20, 0xe, 0x4, 0x8, 0x8, 0x6, 0x4,},
|
||||
[16] = {0x1e, 0xc, 0x2, 0x8, 0xe, 0x2, 0x1e, 0x10, 0x4, 0x2, 0x2, 0x2,
|
||||
0x2, 0x2, 0x4, 0x2, 0x4,},
|
||||
[17] = {0x1e, 0xc, 0x2, 0x8, 0xe, 0x2, 0x1e, 0x10, 0x4, 0x2, 0x2, 0x2,
|
||||
0x2, 0x2, 0x4, 0x2, 0x4,},
|
||||
[19] = {0x2, 0x1, 0x3, 0x1,},
|
||||
[20] = {0x7, 0x7, 0x3, 0x3, 0x1, 0x1,},
|
||||
};
|
||||
|
||||
static const u8 mtk_smi_larb_mt8192_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||
[0] = {0x2, 0x2, 0x28, 0xa, 0xc, 0x28,},
|
||||
[1] = {0x2, 0x2, 0x18, 0x18, 0x18, 0xa, 0xc, 0x28,},
|
||||
|
|
@ -533,6 +557,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
|
|||
.ostd = mtk_smi_larb_mt8188_ostd,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8189 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
.flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
|
||||
MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL,
|
||||
.ostd = mtk_smi_larb_mt8189_ostd,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
.ostd = mtk_smi_larb_mt8192_ostd,
|
||||
|
|
@ -556,6 +587,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
|
|||
{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
|
||||
{.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186},
|
||||
{.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188},
|
||||
{.compatible = "mediatek,mt8189-smi-larb", .data = &mtk_smi_larb_mt8189},
|
||||
{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
|
||||
{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
|
||||
{}
|
||||
|
|
@ -808,6 +840,17 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
|
|||
.init = mtk_smi_common_mt8195_init,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8189 = {
|
||||
.type = MTK_SMI_GEN2,
|
||||
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(5) |
|
||||
F_MMU1_LARB(7),
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8189 = {
|
||||
.type = MTK_SMI_GEN2_SUB_COMM,
|
||||
.has_gals = true,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
|
||||
.type = MTK_SMI_GEN2,
|
||||
.has_gals = true,
|
||||
|
|
@ -852,6 +895,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
|
|||
{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
|
||||
{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
|
||||
{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
|
||||
{.compatible = "mediatek,mt8189-smi-common", .data = &mtk_smi_common_mt8189},
|
||||
{.compatible = "mediatek,mt8189-smi-sub-common", .data = &mtk_smi_sub_common_mt8189},
|
||||
{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
|
||||
{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
|
||||
{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ static const struct regmap_access_table rpcif_volatile_table = {
|
|||
|
||||
static const struct regmap_range xspi_volatile_ranges[] = {
|
||||
regmap_reg_range(XSPI_CDD0BUF0, XSPI_CDD0BUF0),
|
||||
regmap_reg_range(XSPI_CDD1BUF0, XSPI_CDD1BUF0),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table xspi_volatile_table = {
|
||||
|
|
@ -311,6 +312,14 @@ static int xspi_hw_init_impl(struct rpcif_priv *xspi, bool hyperflash)
|
|||
regmap_update_bits(xspi->regmap, XSPI_INTE, XSPI_INTE_CMDCMPE,
|
||||
XSPI_INTE_CMDCMPE);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL0,
|
||||
XSPI_BMCTL0_CS0ACC(0xff), XSPI_BMCTL0_CS0ACC(0x03));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCFG,
|
||||
XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB |
|
||||
XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN,
|
||||
0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) |
|
||||
XSPI_BMCFG_PREEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -627,18 +636,14 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi)
|
|||
u32 pos = 0, max = 8;
|
||||
int ret = 0;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRNUM(0x3),
|
||||
/* Clear transaction number and request */
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0,
|
||||
XSPI_CDCTL0_TRNUM(0x3) | XSPI_CDCTL0_TRREQ,
|
||||
XSPI_CDCTL0_TRNUM(0));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRREQ, 0);
|
||||
|
||||
regmap_write(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_CMDSIZE(0x1) | XSPI_CDTBUF_CMD_FIELD(xspi->command));
|
||||
|
||||
regmap_write(xspi->regmap, XSPI_CDABUF0, 0);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, XSPI_CDTBUF_ADDSIZE(0x7),
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
XSPI_CDTBUF_CMDSIZE(0x1) | XSPI_CDTBUF_CMD_FIELD(xspi->command) |
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
|
||||
regmap_write(xspi->regmap, XSPI_CDABUF0, xspi->smadr);
|
||||
|
||||
|
|
@ -651,17 +656,12 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi)
|
|||
u32 bytes_left = xspi->xferlen - pos;
|
||||
u32 nbytes, data[2], *p = data;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_TRTYPE, XSPI_CDTBUF_TRTYPE);
|
||||
|
||||
nbytes = bytes_left >= max ? max : bytes_left;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_DATASIZE(0xf),
|
||||
XSPI_CDTBUF_DATASIZE(nbytes));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_TRTYPE | XSPI_CDTBUF_DATASIZE(0xf) |
|
||||
XSPI_CDTBUF_ADDSIZE(0x7),
|
||||
XSPI_CDTBUF_TRTYPE | XSPI_CDTBUF_DATASIZE(nbytes) |
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
|
||||
memcpy(data, xspi->buffer + pos, nbytes);
|
||||
|
|
@ -693,30 +693,33 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi)
|
|||
while (pos < xspi->xferlen) {
|
||||
u32 bytes_left = xspi->xferlen - pos;
|
||||
u32 nbytes, data[2], *p = data;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_TRTYPE,
|
||||
~(u32)XSPI_CDTBUF_TRTYPE);
|
||||
u32 cdtbuf0_mask, cdtbuf0_val;
|
||||
|
||||
/* nbytes can be up to 8 bytes */
|
||||
nbytes = bytes_left >= max ? max : bytes_left;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_DATASIZE(0xf),
|
||||
XSPI_CDTBUF_DATASIZE(nbytes));
|
||||
/* clear TRTYPE */
|
||||
cdtbuf0_mask = XSPI_CDTBUF_TRTYPE;
|
||||
cdtbuf0_val = 0;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_ADDSIZE(0x7),
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
/* program DATASIZE */
|
||||
cdtbuf0_mask |= XSPI_CDTBUF_DATASIZE(0xf);
|
||||
cdtbuf0_val |= XSPI_CDTBUF_DATASIZE(nbytes);
|
||||
|
||||
/* program ADDSIZE */
|
||||
cdtbuf0_mask |= XSPI_CDTBUF_ADDSIZE(0x7);
|
||||
cdtbuf0_val |= XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes);
|
||||
|
||||
/* program LATE */
|
||||
cdtbuf0_mask |= XSPI_CDTBUF_LATE(0x1f);
|
||||
cdtbuf0_val |= XSPI_CDTBUF_LATE(xspi->dummy);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, cdtbuf0_mask, cdtbuf0_val);
|
||||
|
||||
if (xspi->addr_nbytes)
|
||||
regmap_write(xspi->regmap, XSPI_CDABUF0,
|
||||
xspi->smadr + pos);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_LATE(0x1f),
|
||||
XSPI_CDTBUF_LATE(xspi->dummy));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0,
|
||||
XSPI_CDCTL0_TRREQ, XSPI_CDCTL0_TRREQ);
|
||||
|
||||
|
|
@ -773,7 +776,7 @@ int rpcif_manual_xfer(struct device *dev)
|
|||
|
||||
ret = rpc->info->impl->manual_xfer(rpc);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -868,15 +871,6 @@ static size_t xspi_dirmap_read_impl(struct rpcif_priv *xspi, u64 offs,
|
|||
XSPI_CMCFG1_RDCMD_UPPER_BYTE(xspi->command) |
|
||||
XSPI_CMCFG1_RDLATE(xspi->dummy));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL0, XSPI_BMCTL0_CS0ACC(0xff),
|
||||
XSPI_BMCTL0_CS0ACC(0x01));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCFG,
|
||||
XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB |
|
||||
XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN,
|
||||
0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) |
|
||||
XSPI_BMCFG_PREEN);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_LIOCFGCS0, XSPI_LIOCFG_PRTMD(0x3ff),
|
||||
XSPI_LIOCFG_PRTMD(xspi->proto));
|
||||
|
||||
|
|
@ -897,7 +891,7 @@ ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf)
|
|||
|
||||
read = rpc->info->impl->dirmap_read(rpc, offs, len, buf);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return read;
|
||||
}
|
||||
|
|
@ -944,15 +938,6 @@ ssize_t xspi_dirmap_write(struct device *dev, u64 offs, size_t len, const void *
|
|||
XSPI_CMCFG2_WRCMD_UPPER(xspi->command) |
|
||||
XSPI_CMCFG2_WRLATE(xspi->dummy));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL0,
|
||||
XSPI_BMCTL0_CS0ACC(0xff), XSPI_BMCTL0_CS0ACC(0x03));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCFG,
|
||||
XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB |
|
||||
XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN,
|
||||
0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) |
|
||||
XSPI_BMCFG_PREEN);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_LIOCFGCS0, XSPI_LIOCFG_PRTMD(0x3ff),
|
||||
XSPI_LIOCFG_PRTMD(xspi->proto));
|
||||
|
||||
|
|
@ -963,7 +948,7 @@ ssize_t xspi_dirmap_write(struct device *dev, u64 offs, size_t len, const void *
|
|||
regmap_update_bits(xspi->regmap, XSPI_BMCTL1,
|
||||
XSPI_BMCTL1_MWRPUSH, XSPI_BMCTL1_MWRPUSH);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return writebytes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1297,8 +1297,15 @@ static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_prepare_enable(dmc->fout_bpll);
|
||||
clk_prepare_enable(dmc->mout_bpll);
|
||||
ret = clk_prepare_enable(dmc->fout_bpll);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(dmc->mout_bpll);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(dmc->fout_bpll);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some bootloaders do not set clock routes correctly.
|
||||
|
|
|
|||
|
|
@ -274,6 +274,8 @@ static int stm32_omm_configure(struct device *dev)
|
|||
writel_relaxed(omm->cr, omm->io_base + OMM_CR);
|
||||
|
||||
ret = stm32_omm_set_amcr(dev, true);
|
||||
if (ret && (mux & CR_MUXEN))
|
||||
stm32_omm_toggle_child_clock(dev, false);
|
||||
|
||||
error:
|
||||
pm_runtime_put_sync_suspend(dev);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,47 @@
|
|||
#include "mc.h"
|
||||
#include "tegra264-bwmgr.h"
|
||||
|
||||
/*
|
||||
* Description of a single MCF error type: where to read the status and the
|
||||
* faulting address, how to extract the high address bits, which bits encode
|
||||
* the access direction and security state and the optional error-type sub-code.
|
||||
*/
|
||||
struct tegra264_mc_fault {
|
||||
const char *const *type_names;
|
||||
u32 addr_hi_mask;
|
||||
u32 addr_hi_reg;
|
||||
u32 addr_hi_shift;
|
||||
u32 addr_reg;
|
||||
u32 rw_bit;
|
||||
u32 sec_bit;
|
||||
u32 status1_reg;
|
||||
u32 status_reg;
|
||||
u32 type_mask;
|
||||
u32 type_shift;
|
||||
};
|
||||
|
||||
/*
|
||||
* Maps an MCF interrupt to a callback that fills in the register offsets and
|
||||
* decoding parameters for that error type. The register offsets live in the
|
||||
* per-SoC tegra_mc_regs, so they are collected at runtime rather than being
|
||||
* stored in a static table.
|
||||
*/
|
||||
struct tegra264_mc_error_handler {
|
||||
u32 mask;
|
||||
void (*get_offsets)(struct tegra_mc *mc, struct tegra264_mc_fault *fault);
|
||||
};
|
||||
|
||||
/*
|
||||
* Description of a single HUB error type. addr_reg is zero for error types
|
||||
* that don't latch a fault address.
|
||||
*/
|
||||
struct tegra264_hub_error_handler {
|
||||
u32 addr_hi_reg;
|
||||
u32 addr_reg;
|
||||
u32 mask;
|
||||
u32 status_reg;
|
||||
};
|
||||
|
||||
/*
|
||||
* MC Client entries are sorted in the increasing order of the
|
||||
* override and security register offsets.
|
||||
|
|
@ -717,11 +758,18 @@ static const char *const tegra264_rt_error_names[16] = {
|
|||
};
|
||||
|
||||
/*
|
||||
* MC instance aperture mapping for hubc registers
|
||||
* On Tegra264 the memory controller error interrupts are distributed across
|
||||
* several HUB/HUBC apertures. Each aperture is accessed like a broadcast
|
||||
* channel through mc_ch_readl()/mc_ch_writel() using its fixed index.
|
||||
*/
|
||||
static const int mc_hubc_aperture_number[5] = {
|
||||
7, 8, 9, 10, 11
|
||||
};
|
||||
#define TEGRA264_MC_APERTURE_DISP 7
|
||||
#define TEGRA264_MC_APERTURE_SYSTEM 8
|
||||
#define TEGRA264_MC_APERTURE_VISION 9
|
||||
#define TEGRA264_MC_APERTURE_UPHY 10
|
||||
#define TEGRA264_MC_APERTURE_TOP 11
|
||||
|
||||
/* Tegra264 splits the MCF common interrupt status across five slices. */
|
||||
#define TEGRA264_MC_NUM_SLICES 5
|
||||
|
||||
/*
|
||||
* tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW
|
||||
|
|
@ -807,115 +855,149 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_emem(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_status;
|
||||
fault->addr_reg = mc->soc->regs->err_add;
|
||||
fault->addr_hi_reg = mc->soc->regs->err_add_hi;
|
||||
fault->type_mask = mc->soc->mc_err_status_type_mask;
|
||||
fault->type_shift = MC_ERR_STATUS_TYPE_SHIFT;
|
||||
fault->type_names = tegra264_mc_error_names;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_vpr(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_vpr_status;
|
||||
fault->addr_reg = mc->soc->regs->err_vpr_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_sec(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_sec_status;
|
||||
fault->addr_reg = mc->soc->regs->err_sec_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_mts(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_mts_status;
|
||||
fault->addr_reg = mc->soc->regs->err_mts_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_gsc(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_gen_co_status;
|
||||
fault->status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0;
|
||||
fault->addr_reg = mc->soc->regs->err_gen_co_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_route(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_route_status;
|
||||
fault->addr_reg = mc->soc->regs->err_route_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
fault->rw_bit = MC_ERR_ROUTE_SANITY_RW;
|
||||
fault->sec_bit = MC_ERR_ROUTE_SANITY_SEC;
|
||||
fault->type_mask = MC_ERR_STATUS_RT_TYPE_MASK;
|
||||
fault->type_shift = MC_ERR_STATUS_RT_TYPE_SHIFT;
|
||||
fault->type_names = tegra264_rt_error_names;
|
||||
}
|
||||
|
||||
static const struct tegra264_mc_error_handler tegra264_mc_error_handlers[] = {
|
||||
{ MC_INT_DECERR_EMEM, tegra264_mc_fault_emem },
|
||||
{ MC_INT_SECURITY_VIOLATION, tegra264_mc_fault_emem },
|
||||
{ MC_INT_DECERR_VPR, tegra264_mc_fault_vpr },
|
||||
{ MC_INT_SECERR_SEC, tegra264_mc_fault_sec },
|
||||
{ MC_INT_DECERR_MTS, tegra264_mc_fault_mts },
|
||||
{ MC_INT_DECERR_GENERALIZED_CARVEOUT, tegra264_mc_fault_gsc },
|
||||
{ MC_INT_DECERR_ROUTE_SANITY, tegra264_mc_fault_route },
|
||||
{ MC_INT_DECERR_ROUTE_SANITY_GIC_MSI, tegra264_mc_fault_route },
|
||||
};
|
||||
|
||||
static void tegra264_mc_report_fault(struct tegra_mc *mc, u32 channel,
|
||||
unsigned int interrupt,
|
||||
const struct tegra264_mc_fault *fault)
|
||||
{
|
||||
const char *client = "unknown", *desc = "NA";
|
||||
u32 value, client_id, status1 = 0;
|
||||
phys_addr_t addr = 0;
|
||||
unsigned int i;
|
||||
u8 type;
|
||||
|
||||
value = mc_ch_readl(mc, channel, fault->status_reg);
|
||||
|
||||
if (fault->addr_hi_reg) {
|
||||
addr = mc_ch_readl(mc, channel, fault->addr_hi_reg);
|
||||
} else if (fault->status1_reg) {
|
||||
status1 = mc_ch_readl(mc, channel, fault->status1_reg);
|
||||
addr = (status1 >> fault->addr_hi_shift) & fault->addr_hi_mask;
|
||||
} else {
|
||||
addr = (value >> fault->addr_hi_shift) & fault->addr_hi_mask;
|
||||
}
|
||||
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, channel, fault->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 (fault->type_names) {
|
||||
type = (value & fault->type_mask) >> fault->type_shift;
|
||||
desc = fault->type_names[type];
|
||||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n",
|
||||
client, value & fault->sec_bit ? "secure" : "non-secure",
|
||||
value & fault->rw_bit ? "write" : "read", &addr,
|
||||
tegra_mc_status_names[interrupt] ?: "unknown", desc);
|
||||
|
||||
if (fault->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);
|
||||
}
|
||||
|
||||
static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus)
|
||||
{
|
||||
unsigned int bit;
|
||||
unsigned int interrupt;
|
||||
|
||||
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;
|
||||
for_each_set_bit(interrupt, &mcf_ch_intstatus, 32) {
|
||||
const struct tegra264_mc_error_handler *handler = NULL;
|
||||
struct tegra264_mc_fault fault = {
|
||||
.rw_bit = MC_ERR_STATUS_RW,
|
||||
.sec_bit = MC_ERR_STATUS_SECURITY,
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
for (i = 0; i < ARRAY_SIZE(tegra264_mc_error_handlers); i++) {
|
||||
if (tegra264_mc_error_handlers[i].mask == BIT(interrupt)) {
|
||||
handler = &tegra264_mc_error_handlers[i];
|
||||
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];
|
||||
if (!handler) {
|
||||
dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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));
|
||||
handler->get_offsets(mc, &fault);
|
||||
tegra264_mc_report_fault(mc, channel, interrupt, &fault);
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
|
|
@ -937,7 +1019,7 @@ static irqreturn_t handle_mcf_irq(int irq, void *data)
|
|||
|
||||
for_each_set_bit(slice, &common_intstat, 32) {
|
||||
/* Find out the slice number on which interrupt occurred */
|
||||
if (slice > 4) {
|
||||
if (slice >= TEGRA264_MC_NUM_SLICES) {
|
||||
dev_err(mc->dev, "Slice index out of bounds: %u\n", slice);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
|
@ -950,53 +1032,69 @@ static irqreturn_t handle_mcf_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct tegra264_hub_error_handler tegra264_hub_error_handlers[] = {
|
||||
{
|
||||
.mask = MSS_HUB_COALESCER_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_COALESCE_ERR_STATUS_0,
|
||||
.addr_reg = MSS_HUB_COALESCE_ERR_ADR_0,
|
||||
.addr_hi_reg = MSS_HUB_COALESCE_ERR_ADR_HI_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK,
|
||||
.status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_MSI_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_MSI_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_POISON_RSP_INTMASK,
|
||||
.status_reg = MSS_HUB_POISON_RSP_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_RESERVED_PA_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0,
|
||||
},
|
||||
};
|
||||
|
||||
static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat)
|
||||
{
|
||||
unsigned int bit;
|
||||
unsigned int interrupt;
|
||||
|
||||
for_each_set_bit(bit, &hub_intstat, 32) {
|
||||
for_each_set_bit(interrupt, &hub_intstat, 32) {
|
||||
const struct tegra264_hub_error_handler *handler = NULL;
|
||||
const char *client = "unknown";
|
||||
u32 client_id, status_reg, value, i;
|
||||
u32 client_id, value;
|
||||
phys_addr_t addr = 0;
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
for (i = 0; i < ARRAY_SIZE(tegra264_hub_error_handlers); i++) {
|
||||
if (tegra264_hub_error_handlers[i].mask == BIT(interrupt)) {
|
||||
handler = &tegra264_hub_error_handlers[i];
|
||||
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:
|
||||
if (!handler) {
|
||||
dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, hub, status_reg);
|
||||
if (handler->addr_reg) {
|
||||
addr = mc_ch_readl(mc, hub, handler->addr_hi_reg);
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, hub, handler->addr_reg);
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, hub, handler->status_reg);
|
||||
|
||||
client_id = value & mc->soc->client_id_mask;
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
|
|
@ -1007,8 +1105,8 @@ static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intsta
|
|||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n",
|
||||
client, &addr, tegra264_hub_error_names[bit] ?: "unknown",
|
||||
value);
|
||||
client, &addr,
|
||||
tegra264_hub_error_names[interrupt] ?: "unknown", value);
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
|
|
@ -1057,27 +1155,27 @@ static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_numb
|
|||
|
||||
static irqreturn_t handle_disp_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_DISP);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_system_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_SYSTEM);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_vision_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_VISION);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_uphy_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_UPHY);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_top_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_TOP);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user