diff mbox series

memory: tegra: Deduplicate rate request management code

Message ID 20260206-memory-refactor-v1-1-4385d439558a@nvidia.com
State New
Headers show
Series memory: tegra: Deduplicate rate request management code | expand

Commit Message

Mikko Perttunen Feb. 6, 2026, 2:54 a.m. UTC
As is, the EMC drivers for each 32-bit platform contain almost
identical duplicated code for aggregating rate requests. Move this
code out to a shared tegra-emc-common file to reduce duplication.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
This patch is on top of 'memory: tegra: Add Tegra114 EMC driver'
---
 drivers/memory/tegra/Kconfig            |   7 ++
 drivers/memory/tegra/Makefile           |   1 +
 drivers/memory/tegra/tegra-emc-common.c |  96 ++++++++++++++++++++++++++++
 drivers/memory/tegra/tegra-emc-common.h |  38 +++++++++++
 drivers/memory/tegra/tegra114-emc.c     | 107 ++-----------------------------
 drivers/memory/tegra/tegra124-emc.c     | 107 ++-----------------------------
 drivers/memory/tegra/tegra20-emc.c      | 110 ++------------------------------
 drivers/memory/tegra/tegra30-emc.c      | 107 ++-----------------------------
 8 files changed, 167 insertions(+), 406 deletions(-)


---
base-commit: ed4cdcc0b03e72cfdffbff9f0ea24338517bc893
change-id: 20260203-memory-refactor-54a6089a8dcf
prerequisite-message-id: <20260126190755.78475-1-clamor95@gmail.com>
prerequisite-patch-id: d0cc6cf04447264ce099226c9157f1def25df716
prerequisite-patch-id: c57efa588876ea5cf00ea0f28f814ec818bbea58
prerequisite-patch-id: cddf792516ed7582a3cc20eb00ae7745969ff984
prerequisite-patch-id: 9e7e9d889caed5b5deeb60e03b233ffcb0f25724
prerequisite-patch-id: 90ba18fe5154b59da1c7b2db058e93c9f007854e

Comments

Krzysztof Kozlowski Feb. 13, 2026, 10:24 a.m. UTC | #1
On 06/02/2026 03:54, Mikko Perttunen wrote:
> As is, the EMC drivers for each 32-bit platform contain almost
> identical duplicated code for aggregating rate requests. Move this
> code out to a shared tegra-emc-common file to reduce duplication.
> 
> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
> This patch is on top of 'memory: tegra: Add Tegra114 EMC driver'

If that patch is not merged, then this should be reversed. First you
remove duplication then you add smaller new patch. Not vice versa, where
you add duplicated code just to remove it.

> ---
>  drivers/memory/tegra/Kconfig            |   7 ++
>  drivers/memory/tegra/Makefile           |   1 +
>  drivers/memory/tegra/tegra-emc-common.c |  96 ++++++++++++++++++++++++++++
>  drivers/memory/tegra/tegra-emc-common.h |  38 +++++++++++
>  drivers/memory/tegra/tegra114-emc.c     | 107 ++-----------------------------
>  drivers/memory/tegra/tegra124-emc.c     | 107 ++-----------------------------
>  drivers/memory/tegra/tegra20-emc.c      | 110 ++------------------------------
>  drivers/memory/tegra/tegra30-emc.c      | 107 ++-----------------------------
>  8 files changed, 167 insertions(+), 406 deletions(-)
> 
> diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
> index 11e7cc357d39..aeda7f104d34 100644
> --- a/drivers/memory/tegra/Kconfig
> +++ b/drivers/memory/tegra/Kconfig
> @@ -17,6 +17,7 @@ config TEGRA20_EMC
>  	select DEVFREQ_GOV_SIMPLE_ONDEMAND
>  	select PM_DEVFREQ
>  	select DDR
> +	select TEGRA_EMC_COMMON
>  	help
>  	  This driver is for the External Memory Controller (EMC) found on
>  	  Tegra20 chips. The EMC controls the external DRAM on the board.
> @@ -29,6 +30,7 @@ config TEGRA30_EMC
>  	depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
>  	select PM_OPP
>  	select DDR
> +	select TEGRA_EMC_COMMON
>  	help
>  	  This driver is for the External Memory Controller (EMC) found on
>  	  Tegra30 chips. The EMC controls the external DRAM on the board.
> @@ -41,6 +43,7 @@ config TEGRA114_EMC
>  	depends on ARCH_TEGRA_114_SOC || COMPILE_TEST
>  	select TEGRA124_CLK_EMC if ARCH_TEGRA
>  	select PM_OPP
> +	select TEGRA_EMC_COMMON
>  	help
>  	  This driver is for the External Memory Controller (EMC) found on
>  	  Tegra114 chips. The EMC controls the external DRAM on the board.
> @@ -53,6 +56,7 @@ config TEGRA124_EMC
>  	depends on ARCH_TEGRA_124_SOC || COMPILE_TEST
>  	select TEGRA124_CLK_EMC if ARCH_TEGRA
>  	select PM_OPP
> +	select TEGRA_EMC_COMMON
>  	help
>  	  This driver is for the External Memory Controller (EMC) found on
>  	  Tegra124 chips. The EMC controls the external DRAM on the board.
> @@ -73,4 +77,7 @@ config TEGRA210_EMC
>  	  This driver is required to change memory timings / clock rate for
>  	  external memory.
>  
> +config TEGRA_EMC_COMMON
> +	tristate
> +
>  endif
> diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
> index 6b9156de4b66..28f22c957a34 100644
> --- a/drivers/memory/tegra/Makefile
> +++ b/drivers/memory/tegra/Makefile
> @@ -14,6 +14,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
>  
>  obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
>  
> +obj-$(CONFIG_TEGRA_EMC_COMMON) += tegra-emc-common.o
>  obj-$(CONFIG_TEGRA20_EMC)  += tegra20-emc.o
>  obj-$(CONFIG_TEGRA30_EMC)  += tegra30-emc.o
>  obj-$(CONFIG_TEGRA114_EMC) += tegra114-emc.o
> diff --git a/drivers/memory/tegra/tegra-emc-common.c b/drivers/memory/tegra/tegra-emc-common.c
> new file mode 100644
> index 000000000000..9292472a5890
> --- /dev/null
> +++ b/drivers/memory/tegra/tegra-emc-common.c
> @@ -0,0 +1,96 @@
> +// SPDX-License-Identifier: GPL-2.0


