2023-10-17 05:24:16

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 0/8] soc/tegra: fuse: Add ACPI support

This series of patches add ACPI support for Tegra194 and Tegra234 in
Tegra fuse and apbmisc drivers. It also adds support for Tegra241
which uses ACPI boot.

Kartik (8):
mm/util: Introduce kmemdup_array()
soc/tegra: fuse: Use dev_err_probe for probe failures
soc/tegra: fuse: Refactor resource mapping
soc/tegra: fuse: Add tegra_acpi_init_apbmisc()
soc/tegra: fuse: Add function to add lookups
soc/tegra: fuse: Add function to print SKU info
soc/tegra: fuse: Add ACPI support for Tegra194 and Tegra234
soc/tegra: fuse: Add support for Tegra241

drivers/soc/tegra/Kconfig | 5 ++
drivers/soc/tegra/fuse/fuse-tegra.c | 112 ++++++++++++++++++-------
drivers/soc/tegra/fuse/fuse-tegra30.c | 20 +++++
drivers/soc/tegra/fuse/fuse.h | 5 ++
drivers/soc/tegra/fuse/tegra-apbmisc.c | 110 ++++++++++++++++++++----
include/linux/string.h | 1 +
include/soc/tegra/fuse.h | 1 +
mm/util.c | 17 ++++
8 files changed, 227 insertions(+), 44 deletions(-)

---
v3 -> v4:
* Added following patch to introduce kmemdup_array:
"mm/util: Introduce kmemdup_array() to duplicate an array"
* Add "soc/tegra: fuse: Use dev_err_probe for probe failures".
v2 -> v3:
* Minor changes in following patches:
soc/tegra: fuse: Add tegra_acpi_init_apbmisc()
soc/tegra: fuse: Add ACPI support for Tegra194 and Tegra234

v1 -> v2:
* Used '--patience' while formatting patches.
* Added "soc/tegra: fuse: Refactor resource mapping" to share
the common code between tegra_init_apbmisc() and
tegra_acpi_init_apbmisc() functions.
* Dropped "soc/tegra: fuse: Add function to register nvmem"
as ACPI and device-tree boot are sharing the same probe.
So, no need to refactor the code here.
---
--
2.34.1


2023-10-17 05:24:35

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 1/8] mm/util: Introduce kmemdup_array()

Introduce kmemdup_array() API to duplicate `n` number of elements
from a given array. This internally uses kmemdup to allocate and duplicate
the `src` array.

Signed-off-by: Kartik <[email protected]>
Acked-by: Kees Cook <[email protected]>
---
v4 -> v5:
* Simplify the implementation by just returning kmemdup(size_mul).
---
include/linux/string.h | 1 +
mm/util.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 3c920b6d609b..fcfa1062c79b 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -180,6 +180,7 @@ extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
extern void *kmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
+extern void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp);

extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
extern void argv_free(char **argv);
diff --git a/mm/util.c b/mm/util.c
index 6eddd891198e..8801446140d6 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -135,6 +135,23 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
}
EXPORT_SYMBOL(kmemdup);

