From 9cf1f30f0a0d86d14b7366094af5fa87b5a76e5b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 22 Jun 2023 12:34:49 +0000 Subject: [PATCH] NVIDIA: SAUCE: platform: tegra: Add tegra prod as built-in driver BugLink: https://bugs.launchpad.net/bugs/2080908 This is an integration squash change of below commits. - [INTG: NV INTERNAL] platform: tegra: Add tegra prod as built-in - [INTG: NV INTERNAL] platform: tegra: Add tegra prod framework - [INTG: NV INTERNAL] platform: tegra: Add support for mask with 1s - [INTG: NV INTERNAL] platform: tegra_prod: Use kmemleak_not_leak for allocated memory - [INTG: NV INTERNAL] platform: tegra_prod: Fix prod setting parsing for package/board - [INTG: NV INTERNAL] platform: tegra_prod: Use proper variable name - [INTG: NV INTERNAL] platform: tegra_prod: Use for_each_available_child_of_node() - [INTG: NV INTERNAL] platform: tegra: move struct tegra_prod_list to private - [INTG: NV INTERNAL] platform: tegra_prod: Add APIs to managed allocation of prod_list - [INTG: NV INTERNAL] platform: tegra_prod: Remove unused APIs from public header - [INTG: NV INTERNAL] platform: tegra_prod: Get rid of tegra_prod_release() - [INTG: NV INTERNAL] platform: tegra_prod: Add support for nested prod nodes - [INTG: NV INTERNAL] platform: tegra_prod: Add devm_tegra_prod_get_from_node() - [INTG: NV INTERNAL] platform: tegra_prod: use devm_ for allocation - [INTG: NV INTERNAL] platform: tegra_prod: Do not use kmemleak_not_leak() - [INTG: NV INTERNAL] platform: tegra: Add support to find prod setting - [INTG: NV INTERNAL] platform: tegra: APIs to set prod based on name/index/offset/mask - [INTG: NV INTERNAL] prod: Add support for masked write in partially prod config - [INTG: NV INTERNAL] platform: tegra_prod: Use strcasecmp() for prod name - [INTG: NV INTERNAL] prod: set prod-settings mask to 1-style default - [INTG: NV INTERNAL] platform: tegra_prod: add support to avoid multiple configruation - soc: tegra: Add prod configuration parser - prod: remove package and board specific prod node - platform: tegra: Add config for next generation tegra prod - tegra-prod: Add legacy and next gen prod based on config - tegra-prod: Fix missing last entry - tegra-prod: Fix null pointer error - tegra-prod: Fix null pointer error - tegra: prod: remove new prod settings support http://nvbugs/4165866 http://nvbugs/200416207 http://nvbugs/1758682 http://nvbugs/1745386 http://nvbugs/1768583 http://nvbugs/200217343 http://nvbugs/200215286 http://nvbugs/1807581 http://nvbugs/1865456 http://nvbugs/4097475 http://nvbugs/3389584 http://nvbugs/4638219 http://nvbugs/4283554 http://nvbugs/4765671 http://nvbugs/4754882 Signed-off-by: Laxman Dewangan Signed-off-by: Petlozu Pravareshwar Acked-by: Noah Wager Acked-by: Jacob Martin Signed-off-by: Noah Wager --- drivers/platform/Makefile | 1 + drivers/platform/tegra/Kconfig | 24 ++ drivers/platform/tegra/Makefile | 3 + drivers/platform/tegra/tegra_prod.c | 620 ++++++++++++++++++++++++++++ include/linux/tegra_prod.h | 126 ++++++ 5 files changed, 774 insertions(+) create mode 100644 drivers/platform/tegra/Kconfig create mode 100644 drivers/platform/tegra/Makefile create mode 100644 drivers/platform/tegra/tegra_prod.c create mode 100644 include/linux/tegra_prod.h diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 19ac54648586..720ca35166bd 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -12,4 +12,5 @@ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/ obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ +obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/ diff --git a/drivers/platform/tegra/Kconfig b/drivers/platform/tegra/Kconfig new file mode 100644 index 000000000000..ba9ae5dda38e --- /dev/null +++ b/drivers/platform/tegra/Kconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Tegra Platform Specific Drivers +# + +menuconfig TEGRA_PLATFORM_DEVICES + bool "Tegra Platform Specific Device Drivers" + default y + help + Say Y here to get to see options for device drivers of various + Tegra platforms. This option itself does not add any kernel code. + + If you say N, all options in this submenu will be skipped and + disabled. + +if TEGRA_PLATFORM_DEVICES + +config TEGRA_PROD_LEGACY + def_bool y + help + This config helps client driver to identify whether prod + framework is implemented as legacy method or not. + +endif # TEGRA_PLATFORM_DEVICES diff --git a/drivers/platform/tegra/Makefile b/drivers/platform/tegra/Makefile new file mode 100644 index 000000000000..1168e8988349 --- /dev/null +++ b/drivers/platform/tegra/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_TEGRA_PROD_LEGACY) += tegra_prod.o diff --git a/drivers/platform/tegra/tegra_prod.c b/drivers/platform/tegra/tegra_prod.c new file mode 100644 index 000000000000..19aa893df939 --- /dev/null +++ b/drivers/platform/tegra/tegra_prod.c @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PROD_TUPLE_NUM (sizeof(struct prod_tuple)/sizeof(u32)) + +/* tegra_prod: Tegra Prod list for the given submodule + * @n_prod_cells: Number of prod setting cells. + */ +struct tegra_prod { + struct tegra_prod_config *prod_config; + int num; /* number of tegra_prod*/ + int n_prod_cells; +}; + +struct prod_tuple { + u32 index; /* Address base index */ + u32 addr; /* offset address*/ + u32 mask; /* mask */ + u32 val; /* value */ +}; + +struct tegra_prod_config { + const char *name; + struct prod_tuple *prod_tuple; + int count; /* number of prod_tuple*/ + bool boot_init; +}; + +static int tegra_prod_get_child_tupple_count(struct device *dev, + struct device_node *np, + int n_tupple) +{ + struct device_node *child; + int count; + int total_tupple = 0; + + count = of_property_count_u32_elems(np, "prod"); + if (count > 0) { + if ((count < n_tupple) || (count % n_tupple != 0)) { + dev_err(dev, "Node %s has invalid entries\n", np->name); + return -EINVAL; + } + total_tupple = count / n_tupple; + } + + for_each_available_child_of_node(np, child) { + count = tegra_prod_get_child_tupple_count(dev, child, n_tupple); + if (count < 0) + return count; + + total_tupple += count; + } + + return total_tupple; +} + +static int tegra_prod_read_prod_data(struct device *dev, + struct device_node *np, + struct prod_tuple *p_tuple, + int n_tupple) +{ + u32 pval; + int count; + int t_count; + int cnt; + int index; + int ret; + + count = of_property_count_u32_elems(np, "prod"); + if (count <= 0) { + dev_dbg(dev, "Node %s: prod prop not found\n", np->name); + return 0; + } + + t_count = count / n_tupple; + for (cnt = 0; cnt < t_count; cnt++, p_tuple++) { + index = cnt * n_tupple; + + if (n_tupple == 4) { + ret = of_property_read_u32_index(np, "prod", index, + &pval); + if (ret) { + dev_err(dev, "Failed to parse prod of node %s\n", + np->name); + return -EINVAL; + } + + p_tuple->index = pval; + index++; + } else { + p_tuple->index = 0; + } + + ret = of_property_read_u32_index(np, "prod", index, &pval); + if (ret) { + dev_err(dev, "Failed to parse address of node %s\n", + np->name); + return -EINVAL; + } + p_tuple->addr = pval; + index++; + + ret = of_property_read_u32_index(np, "prod", index, &pval); + if (ret) { + dev_err(dev, "Failed to parse mask of node %s\n", + np->name); + return -EINVAL; + } + p_tuple->mask = pval; + index++; + + ret = of_property_read_u32_index(np, "prod", index, &pval); + if (ret) { + dev_err(dev, "Failed to parse value of node %s\n", + np->name); + return -EINVAL; + } + p_tuple->val = pval; + } + + return t_count; +} + +static int tegra_prod_read_node_tupple(struct device *dev, + struct device_node *np, + struct prod_tuple *p_tuple, + int n_tupple) +{ + int ret = 0; + int sindex; + struct device_node *child; + + ret = tegra_prod_read_prod_data(dev, np, p_tuple, n_tupple); + if (ret < 0) + return -EINVAL; + + sindex = ret; + p_tuple += ret; + + for_each_available_child_of_node(np, child) { + ret = tegra_prod_read_node_tupple(dev, child, + p_tuple, n_tupple); + if (ret < 0) + return -EINVAL; + sindex += ret; + p_tuple += ret; + } + + return sindex; +} + +/* Process the tupples and optimise for the register configuration for + * Same location. + */ +static void tegra_prod_optimise_tupple(struct prod_tuple *p_tuple, + int n_tupple) +{ + struct prod_tuple *ti, *tj; + u32 mask; + int i, j; + + for (i = 0; i < n_tupple; ++i) { + ti = p_tuple + i; + for (j = i + 1; j < n_tupple; ++j) { + tj = p_tuple + j; + if (ti->index != tj->index) + continue; + + if (ti->addr != tj->addr) + continue; + + mask = ti->mask & tj->mask; + if (!mask) + continue; + + ti->val &= ~mask; + ti->mask &= ~mask; + } + } +} + +/** + * tegra_prod_parse_dt - Read the prod setting form Device tree. + * @np: device node from which the property value is to be read. + * @np_prod: Prod setting node. + * @tegra_prod: The list of tegra prods. + * + * Read the prod setting form DT according the prod name in tegra prod list. + * prod tuple will be allocated dynamically according to the tuple number of + * each prod in DT. + * + * Returns 0 on success. + */ + +static int tegra_prod_parse_dt(struct device *dev, + const struct device_node *np, + const struct device_node *np_prod, + struct tegra_prod *tegra_prod) +{ + struct device_node *child; + struct tegra_prod_config *t_prod; + struct prod_tuple *p_tuple; + int n_child; + int n_tupple = 3; + int ret; + int count; + u32 pval; + bool mask_opt; + + if (!tegra_prod || !tegra_prod->prod_config) { + dev_err(dev, "Node %s: Invalid tegra prods list.\n", np->name); + return -EINVAL; + }; + + mask_opt = of_property_read_bool(np_prod, "enable-mask-optimisation"); + + ret = of_property_read_u32(np_prod, "#prod-cells", &pval); + if (!ret) + n_tupple = pval; + if ((n_tupple != 3) && (n_tupple != 4)) { + dev_err(dev, "Node %s: Prod cells not supported\n", np->name); + return -EINVAL; + } + tegra_prod->n_prod_cells = n_tupple; + + n_child = 0; + for_each_available_child_of_node(np_prod, child) { + t_prod = &tegra_prod->prod_config[n_child]; + t_prod->name = child->name; + + count = tegra_prod_get_child_tupple_count(dev, child, n_tupple); + if (count < 0) { + dev_err(dev, "Node %s: Child has not proper setting\n", + child->name); + return -EINVAL; + } + + if (!count) { + dev_err(dev, "Node %s: prod prop not found\n", + child->name); + return -EINVAL; + } + + t_prod->count = count; + + t_prod->prod_tuple = devm_kcalloc(dev, t_prod->count, + sizeof(*p_tuple), GFP_KERNEL); + if (!t_prod->prod_tuple) + return -ENOMEM; + + t_prod->boot_init = of_property_read_bool(child, + "nvidia,prod-boot-init"); + + ret = tegra_prod_read_node_tupple(dev, child, + t_prod->prod_tuple, n_tupple); + if (ret < 0) { + dev_err(dev, "Node %s: Reading prod setting failed: %d\n", + child->name, ret); + return ret; + } + if (t_prod->count != ret) { + dev_err(dev, "Node %s: prod read failed: exp %d read %d\n", + child->name, t_prod->count, ret); + return -EINVAL; + } + + /* Optimise the prod configuration */ + if (mask_opt) + tegra_prod_optimise_tupple(t_prod->prod_tuple, + t_prod->count); + + + n_child++; + } + + tegra_prod->num = n_child; + + return 0; +} + +/** + * tegra_prod_set_tuple - Only set a tuple. + * @base: base address of the register. + * @prod_tuple: the tuple to set. + * @new_mask: Mask override value, 0 means use from tupple. + * + * Returns 0 on success. + */ +static int tegra_prod_set_tuple(void __iomem **base, + struct prod_tuple *prod_tuple, + u32 new_mask) +{ + u32 reg; + u32 mask = (new_mask) ? new_mask : prod_tuple->mask; + + if (!prod_tuple) + return -EINVAL; + + reg = readl(base[prod_tuple->index] + prod_tuple->addr); + reg = ((reg & ~mask) | (prod_tuple->val & mask)); + + writel(reg, base[prod_tuple->index] + prod_tuple->addr); + + return 0; +} + +/** + * tegra_prod_set - Set one prod setting. + * @base: base address of the register. + * @tegra_prod: the prod setting to set. + * + * Set all the tuples in one tegra_prod. + * Returns 0 on success. + */ +static int tegra_prod_set(void __iomem **base, + struct tegra_prod_config *tegra_prod) +{ + int i; + int ret; + + if (!tegra_prod) + return -EINVAL; + + for (i = 0; i < tegra_prod->count; i++) { + ret = tegra_prod_set_tuple(base, &tegra_prod->prod_tuple[i], 0); + if (ret) + return ret; + } + + return 0; +} + +/** + * tegra_prod_set_list - Set all the prod settings of the list in sequence. + * @base: base address of the register. + * @tegra_prod: the list of tegra prods. + * + * Returns 0 on success. + */ +int tegra_prod_set_list(void __iomem **base, + struct tegra_prod *tegra_prod) +{ + int i; + int ret; + + if (!tegra_prod) + return -EINVAL; + + for (i = 0; i < tegra_prod->num; i++) { + ret = tegra_prod_set(base, &tegra_prod->prod_config[i]); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(tegra_prod_set_list); + +/** + * tegra_prod_set_boot_init - Set all the prod settings of the list in sequence + * Which are needed for boot initialisation. + * @base: base address of the register. + * @tegra_prod: the list of tegra prods. + * + * Returns 0 on success. + */ +int tegra_prod_set_boot_init(void __iomem **base, + struct tegra_prod *tegra_prod) +{ + int i; + int ret; + + if (!tegra_prod) + return -EINVAL; + + for (i = 0; i < tegra_prod->num; i++) { + if (!tegra_prod->prod_config[i].boot_init) + continue; + ret = tegra_prod_set(base, &tegra_prod->prod_config[i]); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(tegra_prod_set_boot_init); + +/** + * tegra_prod_set_by_name - Set the prod setting according the name. + * @base: base address of the register. + * @name: the name of tegra prod need to set. + * @tegra_prod: the list of tegra prods. + * + * Find the tegra prod in the list according to the name. Then set + * that tegra prod. + * + * Returns 0 on success. + */ +int tegra_prod_set_by_name(void __iomem **base, const char *name, + struct tegra_prod *tegra_prod) +{ + int i; + struct tegra_prod_config *t_prod; + + if (!tegra_prod) + return -EINVAL; + + for (i = 0; i < tegra_prod->num; i++) { + t_prod = &tegra_prod->prod_config[i]; + if (!strcasecmp(t_prod->name, name)) + return tegra_prod_set(base, t_prod); + } + + return -ENODEV; +} +EXPORT_SYMBOL(tegra_prod_set_by_name); + +/** + * tegra_prod_set_by_name_partially - Set the prod setting from list partially + * under given prod name. The matching is done + * qith index, offset and mask. + * @base: base address of the register. + * @name: the name of tegra prod need to set. + * @tegra_prod: the list of tegra prods. + * @index: Index of base address. + * @offset: Offset of the register. + * @mask: Mask field on given register. + * + * Find the tegra prod in the list according to the name. Then set + * that tegra prod which has matching of index, offset and mask. + * + * Returns 0 on success. + */ +int tegra_prod_set_by_name_partially(void __iomem **base, const char *name, + struct tegra_prod *tegra_prod, u32 index, + u32 offset, u32 mask) +{ + struct tegra_prod_config *t_prod; + int ret; + int i; + bool found = false; + + if (!tegra_prod) + return -EINVAL; + + for (i = 0; i < tegra_prod->num; i++) { + t_prod = &tegra_prod->prod_config[i]; + if (!strcasecmp(t_prod->name, name)) { + found = true; + break; + } + } + + if (!found) + return -ENODEV; + + for (i = 0; i < t_prod->count; i++) { + struct prod_tuple *ptuple = &t_prod->prod_tuple[i];; + + if ((ptuple->index != index) || (ptuple->addr != offset) || + ((ptuple->mask & mask) != mask)) + continue; + + ret = tegra_prod_set_tuple(base, ptuple, mask); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(tegra_prod_set_by_name_partially); + +bool tegra_prod_by_name_supported(struct tegra_prod *tegra_prod, + const char *name) +{ + int i; + struct tegra_prod_config *t_prod; + + if (!tegra_prod) + return false; + + for (i = 0; i < tegra_prod->num; i++) { + t_prod = &tegra_prod->prod_config[i]; + if (!t_prod) + break; + + if (!strcasecmp(t_prod->name, name)) + return true; + } + + return false; +} +EXPORT_SYMBOL(tegra_prod_by_name_supported); + +/** + * tegra_prod_init - Init tegra prod list. + # @dev: Device handle. + * @np: device node from which the property value is to be read. + * + * Query all the prod settings under DT node & Init the tegra prod list + * automatically. + * + * Returns 0 on success, -EINVAL for wrong prod number, -ENOMEM if failed + * to allocate memory for tegra prod list. + */ +static struct tegra_prod *tegra_prod_init(struct device *dev, + const struct device_node *np) +{ + struct tegra_prod *tegra_prod; + struct device_node *np_prod; + int prod_num = 0; + int ret; + + np_prod = of_get_child_by_name(np, "prod-settings"); + if (!np_prod) + return ERR_PTR(-ENODEV); + + /* Check whether child is enabled or not */ + if (!of_device_is_available(np_prod)) { + dev_err(dev, "Node %s: Node is not enabled\n", np_prod->name); + return ERR_PTR(-ENODEV); + } + + prod_num = of_get_child_count(np_prod); + if (prod_num <= 0) { + dev_err(dev, "Node %s: No child node for prod settings\n", + np_prod->name); + return ERR_PTR(-ENODEV); + } + + tegra_prod = devm_kzalloc(dev, sizeof(*tegra_prod), GFP_KERNEL); + if (!tegra_prod) + return ERR_PTR(-ENOMEM); + + tegra_prod->prod_config = devm_kcalloc(dev, prod_num, + sizeof(*tegra_prod->prod_config), + GFP_KERNEL); + if (!tegra_prod->prod_config) + return ERR_PTR(-ENOMEM); + + tegra_prod->num = prod_num; + + ret = tegra_prod_parse_dt(dev, np, np_prod, tegra_prod); + if (ret) { + dev_err(dev, "Node %s: Failed to read the Prod Setting.\n", + np->name); + return ERR_PTR(ret); + } + + return tegra_prod; +} + +static void devm_tegra_prod_release(struct device *dev, void *res) +{ +} + +struct tegra_prod *devm_tegra_prod_get(struct device *dev) +{ + struct tegra_prod **ptr, *prod_list; + + ptr = devres_alloc(devm_tegra_prod_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + prod_list = tegra_prod_init(dev, dev->of_node); + if (IS_ERR(prod_list)) { + devres_free(ptr); + return prod_list; + } + + *ptr = prod_list; + devres_add(dev, ptr); + + return prod_list; +} +EXPORT_SYMBOL(devm_tegra_prod_get); + +struct tegra_prod *devm_tegra_prod_get_from_node(struct device *dev, + struct device_node *np) +{ + struct tegra_prod **ptr, *prod_list; + + ptr = devres_alloc(devm_tegra_prod_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + prod_list = tegra_prod_init(dev, np); + if (IS_ERR(prod_list)) { + devres_free(ptr); + return prod_list; + } + + *ptr = prod_list; + devres_add(dev, ptr); + + return prod_list; +} +EXPORT_SYMBOL(devm_tegra_prod_get_from_node); diff --git a/include/linux/tegra_prod.h b/include/linux/tegra_prod.h new file mode 100644 index 000000000000..b69938d504e6 --- /dev/null +++ b/include/linux/tegra_prod.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA_PRODS_H +#define _TEGRA_PRODS_H + +struct tegra_prod; + +/** + * tegra_prod_set_list(): Set all prods configurations + * @base: List of IO mapped registers. + * @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get() + * or tegra_prod_get_from_node(); + * + * Configure all the prod configuration listed on prod-setting nodes. + * + * Returns 0 on success otherwise negive error number for failed case. + */ +int tegra_prod_set_list(void __iomem **base, struct tegra_prod *tegra_prod); + +/** + * tegra_prod_set_boot_init(): Set all prods configurations which has boot init + * flag on the prod setting nodes. + * @base: List of IO mapped registers. + * @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get() + * or tegra_prod_get_from_node(); + * + * Configure all the prod configuration listed on prod-setting nodes. + * + * Returns 0 on success otherwise negive error number for failed case. + */ +int tegra_prod_set_boot_init(void __iomem **base, + struct tegra_prod *tegra_prod); + +/** + * tegra_prod_set_by_name(): Set prod configuration with specific prod name. + * This is used for conditional prod configurations. + * @base: List of IO mapped registers. + * @name: Name of conditional prod which need to be configure. + * @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get() + * or tegra_prod_get_from_node(); + * + * Configure prod configuration with specific prod name for conditional + * prod configurations. + * + * Returns 0 on success otherwise negive error number for failed case. + */ +int tegra_prod_set_by_name(void __iomem **base, const char *name, + struct tegra_prod *tegra_prod); + +/** + * tegra_prod_set_by_name_partially - Set the prod setting from list partially + * under given prod name. The matching is done + * qith index, offset and mask. + * @base: base address of the register. + * @name: the name of tegra prod need to set. + * @tegra_prod: the list of tegra prods. + * @index: Index of base address. + * @offset: Offset of the register. + * @mask: Mask field on given register. + * + * Find the tegra prod in the list according to the name. Then set + * that tegra prod which has matching of index, offset and mask. + * + * Returns 0 on success. + */ +int tegra_prod_set_by_name_partially(void __iomem **base, const char *name, + struct tegra_prod *tegra_prod, u32 index, + u32 offset, u32 mask); + +/** + * tegra_prod_by_name_supported - Tell whether tegra prod will be supported by + * given name or not. + * @tegra_prod: the list of tegra prods. + * @name: the name of tegra prod need to set. + * + * Find the tegra prod in the list according to the name. If it exist then + * return true else false. + */ +bool tegra_prod_by_name_supported(struct tegra_prod *tegra_prod, + const char *name); + +/** + * devm_tegra_prod_get(): Get the prod handle from the device. + * @dev: Device handle on which prod setting nodes are available. + * + * Parse the prod-setting node of the dev->of_node and keep all prod + * setting data in prod handle. + * This handle is used for setting prod configurations. + * + * Returns valid prod_list handle on success or pointer to the error + * when it failed. + */ +struct tegra_prod *devm_tegra_prod_get(struct device *dev); + +/** + * devm_tegra_prod_get_from_node(): Get the prod handle from the node. + * @dev: Device handle. + * @np: Node pointer on which prod setting nodes are available. + * + * Parse the prod-setting node of the node pointer "np" and keep all prod + * setting data in prod handle. + * This handle is used for setting prod configurations. + * + * Returns valid prod_list handle on success or pointer to the error + * when it failed. + * The allocated resource is released by driver core framework when device + * is unbinded and so no need to call any release APIs for the tegra_prod + * handle. + */ +struct tegra_prod *devm_tegra_prod_get_from_node(struct device *dev, + struct device_node *np); +#endif