... and that's why we ask for consistent license. Code in tegra30-emc
has difference license, so I assume here you copied the one matching
license above. Explain in the commit msg which code you copied or on
which existing code you based this.

> +
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_opp.h>
> +
> +#include "tegra-emc-common.h"
> +

All exported functions need kerneldoc.

> +void tegra_emc_rate_requests_init(struct tegra_emc_rate_requests *reqs,
> +				  struct device *dev)
> +{
> +	unsigned int i;
> +
> +	mutex_init(&reqs->rate_lock);
> +	reqs->dev = dev;
> +
> +	for (i = 0; i < TEGRA_EMC_RATE_TYPE_MAX; i++) {
> +		reqs->requested_rate[i].min_rate = 0;
> +		reqs->requested_rate[i].max_rate = ULONG_MAX;
> +	}
> +}
> +EXPORT_SYMBOL_GPL(tegra_emc_rate_requests_init);
> +

Best regards,
Krzysztof
Mikko Perttunen Feb. 17, 2026, 4:22 a.m. UTC | #2
On Friday, February 13, 2026 7:24 PM Krzysztof Kozlowski wrote:
> On 06/02/2026 03:54, Mikko Perttunen wrote:
> > As is, the EMC drivers for each 32-bit platform contain almost
> > identical duplicated code for aggregating rate requests. Move this
> > code out to a shared tegra-emc-common file to reduce duplication.
> > 
> > Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> > ---
> > This patch is on top of 'memory: tegra: Add Tegra114 EMC driver'
> 
> If that patch is not merged, then this should be reversed. First you
> remove duplication then you add smaller new patch. Not vice versa, where
> you add duplicated code just to remove it.

The code is already duplicated multiple times before. The Tegra114 driver doesn't change the situation in any significant way. Sequencing in this way is just easier rather than disrupting that - more important - series.

> 
> > ---
> >  drivers/memory/tegra/Kconfig            |   7 ++
> >  drivers/memory/tegra/Makefile           |   1 +
> >  drivers/memory/tegra/tegra-emc-common.c |  96 ++++++++++++++++++++++++++++
> >  drivers/memory/tegra/tegra-emc-common.h |  38 +++++++++++
> >  drivers/memory/tegra/tegra114-emc.c     | 107 ++-----------------------------
> >  drivers/memory/tegra/tegra124-emc.c     | 107 ++-----------------------------
> >  drivers/memory/tegra/tegra20-emc.c      | 110 ++------------------------------
> >  drivers/memory/tegra/tegra30-emc.c      | 107 ++-----------------------------
> >  8 files changed, 167 insertions(+), 406 deletions(-)
> > 
> > diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
> > index 11e7cc357d39..aeda7f104d34 100644
> > --- a/drivers/memory/tegra/Kconfig
> > +++ b/drivers/memory/tegra/Kconfig
> > @@ -17,6 +17,7 @@ config TEGRA20_EMC
> >  	select DEVFREQ_GOV_SIMPLE_ONDEMAND
> >  	select PM_DEVFREQ
> >  	select DDR
> > +	select TEGRA_EMC_COMMON
> >  	help
> >  	  This driver is for the External Memory Controller (EMC) found on
> >  	  Tegra20 chips. The EMC controls the external DRAM on the board.
> > @@ -29,6 +30,7 @@ config TEGRA30_EMC
> >  	depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
> >  	select PM_OPP
> >  	select DDR
> > +	select TEGRA_EMC_COMMON
> >  	help
> >  	  This driver is for the External Memory Controller (EMC) found on
> >  	  Tegra30 chips. The EMC controls the external DRAM on the board.
> > @@ -41,6 +43,7 @@ config TEGRA114_EMC
> >  	depends on ARCH_TEGRA_114_SOC || COMPILE_TEST
> >  	select TEGRA124_CLK_EMC if ARCH_TEGRA
> >  	select PM_OPP
> > +	select TEGRA_EMC_COMMON
> >  	help
> >  	  This driver is for the External Memory Controller (EMC) found on
> >  	  Tegra114 chips. The EMC controls the external DRAM on the board.
> > @@ -53,6 +56,7 @@ config TEGRA124_EMC
> >  	depends on ARCH_TEGRA_124_SOC || COMPILE_TEST
> >  	select TEGRA124_CLK_EMC if ARCH_TEGRA
> >  	select PM_OPP
> > +	select TEGRA_EMC_COMMON
> >  	help
> >  	  This driver is for the External Memory Controller (EMC) found on
> >  	  Tegra124 chips. The EMC controls the external DRAM on the board.
> > @@ -73,4 +77,7 @@ config TEGRA210_EMC
> >  	  This driver is required to change memory timings / clock rate for
> >  	  external memory.
> >  
> > +config TEGRA_EMC_COMMON
> > +	tristate
> > +
> >  endif
> > diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
> > index 6b9156de4b66..28f22c957a34 100644
> > --- a/drivers/memory/tegra/Makefile
> > +++ b/drivers/memory/tegra/Makefile
> > @@ -14,6 +14,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
> >  
> >  obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
> >  
> > +obj-$(CONFIG_TEGRA_EMC_COMMON) += tegra-emc-common.o
> >  obj-$(CONFIG_TEGRA20_EMC)  += tegra20-emc.o
> >  obj-$(CONFIG_TEGRA30_EMC)  += tegra30-emc.o
> >  obj-$(CONFIG_TEGRA114_EMC) += tegra114-emc.o
> > diff --git a/drivers/memory/tegra/tegra-emc-common.c b/drivers/memory/tegra/tegra-emc-common.c
> > new file mode 100644
> > index 000000000000..9292472a5890
> > --- /dev/null
> > +++ b/drivers/memory/tegra/tegra-emc-common.c
> > @@ -0,0 +1,96 @@
> > +// SPDX-License-Identifier: GPL-2.0
> 
> 
> ... and that's why we ask for consistent license. Code in tegra30-emc
> has difference license, so I assume here you copied the one matching
> license above. Explain in the commit msg which code you copied or on
> which existing code you based this.