+/**
+ * kmemdup_array - duplicate a given array.
+ *
+ * @src: array to duplicate.
+ * @element_size: size of each element of array.
+ * @count: number of elements to duplicate from array.
+ * @gfp: GFP mask to use.
+ *
+ * Return: duplicated array of @src or %NULL in case of error,
+ * result is physically contiguous. Use kfree() to free.
+ */
+void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp)
+{
+ return kmemdup(src, size_mul(element_size, count), gfp);
+}
+EXPORT_SYMBOL(kmemdup_array);
+
/**
* kvmemdup - duplicate region of memory
*
--
2.34.1

2023-10-17 05:24:41

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 2/8] soc/tegra: fuse: Use dev_err_probe for probe failures

Currently, in tegra_fuse_probe() if clock/reset get fails, then the
driver prints an error if the error is not caused by -EPROBE_DEFER.
This can be improved by using dev_err_probe() instead.

So, return dev_err_probe() if clock/reset get fails.

Signed-off-by: Kartik <[email protected]>
---
drivers/soc/tegra/fuse/fuse-tegra.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index a2c28f493a75..98805885158e 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -131,13 +131,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
fuse->phys = res->start;

fuse->clk = devm_clk_get(&pdev->dev, "fuse");
- if (IS_ERR(fuse->clk)) {
- if (PTR_ERR(fuse->clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
- PTR_ERR(fuse->clk));
-
- return PTR_ERR(fuse->clk);
- }
+ if (IS_ERR(fuse->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(fuse->clk), "failed to get FUSE clock\n");

platform_set_drvdata(pdev, fuse);
fuse->dev = &pdev->dev;
@@ -179,12 +174,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
}

fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse");
- if (IS_ERR(fuse->rst)) {
- err = PTR_ERR(fuse->rst);
- dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
- fuse->rst);
- return err;
- }
+ if (IS_ERR(fuse->rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(fuse->rst), "failed to get FUSE reset\n");

/*
* FUSE clock is enabled at a boot time, hence this resume/suspend
--
2.34.1

2023-10-17 05:24:53

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 4/8] soc/tegra: fuse: Add tegra_acpi_init_apbmisc()

In preparation to ACPI support in Tegra fuse driver add function
tegra_acpi_init_apbmisc() to initialize tegra-apbmisc driver.
Also, document the reason of calling tegra_init_apbmisc() at early init.

Note that function tegra_acpi_init_apbmisc() is not placed in the __init
section, because it will be called during probe.

Signed-off-by: Kartik <[email protected]>
---
v3 -> v6:
* Use resource_list_for_each_entry() instead of
resource_list_for_each_entry_safe().
v2 -> v3:
* Fix build warnings seen when CONFIG_ACPI is disabled by moving
tegra_init_apbmisc table inside #ifdef CONFIG_ACPI block.

v1 -> v2:
* Update ACPI ID table 'tegra_init_apbmisc'.
* Add comment to document the reason to call tegra_init_apbmisc
at early init.
* Fix an issue where acpi_dev_free_resource_list() and
* acpi_dev_put() were not called if
acpi_dev_get_memory_resources() returned 1.
* Update logic to fetch memory resources in
tegra_acpi_init_apbmisc().
* Fix build errors seen when CONFIG_ACPI is disabled.
---
drivers/soc/tegra/fuse/fuse.h | 1 +
drivers/soc/tegra/fuse/tegra-apbmisc.c | 72 ++++++++++++++++++++++++++
2 files changed, 73 insertions(+)

diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index 90f23be73894..a41e9f85281a 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -69,6 +69,7 @@ struct tegra_fuse {

void tegra_init_revision(void);
void tegra_init_apbmisc(void);
+void tegra_acpi_init_apbmisc(void);

u32 __init tegra_fuse_read_spare(unsigned int spare);
u32 __init tegra_fuse_read_early(unsigned int offset);
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 06c1b3a2c7ec..6457f80821bb 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -3,9 +3,11 @@
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
*/

+#include <linux/acpi.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/of_address.h>

@@ -180,6 +182,12 @@ static void tegra_init_apbmisc_resources(struct resource *apbmisc,
}
}

