From 22ced26b1a7edc044952d685792b7d63d9bbae94 Mon Sep 17 00:00:00 2001 From: Kartik Date: Wed, 24 Apr 2024 10:50:01 +0530 Subject: [PATCH] NVIDIA: SAUCE: soc/tegra: fuse: Add tegra_fuse_control_read BugLink: https://bugs.launchpad.net/bugs/2080908 Currently, tegra_fuse_readl() only supports reading fuse offsets >= 0x100. The driver do not support reading fuse registers that have offset < 0x100. Introduce tegra_fuse_control_read() to allow reading fuse offsets < 0x100. http://nvbugs/4648782 Signed-off-by: Kartik Tested-by: Petlozu Pravareshwar Signed-off-by: Laxman Dewangan Acked-by: Noah Wager Acked-by: Jacob Martin Signed-off-by: Noah Wager --- drivers/soc/tegra/fuse/fuse-tegra.c | 14 ++++++++++++++ drivers/soc/tegra/fuse/fuse-tegra30.c | 17 +++++++++++++++++ drivers/soc/tegra/fuse/fuse.h | 3 ++- include/soc/tegra/fuse.h | 1 + 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 98805885158e..c7543c2f0091 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -290,6 +290,20 @@ int tegra_fuse_readl(unsigned long offset, u32 *value) } EXPORT_SYMBOL(tegra_fuse_readl); +int tegra_fuse_control_read(unsigned long offset, u32 *value) +{ + if (!fuse->read || !fuse->clk) + return -EPROBE_DEFER; + + if (IS_ERR(fuse->clk)) + return PTR_ERR(fuse->clk); + + *value = fuse->control_read(fuse, offset); + + return 0; +} +EXPORT_SYMBOL(tegra_fuse_control_read); + static void tegra_enable_fuse_clk(void __iomem *base) { u32 reg; diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index e94d46372a63..c03771281b0b 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -63,6 +63,22 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset) return value; } +static u32 tegra30_fuse_control_read(struct tegra_fuse *fuse, unsigned int offset) +{ + u32 value; + int err; + + err = pm_runtime_resume_and_get(fuse->dev); + if (err) + return 0; + + value = readl_relaxed(fuse->base + offset); + + pm_runtime_put(fuse->dev); + + return value; +} + static void __init tegra30_fuse_add_randomness(void) { u32 randomness[12]; @@ -89,6 +105,7 @@ static void __init tegra30_fuse_init(struct tegra_fuse *fuse) { fuse->read_early = tegra30_fuse_read_early; fuse->read = tegra30_fuse_read; + fuse->control_read = tegra30_fuse_control_read; tegra_init_revision(); diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index 90f23be73894..25bccf7887a1 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2024, NVIDIA CORPORATION. All rights reserved. * * Author: * Colin Cross @@ -51,6 +51,7 @@ struct tegra_fuse { u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset); u32 (*read)(struct tegra_fuse *fuse, unsigned int offset); + u32 (*control_read)(struct tegra_fuse *fuse, unsigned int offset); const struct tegra_fuse_soc *soc; /* APBDMA on Tegra20 */ diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 3a513be50243..47d44187a020 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -70,6 +70,7 @@ extern struct tegra_sku_info tegra_sku_info; u32 tegra_read_straps(void); u32 tegra_read_ram_code(void); int tegra_fuse_readl(unsigned long offset, u32 *value); +int tegra_fuse_control_read(unsigned long offset, u32 *value); u32 tegra_read_chipid(void); u8 tegra_get_chip_id(void); u8 tegra_get_platform(void);