Ok.

> 
> > +
> > +#include <linux/device.h>
> > +#include <linux/mutex.h>
> > +#include <linux/pm_opp.h>
> > +
> > +#include "tegra-emc-common.h"
> > +
> 
> All exported functions need kerneldoc.

Ok.

> 
> > +void tegra_emc_rate_requests_init(struct tegra_emc_rate_requests *reqs,
> > +				  struct device *dev)
> > +{
> > +	unsigned int i;
> > +
> > +	mutex_init(&reqs->rate_lock);
> > +	reqs->dev = dev;
> > +
> > +	for (i = 0; i < TEGRA_EMC_RATE_TYPE_MAX; i++) {
> > +		reqs->requested_rate[i].min_rate = 0;
> > +		reqs->requested_rate[i].max_rate = ULONG_MAX;
> > +	}
> > +}
> > +EXPORT_SYMBOL_GPL(tegra_emc_rate_requests_init);
> > +
> 
> Best regards,
> Krzysztof
>
Krzysztof Kozlowski Feb. 17, 2026, 7:14 a.m. UTC | #3
On 17/02/2026 05:22, Mikko Perttunen wrote:
> On Friday, February 13, 2026 7:24 PM Krzysztof Kozlowski wrote:
>> On 06/02/2026 03:54, Mikko Perttunen wrote:
>>> As is, the EMC drivers for each 32-bit platform contain almost
>>> identical duplicated code for aggregating rate requests. Move this
>>> code out to a shared tegra-emc-common file to reduce duplication.
>>>
>>> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
>>> ---
>>> This patch is on top of 'memory: tegra: Add Tegra114 EMC driver'
>>
>> If that patch is not merged, then this should be reversed. First you
>> remove duplication then you add smaller new patch. Not vice versa, where
>> you add duplicated code just to remove it.
> 
> The code is already duplicated multiple times before. 

That's the meaning of duplication... and adding more duplicated code is
obviously not proper choice.


> The Tegra114 driver doesn't change the situation in any significant way. Sequencing in this way is just easier rather than disrupting that - more important - series.

Fix your email so message will be properly wrapped.

Also in the future, please use normal ways to express dependencies - by
lore links or b4 deps.


Best regards,
Krzysztof
Mikko Perttunen Feb. 17, 2026, 10:12 a.m. UTC | #4
On Tuesday, February 17, 2026 4:14 PM Krzysztof Kozlowski wrote:
> On 17/02/2026 05:22, Mikko Perttunen wrote:
> > On Friday, February 13, 2026 7:24 PM Krzysztof Kozlowski wrote:
> >> On 06/02/2026 03:54, Mikko Perttunen wrote:
> >>> As is, the EMC drivers for each 32-bit platform contain almost
> >>> identical duplicated code for aggregating rate requests. Move this
> >>> code out to a shared tegra-emc-common file to reduce duplication.
> >>> 
> >>> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> >>> ---
> >>> This patch is on top of 'memory: tegra: Add Tegra114 EMC driver'
> >> 
> >> If that patch is not merged, then this should be reversed. First you
> >> remove duplication then you add smaller new patch. Not vice versa, where
> >> you add duplicated code just to remove it.
> > 
> > The code is already duplicated multiple times before.
> 
> That's the meaning of duplication... and adding more duplicated code is
> obviously not proper choice.