+/**
+ * tegra_init_apbmisc - Initializes Tegra APBMISC and Strapping registers.
+ *
+ * This is called during early init as some of the old 32-bit ARM code needs
+ * information from the APBMISC registers very early during boot.
+ */
void __init tegra_init_apbmisc(void)
{
struct resource apbmisc, straps;
@@ -244,3 +252,67 @@ void __init tegra_init_apbmisc(void)
put:
of_node_put(np);
}
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id apbmisc_acpi_match[] = {
+ { "NVDA2010" },
+ { /* sentinel */ }
+};
+
+void tegra_acpi_init_apbmisc(void)
+{
+ struct resource *resources[2] = { NULL };
+ struct resource_entry *rentry;
+ struct acpi_device *adev = NULL;
+ struct list_head resource_list;
+ int rcount = 0;
+ int ret;
+
+ adev = acpi_dev_get_first_match_dev(apbmisc_acpi_match[0].id, NULL, -1);
+ if (!adev)
+ return;
+
+ INIT_LIST_HEAD(&resource_list);
+
+ ret = acpi_dev_get_memory_resources(adev, &resource_list);
+ if (ret < 0) {
+ pr_err("failed to get APBMISC memory resources");
+ goto out_put_acpi_dev;
+ }
+
+ /*
+ * Get required memory resources.
+ *
+ * resources[0]: apbmisc.
+ * resources[1]: straps.
+ */
+ resource_list_for_each_entry(rentry, &resource_list) {
+ if (rcount >= ARRAY_SIZE(resources))
+ break;
+
+ resources[rcount++] = rentry->res;
+ }
+
+ if (!resources[0]) {
+ pr_err("failed to get APBMISC registers\n");
+ goto out_free_resource_list;
+ }
+
+ if (!resources[1]) {
+ pr_err("failed to get strapping options registers\n");
+ goto out_free_resource_list;
+ }
+
+ tegra_init_apbmisc_resources(resources[0], resources[1]);
+
+out_free_resource_list:
+ acpi_dev_free_resource_list(&resource_list);
+
+out_put_acpi_dev:
+ acpi_dev_put(adev);
+}
+#else
+void tegra_acpi_init_apbmisc(void)
+{
+}
+#endif
--
2.34.1

2023-10-17 05:24:56

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 3/8] soc/tegra: fuse: Refactor resource mapping

To prepare for adding ACPI support to the tegra-apbmisc driver,
relocate the code responsible for mapping memory resources from
the function ‘tegra_init_apbmisc’ to the function
‘tegra_init_apbmisc_resources.’ This adjustment will allow the
code to be shared between ‘tegra_init_apbmisc’ and the upcoming
‘tegra_acpi_init_apbmisc’ function.

Signed-off-by: Kartik <[email protected]>
---
drivers/soc/tegra/fuse/tegra-apbmisc.c | 37 +++++++++++++++-----------
1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index da970f3dbf35..06c1b3a2c7ec 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -160,9 +160,28 @@ void __init tegra_init_revision(void)
tegra_sku_info.platform = tegra_get_platform();
}

-void __init tegra_init_apbmisc(void)
+static void tegra_init_apbmisc_resources(struct resource *apbmisc,
+ struct resource *straps)
{
void __iomem *strapping_base;
+
+ apbmisc_base = ioremap(apbmisc->start, resource_size(apbmisc));
+ if (apbmisc_base)
+ chipid = readl_relaxed(apbmisc_base + 4);
+ else
+ pr_err("failed to map APBMISC registers\n");
+
+ strapping_base = ioremap(straps->start, resource_size(straps));
+ if (strapping_base) {
+ strapping = readl_relaxed(strapping_base);
+ iounmap(strapping_base);
+ } else {
+ pr_err("failed to map strapping options registers\n");
+ }
+}
+
+void __init tegra_init_apbmisc(void)
+{
struct resource apbmisc, straps;
struct device_node *np;

@@ -219,21 +238,7 @@ void __init tegra_init_apbmisc(void)
}
}

- apbmisc_base = ioremap(apbmisc.start, resource_size(&apbmisc));
- if (!apbmisc_base) {
- pr_err("failed to map APBMISC registers\n");
- } else {
- chipid = readl_relaxed(apbmisc_base + 4);
- }
-
- strapping_base = ioremap(straps.start, resource_size(&straps));
- if (!strapping_base) {
- pr_err("failed to map strapping options registers\n");
- } else {
- strapping = readl_relaxed(strapping_base);
- iounmap(strapping_base);
- }
-
+ tegra_init_apbmisc_resources(&apbmisc, &straps);
long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");

