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