I understand you want the cleanup to be done first, and that's fine and you 
decide -- and more duplicated code is obviously not good, but I don't think 
the order these series should go in is obvious. I'm only saying that because 
to me your wording reads as accusing me of making obviously bad arguments, and 
it's not making my day better.

> 
> > The Tegra114 driver doesn't change the situation in any significant way.
> > Sequencing in this way is just easier rather than disrupting that - more
> > important - series.
> Fix your email so message will be properly wrapped.

It seems some update must have overridden my email config. I think I have 
fixed it.

> 
> Also in the future, please use normal ways to express dependencies - by
> lore links or b4 deps.

I did use b4 deps.

> 
> 
> Best regards,
> Krzysztof

Cheers,
Mikko
diff mbox series

Patch

diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
index 11e7cc357d39..aeda7f104d34 100644
--- a/drivers/memory/tegra/Kconfig
+++ b/drivers/memory/tegra/Kconfig
@@ -17,6 +17,7 @@  config TEGRA20_EMC
 	select DEVFREQ_GOV_SIMPLE_ONDEMAND
 	select PM_DEVFREQ
 	select DDR
+	select TEGRA_EMC_COMMON
 	help
 	  This driver is for the External Memory Controller (EMC) found on
 	  Tegra20 chips. The EMC controls the external DRAM on the board.
@@ -29,6 +30,7 @@  config TEGRA30_EMC
 	depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
 	select PM_OPP
 	select DDR
+	select TEGRA_EMC_COMMON
 	help
 	  This driver is for the External Memory Controller (EMC) found on
 	  Tegra30 chips. The EMC controls the external DRAM on the board.
@@ -41,6 +43,7 @@  config TEGRA114_EMC
 	depends on ARCH_TEGRA_114_SOC || COMPILE_TEST
 	select TEGRA124_CLK_EMC if ARCH_TEGRA
 	select PM_OPP
+	select TEGRA_EMC_COMMON
 	help
 	  This driver is for the External Memory Controller (EMC) found on
 	  Tegra114 chips. The EMC controls the external DRAM on the board.
@@ -53,6 +56,7 @@  config TEGRA124_EMC
 	depends on ARCH_TEGRA_124_SOC || COMPILE_TEST
 	select TEGRA124_CLK_EMC if ARCH_TEGRA
 	select PM_OPP
+	select TEGRA_EMC_COMMON
 	help
 	  This driver is for the External Memory Controller (EMC) found on
 	  Tegra124 chips. The EMC controls the external DRAM on the board.
@@ -73,4 +77,7 @@  config TEGRA210_EMC
 	  This driver is required to change memory timings / clock rate for
 	  external memory.
 
+config TEGRA_EMC_COMMON
+	tristate
+
 endif
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index 6b9156de4b66..28f22c957a34 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -14,6 +14,7 @@  tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
 
 obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
 
+obj-$(CONFIG_TEGRA_EMC_COMMON) += tegra-emc-common.o
 obj-$(CONFIG_TEGRA20_EMC)  += tegra20-emc.o
 obj-$(CONFIG_TEGRA30_EMC)  += tegra30-emc.o
 obj-$(CONFIG_TEGRA114_EMC) += tegra114-emc.o