put:
--
2.34.1

2023-10-17 05:25:01

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 6/8] soc/tegra: fuse: Add function to print SKU info

Add helper function tegra_fuse_print_sku_info() to print Tegra SKU
information. So, it can be shared between tegra_fuse_init() and
ACPI probe which is to be introduced later.

Signed-off-by: Kartik <[email protected]>
---
v1 -> v2:
* Renamed tegra_fuse_pr_sku_info() as
tegra_fuse_print_sku_info().
---
drivers/soc/tegra/fuse/fuse-tegra.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index 4ebb5597a77b..7a93c6512f7b 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -113,6 +113,16 @@ static void tegra_fuse_restore(void *base)
fuse->clk = NULL;
}

+static void tegra_fuse_print_sku_info(struct tegra_sku_info *tegra_sku_info)
+{
+ pr_info("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n",
+ tegra_revision_name[tegra_sku_info->revision],
+ tegra_sku_info->sku_id, tegra_sku_info->cpu_process_id,
+ tegra_sku_info->soc_process_id);
+ pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
+ tegra_sku_info->cpu_speedo_id, tegra_sku_info->soc_speedo_id);
+}
+
static int tegra_fuse_add_lookups(struct tegra_fuse *fuse)
{
fuse->lookups = kmemdup_array(fuse->soc->lookups, sizeof(*fuse->lookups),
@@ -501,12 +511,7 @@ static int __init tegra_init_fuse(void)

fuse->soc->init(fuse);

- pr_info("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n",
- tegra_revision_name[tegra_sku_info.revision],
- tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id,
- tegra_sku_info.soc_process_id);
- pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
- tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
+ tegra_fuse_print_sku_info(&tegra_sku_info);

err = tegra_fuse_add_lookups(fuse);
if (err)
--
2.34.1

2023-10-17 05:25:14

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 5/8] soc/tegra: fuse: Add function to add lookups

Add helper function tegra_fuse_add_lookups() to register Tegra fuse
nvmem lookups. So, this can be shared between tegra_fuse_init() and
ACPI probe, which is to be introduced later.

Use kmemdup_array to duplicate fuse->soc->lookups.

Signed-off-by: Kartik <[email protected]>
---
v3 -> v4:
* Use kmemdup_array to duplicate fuse->soc->lookups.
* Return err at the end of tegra_fuse_probe to remove
redundant code.
v1 -> v2:
* Use size_mul to calculate lookups array size.
---
drivers/soc/tegra/fuse/fuse-tegra.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index 98805885158e..4ebb5597a77b 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -113,6 +113,18 @@ static void tegra_fuse_restore(void *base)
fuse->clk = NULL;
}

+static int tegra_fuse_add_lookups(struct tegra_fuse *fuse)
+{
+ fuse->lookups = kmemdup_array(fuse->soc->lookups, sizeof(*fuse->lookups),
+ fuse->soc->num_lookups, GFP_KERNEL);
+ if (!fuse->lookups)
+ return -ENOMEM;
+
+ nvmem_add_cell_lookups(fuse->lookups, fuse->soc->num_lookups);
+
+ return 0;
+}
+
static int tegra_fuse_probe(struct platform_device *pdev)
{
void __iomem *base = fuse->base;
@@ -398,6 +410,7 @@ static int __init tegra_init_fuse(void)
const struct of_device_id *match;
struct device_node *np;
struct resource regs;
+ int err;

tegra_init_apbmisc();

@@ -495,15 +508,11 @@ static int __init tegra_init_fuse(void)
pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);

- if (fuse->soc->lookups) {
- size_t size = sizeof(*fuse->lookups) * fuse->soc->num_lookups;
+ err = tegra_fuse_add_lookups(fuse);
+ if (err)
+ pr_err("failed to add FUSE lookups\n");

- fuse->lookups = kmemdup(fuse->soc->lookups, size, GFP_KERNEL);
- if (fuse->lookups)
- nvmem_add_cell_lookups(fuse->lookups, fuse->soc->num_lookups);
- }
-
- return 0;
+ return err;
}
early_initcall(tegra_init_fuse);