diff --git a/drivers/memory/tegra/tegra-emc-common.c b/drivers/memory/tegra/tegra-emc-common.c
new file mode 100644
index 000000000000..9292472a5890
--- /dev/null
+++ b/drivers/memory/tegra/tegra-emc-common.c
@@ -0,0 +1,96 @@ 
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_opp.h>
+
+#include "tegra-emc-common.h"
+
+void tegra_emc_rate_requests_init(struct tegra_emc_rate_requests *reqs,
+				  struct device *dev)
+{
+	unsigned int i;
+
+	mutex_init(&reqs->rate_lock);
+	reqs->dev = dev;
+
+	for (i = 0; i < TEGRA_EMC_RATE_TYPE_MAX; i++) {
+		reqs->requested_rate[i].min_rate = 0;
+		reqs->requested_rate[i].max_rate = ULONG_MAX;
+	}
+}
+EXPORT_SYMBOL_GPL(tegra_emc_rate_requests_init);
+
+static int tegra_emc_request_rate(struct tegra_emc_rate_requests *reqs,
+				  unsigned long new_min_rate,
+				  unsigned long new_max_rate,
+				  enum tegra_emc_rate_request_type type)
+{
+	struct tegra_emc_rate_request *req = reqs->requested_rate;
+	unsigned long min_rate = 0, max_rate = ULONG_MAX;
+	unsigned int i;
+	int err;
+
+	/* select minimum and maximum rates among the requested rates */
+	for (i = 0; i < TEGRA_EMC_RATE_TYPE_MAX; i++, req++) {
+		if (i == type) {
+			min_rate = max(new_min_rate, min_rate);
+			max_rate = min(new_max_rate, max_rate);
+		} else {
+			min_rate = max(req->min_rate, min_rate);
+			max_rate = min(req->max_rate, max_rate);
+		}
+	}
+
+	if (min_rate > max_rate) {
+		dev_err_ratelimited(reqs->dev, "%s: type %u: out of range: %lu %lu\n",
+				    __func__, type, min_rate, max_rate);
+		return -ERANGE;
+	}
+
+	/*
+	 * EMC rate-changes should go via OPP API because it manages voltage
+	 * changes.
+	 */
+	err = dev_pm_opp_set_rate(reqs->dev, min_rate);
+	if (err)
+		return err;
+
+	reqs->requested_rate[type].min_rate = new_min_rate;
+	reqs->requested_rate[type].max_rate = new_max_rate;
+
+	return 0;
+}
+
+int tegra_emc_set_min_rate(struct tegra_emc_rate_requests *reqs,
+			   unsigned long rate,
+			   enum tegra_emc_rate_request_type type)
+{
+	struct tegra_emc_rate_request *req = &reqs->requested_rate[type];
+	int ret;
+
+	mutex_lock(&reqs->rate_lock);
+	ret = tegra_emc_request_rate(reqs, rate, req->max_rate, type);
+	mutex_unlock(&reqs->rate_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tegra_emc_set_min_rate);
+
+int tegra_emc_set_max_rate(struct tegra_emc_rate_requests *reqs,
+			   unsigned long rate,
+			   enum tegra_emc_rate_request_type type)
+{
+	struct tegra_emc_rate_request *req = &reqs->requested_rate[type];
+	int ret;
+
+	mutex_lock(&reqs->rate_lock);
+	ret = tegra_emc_request_rate(reqs, req->min_rate, rate, type);
+	mutex_unlock(&reqs->rate_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tegra_emc_set_max_rate);
+
+MODULE_DESCRIPTION("NVIDIA Tegra EMC common code");
+MODULE_LICENSE("GPL");
diff --git a/drivers/memory/tegra/tegra-emc-common.h b/drivers/memory/tegra/tegra-emc-common.h
new file mode 100644
index 000000000000..420ff574045c
--- /dev/null
+++ b/drivers/memory/tegra/tegra-emc-common.h
@@ -0,0 +1,38 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef TEGRA_EMC_COMMON_H
+#define TEGRA_EMC_COMMON_H
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+enum tegra_emc_rate_request_type {
+	TEGRA_EMC_RATE_DEVFREQ,
+	TEGRA_EMC_RATE_DEBUG,
+	TEGRA_EMC_RATE_ICC,
+	TEGRA_EMC_RATE_TYPE_MAX,
+};
+
+struct tegra_emc_rate_request {
+	unsigned long min_rate;
+	unsigned long max_rate;
+};
+
+struct tegra_emc_rate_requests {
+	struct tegra_emc_rate_request requested_rate[TEGRA_EMC_RATE_TYPE_MAX];
+	struct mutex rate_lock;
+	struct device *dev;
+};
+
+void tegra_emc_rate_requests_init(struct tegra_emc_rate_requests *reqs,
+				  struct device *dev);
+
+int tegra_emc_set_min_rate(struct tegra_emc_rate_requests *reqs,
+			   unsigned long rate,
+			   enum tegra_emc_rate_request_type type);
+
+int tegra_emc_set_max_rate(struct tegra_emc_rate_requests *reqs,
+			   unsigned long rate,
+			   enum tegra_emc_rate_request_type type);
+
+#endif /* TEGRA_EMC_COMMON_H */
diff --git a/drivers/memory/tegra/tegra114-emc.c b/drivers/memory/tegra/tegra114-emc.c
index 789b8e959a68..4fdc30e29488 100644
--- a/drivers/memory/tegra/tegra114-emc.c
+++ b/drivers/memory/tegra/tegra114-emc.c
@@ -32,6 +32,7 @@ 
 #include <soc/tegra/mc.h>
 
 #include "mc.h"
+#include "tegra-emc-common.h"
 
 #define EMC_INTSTATUS				0x0
 #define EMC_INTSTATUS_REFRESH_OVERFLOW		BIT(3)
@@ -392,17 +393,6 @@  struct emc_timing {
 	u32 emc_zcal_interval;
 };
 
-enum emc_rate_request_type {
-	EMC_RATE_DEBUG,
-	EMC_RATE_ICC,
-	EMC_RATE_TYPE_MAX,
-};
-
-struct emc_rate_request {
-	unsigned long min_rate;
-	unsigned long max_rate;
-};
-
 struct tegra_emc {
 	struct device *dev;
 	struct tegra_mc *mc;
@@ -425,14 +415,7 @@  struct tegra_emc {
 
 	struct icc_provider provider;
 
-	/*
-	 * There are multiple sources in the EMC driver which could request
-	 * a min/max clock rate, these rates are contained in this array.
-	 */
-	struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
-
-	/* protect shared rate-change code path */
-	struct mutex rate_lock;
+	struct tegra_emc_rate_requests reqs;
 };
 
 static irqreturn_t tegra_emc_isr(int irq, void *data)
@@ -995,83 +978,6 @@  tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
 	return NULL;
 }
 
-static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
-{
-	unsigned int i;
-
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
-		emc->requested_rate[i].min_rate = 0;
-		emc->requested_rate[i].max_rate = ULONG_MAX;
-	}
-}
-
-static int emc_request_rate(struct tegra_emc *emc,
-			    unsigned long new_min_rate,
-			    unsigned long new_max_rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = emc->requested_rate;
-	unsigned long min_rate = 0, max_rate = ULONG_MAX;
-	unsigned int i;
-	int err;
-
-	/* select minimum and maximum rates among the requested rates */
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
-		if (i == type) {
-			min_rate = max(new_min_rate, min_rate);
-			max_rate = min(new_max_rate, max_rate);
-		} else {
-			min_rate = max(req->min_rate, min_rate);
-			max_rate = min(req->max_rate, max_rate);
-		}
-	}
-
-	if (min_rate > max_rate) {
-		dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
-				    __func__, type, min_rate, max_rate);
-		return -ERANGE;
-	}
-
-	/*
-	 * EMC rate-changes should go via OPP API because it manages voltage
-	 * changes.
-	 */
-	err = dev_pm_opp_set_rate(emc->dev, min_rate);
-	if (err)
-		return err;
-
-	emc->requested_rate[type].min_rate = new_min_rate;
-	emc->requested_rate[type].max_rate = new_max_rate;
-
-	return 0;
-}
-
-static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, rate, req->max_rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
-static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, req->min_rate, rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
 /*
  * debugfs interface
  *
@@ -1144,7 +1050,7 @@  static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
 	if (!tegra_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1174,7 +1080,7 @@  static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
 	if (!tegra_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_max_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1280,7 +1186,7 @@  static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
 	do_div(rate, ddr * dram_data_bus_width_bytes);
 	rate = min_t(u64, rate, U32_MAX);
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_ICC);
 	if (err)
 		return err;
 
@@ -1357,7 +1263,6 @@  static int tegra_emc_probe(struct platform_device *pdev)
 	if (!emc)
 		return -ENOMEM;
 
-	mutex_init(&emc->rate_lock);
 	emc->dev = &pdev->dev;
 
 	emc->regs = devm_platform_ioremap_resource(pdev, 0);
@@ -1424,7 +1329,7 @@  static int tegra_emc_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	tegra_emc_rate_requests_init(emc);
+	tegra_emc_rate_requests_init(&emc->reqs, &pdev->dev);
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS))
 		emc_debugfs_init(&pdev->dev, emc);
diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c
index 9978ff911c47..04ca1f606d29 100644
--- a/drivers/memory/tegra/tegra124-emc.c
+++ b/drivers/memory/tegra/tegra124-emc.c
@@ -27,6 +27,7 @@ 
 #include <soc/tegra/mc.h>
 
 #include "mc.h"
+#include "tegra-emc-common.h"
 
 #define EMC_FBIO_CFG5				0x104
 #define	EMC_FBIO_CFG5_DRAM_TYPE_MASK		0x3
@@ -467,17 +468,6 @@  struct emc_timing {
 	u32 emc_zcal_interval;
 };
 
-enum emc_rate_request_type {
-	EMC_RATE_DEBUG,
-	EMC_RATE_ICC,
-	EMC_RATE_TYPE_MAX,
-};
-
-struct emc_rate_request {
-	unsigned long min_rate;
-	unsigned long max_rate;
-};
-
 struct tegra_emc {
 	struct device *dev;
 
@@ -503,14 +493,7 @@  struct tegra_emc {
 
 	struct icc_provider provider;
 
-	/*
-	 * There are multiple sources in the EMC driver which could request
-	 * a min/max clock rate, these rates are contained in this array.
-	 */
-	struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
-
-	/* protect shared rate-change code path */
-	struct mutex rate_lock;
+	struct tegra_emc_rate_requests reqs;
 };
 
 /* Timing change sequence functions */
@@ -1041,83 +1024,6 @@  tegra124_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
 	return NULL;
 }
 
-static void tegra124_emc_rate_requests_init(struct tegra_emc *emc)
-{
-	unsigned int i;
-
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
-		emc->requested_rate[i].min_rate = 0;
-		emc->requested_rate[i].max_rate = ULONG_MAX;
-	}
-}
-
-static int emc_request_rate(struct tegra_emc *emc,
-			    unsigned long new_min_rate,
-			    unsigned long new_max_rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = emc->requested_rate;
-	unsigned long min_rate = 0, max_rate = ULONG_MAX;
-	unsigned int i;
-	int err;
-
-	/* select minimum and maximum rates among the requested rates */
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
-		if (i == type) {
-			min_rate = max(new_min_rate, min_rate);
-			max_rate = min(new_max_rate, max_rate);
-		} else {
-			min_rate = max(req->min_rate, min_rate);
-			max_rate = min(req->max_rate, max_rate);
-		}
-	}
-
-	if (min_rate > max_rate) {
-		dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
-				    __func__, type, min_rate, max_rate);
-		return -ERANGE;
-	}
-
-	/*
-	 * EMC rate-changes should go via OPP API because it manages voltage
-	 * changes.
-	 */
-	err = dev_pm_opp_set_rate(emc->dev, min_rate);
-	if (err)
-		return err;
-
-	emc->requested_rate[type].min_rate = new_min_rate;
-	emc->requested_rate[type].max_rate = new_max_rate;
-
-	return 0;
-}
-
-static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, rate, req->max_rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
-static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, req->min_rate, rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
 /*
  * debugfs interface
  *
@@ -1190,7 +1096,7 @@  static int tegra124_emc_debug_min_rate_set(void *data, u64 rate)
 	if (!tegra124_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1220,7 +1126,7 @@  static int tegra124_emc_debug_max_rate_set(void *data, u64 rate)
 	if (!tegra124_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_max_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1327,7 +1233,7 @@  static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
 	do_div(rate, ddr * dram_data_bus_width_bytes);
 	rate = min_t(u64, rate, U32_MAX);
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_ICC);
 	if (err)
 		return err;
 
@@ -1441,7 +1347,6 @@  static int tegra124_emc_probe(struct platform_device *pdev)
 	if (!emc)
 		return -ENOMEM;
 
-	mutex_init(&emc->rate_lock);
 	emc->dev = &pdev->dev;
 
 	emc->regs = devm_platform_ioremap_resource(pdev, 0);
@@ -1487,7 +1392,7 @@  static int tegra124_emc_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	tegra124_emc_rate_requests_init(emc);
+	tegra_emc_rate_requests_init(&emc->reqs, &pdev->dev);
 
 	if (IS_ENABLED(CONFIG_DEBUG_FS))
 		emc_debugfs_init(&pdev->dev, emc);
diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index 398cb8ae2e38..1fd59f49242b 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -32,6 +32,7 @@ 
 #include "../of_memory.h"
 
 #include "mc.h"
+#include "tegra-emc-common.h"
 
 #define EMC_INTSTATUS				0x000
 #define EMC_INTMASK				0x004
@@ -182,18 +183,6 @@  struct emc_timing {
 	u32 data[ARRAY_SIZE(emc_timing_registers)];
 };
 
-enum emc_rate_request_type {
-	EMC_RATE_DEVFREQ,
-	EMC_RATE_DEBUG,
-	EMC_RATE_ICC,
-	EMC_RATE_TYPE_MAX,
-};
-
-struct emc_rate_request {
-	unsigned long min_rate;
-	unsigned long max_rate;
-};
-
 struct tegra_emc {
 	struct device *dev;
 	struct tegra_mc *mc;
@@ -212,14 +201,7 @@  struct tegra_emc {
 		unsigned long max_rate;
 	} debugfs;
 
-	/*
-	 * There are multiple sources in the EMC driver which could request
-	 * a min/max clock rate, these rates are contained in this array.
-	 */
-	struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
-
-	/* protect shared rate-change code path */
-	struct mutex rate_lock;
+	struct tegra_emc_rate_requests reqs;
 
 	struct devfreq_simple_ondemand_data ondemand_data;
 