--
2.34.1

2023-10-17 05:25:14

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 7/8] soc/tegra: fuse: Add ACPI support for Tegra194 and Tegra234

Add ACPI support for Tegra194 & Tegra243 SoC's. This requires
following modifications to the probe when ACPI boot is used:
- Initialize soc data.
- Add nvmem lookups.
- Register soc device.
- use devm_clk_get_optional() instead of devm_clk_get() to get
fuse->clk, as fuse clocks are not required when using ACPI boot.

Also, drop '__init' keyword for tegra_soc_device_register() as this is also
used by tegra_fuse_probe() and use dev_err_probe() wherever applicable.

Signed-off-by: Kartik <[email protected]>
---
v5 -> v7:
* Drop __maybe_unused and ACPI_PTR() for tegra_fuse_acpi_match.
v4 -> v5:
* Fix build warnings seen with tegra_fuse_acpi_match when
CONFIG_ACPI is disabled.
v3 -> v4:
* Use dev_fwnode() to dereference the fwnode.
* Add MODULE_DEVICE_TABLE for tegra_fuse_acpi_match.
* Moved tegra_fuse_acpi_match above tegra_fuse_driver i.e.,
close to the user of tegra_fuse_acpi_match.
* Moved the improvements made to fuse clk/rst get error handling
to separate patch.
* Moved ACPI related initialization after fuse->base is
initialized in tegra_fuse_probe(), as this triggers a warning
in tegra_fuse_read_early() which is called from
fuse->soc->init().
v2 -> v3:
* Updated commit message to specify changes related to inclusion
of dev_err_probe().

v1 -> v2:
* Updated ACPI ID table 'tegra_fuse_acpi_match'.
* Removed ',' after "{ /* sentinel */ }" in
'tegra_fuse_acpi_match'.
* Using same probe for ACPI and device-tree boot.
* Added code for required initialization when ACPI boot is used.
* Make clocks optional for ACPI.
* Use dev_err_probe() wherever applicable.
* Check if clock has been initialized only when device-tree
boot is used.
---
drivers/soc/tegra/fuse/fuse-tegra.c | 52 +++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index 7a93c6512f7b..1c758f121f91 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -3,11 +3,13 @@
* Copyright (c) 2013-2023, NVIDIA CORPORATION. All rights reserved.
*/

+#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/mod_devicetable.h>
#include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
@@ -152,7 +154,38 @@ static int tegra_fuse_probe(struct platform_device *pdev)
return PTR_ERR(fuse->base);
fuse->phys = res->start;