@@ -710,83 +692,6 @@  static long emc_round_rate(unsigned long rate,
 	return timing->rate;
 }
 
-static void tegra20_emc_rate_requests_init(struct tegra_emc *emc)
-{
-	unsigned int i;
-
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
-		emc->requested_rate[i].min_rate = 0;
-		emc->requested_rate[i].max_rate = ULONG_MAX;
-	}
-}
-
-static int emc_request_rate(struct tegra_emc *emc,
-			    unsigned long new_min_rate,
-			    unsigned long new_max_rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = emc->requested_rate;
-	unsigned long min_rate = 0, max_rate = ULONG_MAX;
-	unsigned int i;
-	int err;
-
-	/* select minimum and maximum rates among the requested rates */
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
-		if (i == type) {
-			min_rate = max(new_min_rate, min_rate);
-			max_rate = min(new_max_rate, max_rate);
-		} else {
-			min_rate = max(req->min_rate, min_rate);
-			max_rate = min(req->max_rate, max_rate);
-		}
-	}
-
-	if (min_rate > max_rate) {
-		dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
-				    __func__, type, min_rate, max_rate);
-		return -ERANGE;
-	}
-
-	/*
-	 * EMC rate-changes should go via OPP API because it manages voltage
-	 * changes.
-	 */
-	err = dev_pm_opp_set_rate(emc->dev, min_rate);
-	if (err)
-		return err;
-
-	emc->requested_rate[type].min_rate = new_min_rate;
-	emc->requested_rate[type].max_rate = new_max_rate;
-
-	return 0;
-}
-
-static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, rate, req->max_rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
-static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, req->min_rate, rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
 /*
  * debugfs interface
  *
@@ -857,7 +762,7 @@  static int tegra20_emc_debug_min_rate_set(void *data, u64 rate)
 	if (!tegra20_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -887,7 +792,7 @@  static int tegra20_emc_debug_max_rate_set(void *data, u64 rate)
 	if (!tegra20_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_max_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -993,7 +898,7 @@  static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
 	do_div(rate, dram_data_bus_width_bytes);
 	rate = min_t(u64, rate, U32_MAX);
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_ICC);
 	if (err)
 		return err;
 
@@ -1111,7 +1016,7 @@  static int tegra20_emc_devfreq_target(struct device *dev, unsigned long *freq,
 	rate = dev_pm_opp_get_freq(opp);
 	dev_pm_opp_put(opp);
 
-	return emc_set_min_rate(emc, rate, EMC_RATE_DEVFREQ);
+	return tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEVFREQ);
 }
 
 static int tegra20_emc_devfreq_get_dev_status(struct device *dev,
@@ -1190,7 +1095,6 @@  static int tegra20_emc_probe(struct platform_device *pdev)
 	if (!emc)
 		return -ENOMEM;
 
-	mutex_init(&emc->rate_lock);
 	emc->clk_nb.notifier_call = tegra20_emc_clk_change_notify;
 	emc->dev = &pdev->dev;
 
@@ -1228,7 +1132,7 @@  static int tegra20_emc_probe(struct platform_device *pdev)
 		return err;
 
 	platform_set_drvdata(pdev, emc);
-	tegra20_emc_rate_requests_init(emc);
+	tegra_emc_rate_requests_init(&emc->reqs, &pdev->dev);
 	tegra20_emc_debugfs_init(emc);
 	tegra20_emc_interconnect_init(emc);
 	tegra20_emc_devfreq_init(emc);
diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c
index 914116d8ec16..93aeef65b9d4 100644
--- a/drivers/memory/tegra/tegra30-emc.c
+++ b/drivers/memory/tegra/tegra30-emc.c
@@ -36,6 +36,7 @@ 
 #include "../of_memory.h"
 
 #include "mc.h"
+#include "tegra-emc-common.h"
 
 #define EMC_INTSTATUS				0x000
 #define EMC_INTMASK				0x004
@@ -341,17 +342,6 @@  struct emc_timing {
 	bool emc_cfg_dyn_self_ref;
 };
 
-enum emc_rate_request_type {
-	EMC_RATE_DEBUG,
-	EMC_RATE_ICC,
-	EMC_RATE_TYPE_MAX,
-};
-
-struct emc_rate_request {
-	unsigned long min_rate;
-	unsigned long max_rate;
-};
-
 struct tegra_emc {
 	struct device *dev;
 	struct tegra_mc *mc;
@@ -383,14 +373,7 @@  struct tegra_emc {
 		unsigned long max_rate;
 	} debugfs;
 
-	/*
-	 * There are multiple sources in the EMC driver which could request
-	 * a min/max clock rate, these rates are contained in this array.
-	 */
-	struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
-
-	/* protect shared rate-change code path */
-	struct mutex rate_lock;
+	struct tegra_emc_rate_requests reqs;
 
 	bool mrr_error;
 };
@@ -1228,83 +1211,6 @@  static long emc_round_rate(unsigned long rate,
 	return timing->rate;
 }
 
-static void tegra30_emc_rate_requests_init(struct tegra_emc *emc)
-{
-	unsigned int i;
-
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
-		emc->requested_rate[i].min_rate = 0;
-		emc->requested_rate[i].max_rate = ULONG_MAX;
-	}
-}
-
-static int emc_request_rate(struct tegra_emc *emc,
-			    unsigned long new_min_rate,
-			    unsigned long new_max_rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = emc->requested_rate;
-	unsigned long min_rate = 0, max_rate = ULONG_MAX;
-	unsigned int i;
-	int err;
-
-	/* select minimum and maximum rates among the requested rates */
-	for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
-		if (i == type) {
-			min_rate = max(new_min_rate, min_rate);
-			max_rate = min(new_max_rate, max_rate);
-		} else {
-			min_rate = max(req->min_rate, min_rate);
-			max_rate = min(req->max_rate, max_rate);
-		}
-	}
-
-	if (min_rate > max_rate) {
-		dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
-				    __func__, type, min_rate, max_rate);
-		return -ERANGE;
-	}
-
-	/*
-	 * EMC rate-changes should go via OPP API because it manages voltage
-	 * changes.
-	 */
-	err = dev_pm_opp_set_rate(emc->dev, min_rate);
-	if (err)
-		return err;
-
-	emc->requested_rate[type].min_rate = new_min_rate;
-	emc->requested_rate[type].max_rate = new_max_rate;
-
-	return 0;
-}
-
-static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, rate, req->max_rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
-static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
-			    enum emc_rate_request_type type)
-{
-	struct emc_rate_request *req = &emc->requested_rate[type];
-	int ret;
-
-	mutex_lock(&emc->rate_lock);
-	ret = emc_request_rate(emc, req->min_rate, rate, type);
-	mutex_unlock(&emc->rate_lock);
-
-	return ret;
-}
-
 /*
  * debugfs interface
  *
@@ -1375,7 +1281,7 @@  static int tegra30_emc_debug_min_rate_set(void *data, u64 rate)
 	if (!tegra30_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1405,7 +1311,7 @@  static int tegra30_emc_debug_max_rate_set(void *data, u64 rate)
 	if (!tegra30_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
+	err = tegra_emc_set_max_rate(&emc->reqs, rate, TEGRA_EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1511,7 +1417,7 @@  static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
 	do_div(rate, ddr * dram_data_bus_width_bytes);
 	rate = min_t(u64, rate, U32_MAX);
 
-	err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
+	err = tegra_emc_set_min_rate(&emc->reqs, rate, TEGRA_EMC_RATE_ICC);
 	if (err)
 		return err;
 
@@ -1622,7 +1528,6 @@  static int tegra30_emc_probe(struct platform_device *pdev)
 	if (IS_ERR(emc->mc))
 		return PTR_ERR(emc->mc);
 
-	mutex_init(&emc->rate_lock);
 	emc->clk_nb.notifier_call = emc_clk_change_notify;
 	emc->dev = &pdev->dev;
 
@@ -1664,7 +1569,7 @@  static int tegra30_emc_probe(struct platform_device *pdev)
 		return err;
 
 	platform_set_drvdata(pdev, emc);
-	tegra30_emc_rate_requests_init(emc);
+	tegra_emc_rate_requests_init(&emc->reqs, &pdev->dev);
 	tegra30_emc_debugfs_init(emc);
 	tegra30_emc_interconnect_init(emc);