- fuse->clk = devm_clk_get(&pdev->dev, "fuse");
+ /* Initialize the soc data and lookups if using ACPI boot. */
+ if (is_acpi_node(dev_fwnode(&pdev->dev)) && !fuse->soc) {
+ u8 chip;
+
+ tegra_acpi_init_apbmisc();
+
+ chip = tegra_get_chip_id();
+ switch (chip) {
+#if defined(CONFIG_ARCH_TEGRA_194_SOC)
+ case TEGRA194:
+ fuse->soc = &tegra194_fuse_soc;
+ break;
+#endif
+#if defined(CONFIG_ARCH_TEGRA_234_SOC)
+ case TEGRA234:
+ fuse->soc = &tegra234_fuse_soc;
+ break;
+#endif
+ default:
+ return dev_err_probe(&pdev->dev, -EINVAL, "Unsupported SoC: %02x\n", chip);
+ }
+
+ fuse->soc->init(fuse);
+ tegra_fuse_print_sku_info(&tegra_sku_info);
+ tegra_soc_device_register();
+
+ err = tegra_fuse_add_lookups(fuse);
+ if (err)
+ return dev_err_probe(&pdev->dev, err, "failed to add FUSE lookups\n");
+ }
+
+ fuse->clk = devm_clk_get_optional(&pdev->dev, "fuse");
if (IS_ERR(fuse->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(fuse->clk), "failed to get FUSE clock\n");

@@ -275,10 +308,17 @@ static const struct dev_pm_ops tegra_fuse_pm = {
SET_SYSTEM_SLEEP_PM_OPS(tegra_fuse_suspend, tegra_fuse_resume)
};

+static const struct acpi_device_id tegra_fuse_acpi_match[] = {
+ { "NVDA200F" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, tegra_fuse_acpi_match);
+
static struct platform_driver tegra_fuse_driver = {
.driver = {
.name = "tegra-fuse",
.of_match_table = tegra_fuse_match,
+ .acpi_match_table = tegra_fuse_acpi_match,
.pm = &tegra_fuse_pm,
.suppress_bind_attrs = true,
},
@@ -300,7 +340,13 @@ u32 __init tegra_fuse_read_early(unsigned int offset)

int tegra_fuse_readl(unsigned long offset, u32 *value)
{
- if (!fuse->read || !fuse->clk)
+ /*
+ * Wait for fuse->clk to be initialized if device-tree boot is used.
+ */
+ if (is_of_node(dev_fwnode(fuse->dev)) && !fuse->clk)
+ return -EPROBE_DEFER;
+
+ if (!fuse->read)
return -EPROBE_DEFER;

if (IS_ERR(fuse->clk))
@@ -383,7 +429,7 @@ const struct attribute_group tegra194_soc_attr_group = {
};
#endif

-struct device * __init tegra_soc_device_register(void)
+struct device *tegra_soc_device_register(void)
{
struct soc_device_attribute *attr;
struct soc_device *dev;
--
2.34.1

2023-10-17 05:25:20

by Kartik Rajput

[permalink] [raw]
Subject: [PATCH v7 8/8] soc/tegra: fuse: Add support for Tegra241

Add support for Tegra241 which use ACPI boot.

Signed-off-by: Kartik <[email protected]>
---
v1 -> v2:
* Removed few entries from tegra241_fuse_soc which were
initilized as NULL or 0.
---
drivers/soc/tegra/Kconfig | 5 +++++
drivers/soc/tegra/fuse/fuse-tegra.c | 5 +++++
drivers/soc/tegra/fuse/fuse-tegra30.c | 20 ++++++++++++++++++++
drivers/soc/tegra/fuse/fuse.h | 4 ++++
drivers/soc/tegra/fuse/tegra-apbmisc.c | 1 +
include/soc/tegra/fuse.h | 1 +
6 files changed, 36 insertions(+)

diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index f16beeabaa92..33512558af9f 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -133,6 +133,11 @@ config ARCH_TEGRA_234_SOC
help
Enable support for the NVIDIA Tegra234 SoC.

+config ARCH_TEGRA_241_SOC
+ bool "NVIDIA Tegra241 SoC"
+ help
+ Enable support for the NVIDIA Tegra241 SoC.
+
endif
endif

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index 1c758f121f91..233b8e7bb41b 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -171,6 +171,11 @@ static int tegra_fuse_probe(struct platform_device *pdev)
case TEGRA234:
fuse->soc = &tegra234_fuse_soc;
break;
+#endif
+#if defined(CONFIG_ARCH_TEGRA_241_SOC)
+ case TEGRA241:
+ fuse->soc = &tegra241_fuse_soc;
+ break;
#endif
default:
return dev_err_probe(&pdev->dev, -EINVAL, "Unsupported SoC: %02x\n", chip);
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index e94d46372a63..2070d36c510d 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -678,3 +678,23 @@ const struct tegra_fuse_soc tegra234_fuse_soc = {
.clk_suspend_on = false,
};
#endif
+
+#if defined(CONFIG_ARCH_TEGRA_241_SOC)
+static const struct tegra_fuse_info tegra241_fuse_info = {
+ .read = tegra30_fuse_read,
+ .size = 0x16008,
+ .spare = 0xcf0,
+};
+
+static const struct nvmem_keepout tegra241_fuse_keepouts[] = {
+ { .start = 0xc, .end = 0x1600c }
+};
+
+const struct tegra_fuse_soc tegra241_fuse_soc = {
+ .init = tegra30_fuse_init,
+ .info = &tegra241_fuse_info,
+ .keepouts = tegra241_fuse_keepouts,
+ .num_keepouts = ARRAY_SIZE(tegra241_fuse_keepouts),
+ .soc_attr_group = &tegra194_soc_attr_group,
+};
+#endif
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index a41e9f85281a..f3b705327c20 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -136,4 +136,8 @@ extern const struct tegra_fuse_soc tegra194_fuse_soc;
extern const struct tegra_fuse_soc tegra234_fuse_soc;
#endif

+#ifdef CONFIG_ARCH_TEGRA_241_SOC
+extern const struct tegra_fuse_soc tegra241_fuse_soc;
+#endif
+
#endif
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 6457f80821bb..e2ca5d55fd31 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -64,6 +64,7 @@ bool tegra_is_silicon(void)
switch (tegra_get_chip_id()) {
case TEGRA194:
case TEGRA234:
+ case TEGRA241:
case TEGRA264:
if (tegra_get_platform() == 0)
return true;
diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h
index 3a513be50243..8f421b9f7585 100644
--- a/include/soc/tegra/fuse.h
+++ b/include/soc/tegra/fuse.h
@@ -17,6 +17,7 @@
#define TEGRA186 0x18
#define TEGRA194 0x19
#define TEGRA234 0x23
+#define TEGRA241 0x24
#define TEGRA264 0x26

#define TEGRA_FUSE_SKU_CALIB_0 0xf0
--
2.34.1

2023-12-14 17:08:50

by Thierry Reding

[permalink] [raw]
Subject: Re: [PATCH v7 0/8] soc/tegra: fuse: Add ACPI support

On Tue, Oct 17, 2023 at 10:53:14AM +0530, Kartik wrote:
> This series of patches add ACPI support for Tegra194 and Tegra234 in
> Tegra fuse and apbmisc drivers. It also adds support for Tegra241
> which uses ACPI boot.
>
> Kartik (8):
> mm/util: Introduce kmemdup_array()
> soc/tegra: fuse: Use dev_err_probe for probe failures
> soc/tegra: fuse: Refactor resource mapping
> soc/tegra: fuse: Add tegra_acpi_init_apbmisc()
> soc/tegra: fuse: Add function to add lookups
> soc/tegra: fuse: Add function to print SKU info
> soc/tegra: fuse: Add ACPI support for Tegra194 and Tegra234
> soc/tegra: fuse: Add support for Tegra241
>
> drivers/soc/tegra/Kconfig | 5 ++
> drivers/soc/tegra/fuse/fuse-tegra.c | 112 ++++++++++++++++++-------
> drivers/soc/tegra/fuse/fuse-tegra30.c | 20 +++++
> drivers/soc/tegra/fuse/fuse.h | 5 ++
> drivers/soc/tegra/fuse/tegra-apbmisc.c | 110 ++++++++++++++++++++----
> include/linux/string.h | 1 +
> include/soc/tegra/fuse.h | 1 +
> mm/util.c | 17 ++++
> 8 files changed, 227 insertions(+), 44 deletions(-)

Applied, thanks.

Thierry


Attachments:
(No filename) (1.18 kB)
signature.asc (849.00 B)
Download all attachments

2023-12-15 07:32:29

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v7 0/8] soc/tegra: fuse: Add ACPI support

On Thu, Dec 14, 2023, at 17:08, Thierry Reding wrote:
> On Tue, Oct 17, 2023 at 10:53:14AM +0530, Kartik wrote:
>> This series of patches add ACPI support for Tegra194 and Tegra234 in
>> Tegra fuse and apbmisc drivers. It also adds support for Tegra241
>> which uses ACPI boot.
>
> Applied, thanks.

I'm still a bit puzzled by this series, can you provide some more background?

Why does an ACPI based system require access to SoC drivers? Shouldn't
this all be abstracted by the BIOS in some form so the device drivers
can work standalone rather than calling into this driver?

Arnd

2023-12-15 16:44:03

by Thierry Reding

[permalink] [raw]
Subject: Re: [PATCH v7 0/8] soc/tegra: fuse: Add ACPI support

On Thu, Dec 14, 2023 at 06:43:47PM +0000, Arnd Bergmann wrote:
> On Thu, Dec 14, 2023, at 17:08, Thierry Reding wrote:
> > On Tue, Oct 17, 2023 at 10:53:14AM +0530, Kartik wrote:
> >> This series of patches add ACPI support for Tegra194 and Tegra234 in
> >> Tegra fuse and apbmisc drivers. It also adds support for Tegra241
> >> which uses ACPI boot.
> >
> > Applied, thanks.
>
> I'm still a bit puzzled by this series, can you provide some more background?
>
> Why does an ACPI based system require access to SoC drivers? Shouldn't
> this all be abstracted by the BIOS in some form so the device drivers
> can work standalone rather than calling into this driver?

This driver exposes a couple of things such as SoC family and SKU
information that is not otherwise available. It also exposes FUSE
data which can be used to calibrate certain devices. Most of the
region that contains the fuses is in the keep-out, so perhaps they
aren't needed on Tegra241.

I suppose things like SoC family and such could be exposed differently.
Not sure if ACPI has other ways to expose that.

Let's see if Kartik can shed some light on this.

Thierry


Attachments:
(No filename) (1.14 kB)
signature.asc (849.00 B)
Download all attachments

2023-12-18 10:46:56

by Kartik Rajput

[permalink] [raw]
Subject: Re: [PATCH v7 0/8] soc/tegra: fuse: Add ACPI support

On Fri, 2023-12-15 at 17:43 +0100, Thierry Reding wrote
> On Thu, Dec 14, 2023 at 06:43:47PM +0000, Arnd Bergmann wrote:
> > On Thu, Dec 14, 2023, at 17:08, Thierry Reding wrote:
> > > On Tue, Oct 17, 2023 at 10:53:14AM +0530, Kartik wrote:
> > >> This series of patches add ACPI support for Tegra194 and Tegra234 in
> > >> Tegra fuse and apbmisc drivers. It also adds support for Tegra241
> > >> which uses ACPI boot.
> > >
> > > Applied, thanks.
> >
> > I'm still a bit puzzled by this series, can you provide some more background?
> >
> > Why does an ACPI based system require access to SoC drivers? Shouldn't
> > this all be abstracted by the BIOS in some form so the device drivers
> > can work standalone rather than calling into this driver?
>
> This driver exposes a couple of things such as SoC family and SKU
> information that is not otherwise available. It also exposes FUSE
> data which can be used to calibrate certain devices. Most of the
> region that contains the fuses is in the keep-out, so perhaps they
> aren't needed on Tegra241.
>
> I suppose things like SoC family and such could be exposed differently.
> Not sure if ACPI has other ways to expose that.
>
> Let's see if Kartik can shed some light on this.
>
> Thierry

Hi Thierry, Arnd,

Although the keep-out contains most of the FUSE region. The driver still
expose FUSE data with tegra_fuse_readl(), which can be used by drivers to
get the required calibration data. Hence the reason to add ACPI support.

The keep-out region is only used by nvmem interface, which allows reading the
FUSE data from userspace as well as kernel modules. Currently on Tegra241,
there are no users needing this information via nvmem interface.

Regards,
Kartik