diff mbox

[v9,01/15] ARM: Add Krait L2 register accessor functions

Message ID 1520347148-27852-2-git-send-email-sricharan@codeaurora.org (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Sricharan Ramabadhran March 6, 2018, 2:38 p.m. UTC
From: Stephen Boyd <sboyd@codeaurora.org>

Krait CPUs have a handful of L2 cache controller registers that
live behind a cp15 based indirection register. First you program
the indirection register (l2cpselr) to point the L2 'window'
register (l2cpdr) at what you want to read/write.  Then you
read/write the 'window' register to do what you want. The
l2cpselr register is not banked per-cpu so we must lock around
accesses to it to prevent other CPUs from re-pointing l2cpdr
underneath us.

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/common/Kconfig                   |  3 ++
 arch/arm/common/Makefile                  |  1 +
 arch/arm/common/krait-l2-accessors.c      | 48 +++++++++++++++++++++++++++++++
 arch/arm/include/asm/krait-l2-accessors.h | 10 +++++++
 4 files changed, 62 insertions(+)
 create mode 100644 arch/arm/common/krait-l2-accessors.c
 create mode 100644 arch/arm/include/asm/krait-l2-accessors.h

Comments

Bjorn Andersson May 24, 2018, 5:39 p.m. UTC | #1
On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:

> From: Stephen Boyd <sboyd@codeaurora.org>
> 
> Krait CPUs have a handful of L2 cache controller registers that
> live behind a cp15 based indirection register. First you program
> the indirection register (l2cpselr) to point the L2 'window'
> register (l2cpdr) at what you want to read/write.  Then you
> read/write the 'window' register to do what you want. The
> l2cpselr register is not banked per-cpu so we must lock around
> accesses to it to prevent other CPUs from re-pointing l2cpdr
> underneath us.
> 
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

This should have your signed-off-by here as well.

Apart from that:

Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>

Regards,
Bjorn

> ---
>  arch/arm/common/Kconfig                   |  3 ++
>  arch/arm/common/Makefile                  |  1 +
>  arch/arm/common/krait-l2-accessors.c      | 48 +++++++++++++++++++++++++++++++
>  arch/arm/include/asm/krait-l2-accessors.h | 10 +++++++
>  4 files changed, 62 insertions(+)
>  create mode 100644 arch/arm/common/krait-l2-accessors.c
>  create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
> 
> diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
> index e5ad070..c8e1986 100644
> --- a/arch/arm/common/Kconfig
> +++ b/arch/arm/common/Kconfig
> @@ -7,6 +7,9 @@ config DMABOUNCE
>  	bool
>  	select ZONE_DMA
>  
> +config KRAIT_L2_ACCESSORS
> +	bool
> +
>  config SHARP_LOCOMO
>  	bool
>  
> diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
> index 70b4a14..eec6cd1 100644
> --- a/arch/arm/common/Makefile
> +++ b/arch/arm/common/Makefile
> @@ -7,6 +7,7 @@ obj-y				+= firmware.o
>  
>  obj-$(CONFIG_SA1111)		+= sa1111.o
>  obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
> +obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
>  obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
>  obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
>  obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
> diff --git a/arch/arm/common/krait-l2-accessors.c b/arch/arm/common/krait-l2-accessors.c
> new file mode 100644
> index 0000000..9a97dda
> --- /dev/null
> +++ b/arch/arm/common/krait-l2-accessors.c
> @@ -0,0 +1,48 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
> +
> +#include <linux/spinlock.h>
> +#include <linux/export.h>
> +
> +#include <asm/barrier.h>
> +#include <asm/krait-l2-accessors.h>
> +
> +static DEFINE_RAW_SPINLOCK(krait_l2_lock);
> +
> +void krait_set_l2_indirect_reg(u32 addr, u32 val)
> +{
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&krait_l2_lock, flags);
> +	/*
> +	 * Select the L2 window by poking l2cpselr, then write to the window
> +	 * via l2cpdr.
> +	 */
> +	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
> +	isb();
> +	asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
> +	isb();
> +
> +	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
> +}
> +EXPORT_SYMBOL(krait_set_l2_indirect_reg);
> +
> +u32 krait_get_l2_indirect_reg(u32 addr)
> +{
> +	u32 val;
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&krait_l2_lock, flags);
> +	/*
> +	 * Select the L2 window by poking l2cpselr, then read from the window
> +	 * via l2cpdr.
> +	 */
> +	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
> +	isb();
> +	asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
> +
> +	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
> +
> +	return val;
> +}
> +EXPORT_SYMBOL(krait_get_l2_indirect_reg);
> diff --git a/arch/arm/include/asm/krait-l2-accessors.h b/arch/arm/include/asm/krait-l2-accessors.h
> new file mode 100644
> index 0000000..dd7c474
> --- /dev/null
> +++ b/arch/arm/include/asm/krait-l2-accessors.h
> @@ -0,0 +1,10 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
> +
> +#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
> +#define __ASMARM_KRAIT_L2_ACCESSORS_H
> +
> +extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
> +extern u32 krait_get_l2_indirect_reg(u32 addr);
> +
> +#endif
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
>
Sricharan Ramabadhran May 25, 2018, 5:40 a.m. UTC | #2
Hi Bjorn,

On 5/24/2018 11:09 PM, Bjorn Andersson wrote:
> On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:
> 
>> From: Stephen Boyd <sboyd@codeaurora.org>
>>
>> Krait CPUs have a handful of L2 cache controller registers that
>> live behind a cp15 based indirection register. First you program
>> the indirection register (l2cpselr) to point the L2 'window'
>> register (l2cpdr) at what you want to read/write.  Then you
>> read/write the 'window' register to do what you want. The
>> l2cpselr register is not banked per-cpu so we must lock around
>> accesses to it to prevent other CPUs from re-pointing l2cpdr
>> underneath us.
>>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Russell King <linux@arm.linux.org.uk>
>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> 
> This should have your signed-off-by here as well.
> 

 ok.

> Apart from that:
> 
> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> 

 Thanks.

Regards,
 Sricharan


> Regards,
> Bjorn
> 
>> ---
>>  arch/arm/common/Kconfig                   |  3 ++
>>  arch/arm/common/Makefile                  |  1 +
>>  arch/arm/common/krait-l2-accessors.c      | 48 +++++++++++++++++++++++++++++++
>>  arch/arm/include/asm/krait-l2-accessors.h | 10 +++++++
>>  4 files changed, 62 insertions(+)
>>  create mode 100644 arch/arm/common/krait-l2-accessors.c
>>  create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
>>
>> diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
>> index e5ad070..c8e1986 100644
>> --- a/arch/arm/common/Kconfig
>> +++ b/arch/arm/common/Kconfig
>> @@ -7,6 +7,9 @@ config DMABOUNCE
>>  	bool
>>  	select ZONE_DMA
>>  
>> +config KRAIT_L2_ACCESSORS
>> +	bool
>> +
>>  config SHARP_LOCOMO
>>  	bool
>>  
>> diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
>> index 70b4a14..eec6cd1 100644
>> --- a/arch/arm/common/Makefile
>> +++ b/arch/arm/common/Makefile
>> @@ -7,6 +7,7 @@ obj-y				+= firmware.o
>>  
>>  obj-$(CONFIG_SA1111)		+= sa1111.o
>>  obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
>> +obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
>>  obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
>>  obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
>>  obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
>> diff --git a/arch/arm/common/krait-l2-accessors.c b/arch/arm/common/krait-l2-accessors.c
>> new file mode 100644
>> index 0000000..9a97dda
>> --- /dev/null
>> +++ b/arch/arm/common/krait-l2-accessors.c
>> @@ -0,0 +1,48 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
>> +
>> +#include <linux/spinlock.h>
>> +#include <linux/export.h>
>> +
>> +#include <asm/barrier.h>
>> +#include <asm/krait-l2-accessors.h>
>> +
>> +static DEFINE_RAW_SPINLOCK(krait_l2_lock);
>> +
>> +void krait_set_l2_indirect_reg(u32 addr, u32 val)
>> +{
>> +	unsigned long flags;
>> +
>> +	raw_spin_lock_irqsave(&krait_l2_lock, flags);
>> +	/*
>> +	 * Select the L2 window by poking l2cpselr, then write to the window
>> +	 * via l2cpdr.
>> +	 */
>> +	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
>> +	isb();
>> +	asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
>> +	isb();
>> +
>> +	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
>> +}
>> +EXPORT_SYMBOL(krait_set_l2_indirect_reg);
>> +
>> +u32 krait_get_l2_indirect_reg(u32 addr)
>> +{
>> +	u32 val;
>> +	unsigned long flags;
>> +
>> +	raw_spin_lock_irqsave(&krait_l2_lock, flags);
>> +	/*
>> +	 * Select the L2 window by poking l2cpselr, then read from the window
>> +	 * via l2cpdr.
>> +	 */
>> +	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
>> +	isb();
>> +	asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
>> +
>> +	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
>> +
>> +	return val;
>> +}
>> +EXPORT_SYMBOL(krait_get_l2_indirect_reg);
>> diff --git a/arch/arm/include/asm/krait-l2-accessors.h b/arch/arm/include/asm/krait-l2-accessors.h
>> new file mode 100644
>> index 0000000..dd7c474
>> --- /dev/null
>> +++ b/arch/arm/include/asm/krait-l2-accessors.h
>> @@ -0,0 +1,10 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
>> +
>> +#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
>> +#define __ASMARM_KRAIT_L2_ACCESSORS_H
>> +
>> +extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
>> +extern u32 krait_get_l2_indirect_reg(u32 addr);
>> +
>> +#endif
>> -- 
>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
>>
Stephen Boyd May 30, 2018, 3:55 p.m. UTC | #3
Quoting Sricharan R (2018-05-24 22:40:11)
> Hi Bjorn,
> 
> On 5/24/2018 11:09 PM, Bjorn Andersson wrote:
> > On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:
> > 
> >> From: Stephen Boyd <sboyd@codeaurora.org>
> >>
> >> Krait CPUs have a handful of L2 cache controller registers that
> >> live behind a cp15 based indirection register. First you program
> >> the indirection register (l2cpselr) to point the L2 'window'
> >> register (l2cpdr) at what you want to read/write.  Then you
> >> read/write the 'window' register to do what you want. The
> >> l2cpselr register is not banked per-cpu so we must lock around
> >> accesses to it to prevent other CPUs from re-pointing l2cpdr
> >> underneath us.
> >>
> >> Cc: Mark Rutland <mark.rutland@arm.com>
> >> Cc: Russell King <linux@arm.linux.org.uk>
> >> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > 
> > This should have your signed-off-by here as well.
> > 
> 
>  ok.
> 
> > Apart from that:
> > 
> > Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > 
> 

Will these patches come around again? I'll do a quick sweep on them
today but I expect them to be resent.
Sricharan Ramabadhran May 31, 2018, 4:57 a.m. UTC | #4
Hi Stephen,

On 5/30/2018 9:25 PM, Stephen Boyd wrote:
> Quoting Sricharan R (2018-05-24 22:40:11)
>> Hi Bjorn,
>>
>> On 5/24/2018 11:09 PM, Bjorn Andersson wrote:
>>> On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:
>>>
>>>> From: Stephen Boyd <sboyd@codeaurora.org>
>>>>
>>>> Krait CPUs have a handful of L2 cache controller registers that
>>>> live behind a cp15 based indirection register. First you program
>>>> the indirection register (l2cpselr) to point the L2 'window'
>>>> register (l2cpdr) at what you want to read/write.  Then you
>>>> read/write the 'window' register to do what you want. The
>>>> l2cpselr register is not banked per-cpu so we must lock around
>>>> accesses to it to prevent other CPUs from re-pointing l2cpdr
>>>> underneath us.
>>>>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Cc: Russell King <linux@arm.linux.org.uk>
>>>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>>>
>>> This should have your signed-off-by here as well.
>>>
>>
>>  ok.
>>
>>> Apart from that:
>>>
>>> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
>>>
>>
> 
> Will these patches come around again? I'll do a quick sweep on them
> today but I expect them to be resent.

Sure, i will have to resend them again, fixing couple of Bjorn's
minor comments. Will address your comments that you would give
as well along with that.

Regards,
 Sricharan
Stephen Boyd May 31, 2018, 7:41 a.m. UTC | #5
Quoting Sricharan R (2018-05-30 21:57:20)
> Hi Stephen,
> 
> On 5/30/2018 9:25 PM, Stephen Boyd wrote:
> > Quoting Sricharan R (2018-05-24 22:40:11)
> >> Hi Bjorn,
> >>
> >> On 5/24/2018 11:09 PM, Bjorn Andersson wrote:
> >>> On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:
> >>>
> >>>> From: Stephen Boyd <sboyd@codeaurora.org>
> >>>>
> >>>> Krait CPUs have a handful of L2 cache controller registers that
> >>>> live behind a cp15 based indirection register. First you program
> >>>> the indirection register (l2cpselr) to point the L2 'window'
> >>>> register (l2cpdr) at what you want to read/write.  Then you
> >>>> read/write the 'window' register to do what you want. The
> >>>> l2cpselr register is not banked per-cpu so we must lock around
> >>>> accesses to it to prevent other CPUs from re-pointing l2cpdr
> >>>> underneath us.
> >>>>
> >>>> Cc: Mark Rutland <mark.rutland@arm.com>
> >>>> Cc: Russell King <linux@arm.linux.org.uk>
> >>>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> >>>
> >>> This should have your signed-off-by here as well.
> >>>
> >>
> >>  ok.
> >>
> >>> Apart from that:
> >>>
> >>> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> >>>
> >>
> > 
> > Will these patches come around again? I'll do a quick sweep on them
> > today but I expect them to be resent.
> 
> Sure, i will have to resend them again, fixing couple of Bjorn's
> minor comments. Will address your comments that you would give
> as well along with that.
> 

Ok. One general comment is that it would be nice if the bindings for all
the nodes that are introduced included 'clocks' properties and also
maybe 'clock-names' properties for the clocks that are consumed by each
node. Right now, we hide those details from DT and rely on the string
names to hook the clk tree up for us. That sort of prevents us from
moving away from string easily, so I would just throw the clocks into
the binding right now and always have them there just in case we want to
use the binding to figure out the hierarchy in the future.

I've been thinking we need to do something similar for the gcc and other
nodes for any clks they use, but I haven't gotten around to it.

Otherwise the patches look mostly ok to me. Not sure I'll have any other
comments.
Sricharan Ramabadhran June 1, 2018, 1:20 p.m. UTC | #6
Hi Stephen,

On 5/31/2018 1:11 PM, Stephen Boyd wrote:
> Quoting Sricharan R (2018-05-30 21:57:20)
>> Hi Stephen,
>>
>> On 5/30/2018 9:25 PM, Stephen Boyd wrote:
>>> Quoting Sricharan R (2018-05-24 22:40:11)
>>>> Hi Bjorn,
>>>>
>>>> On 5/24/2018 11:09 PM, Bjorn Andersson wrote:
>>>>> On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:
>>>>>
>>>>>> From: Stephen Boyd <sboyd@codeaurora.org>
>>>>>>
>>>>>> Krait CPUs have a handful of L2 cache controller registers that
>>>>>> live behind a cp15 based indirection register. First you program
>>>>>> the indirection register (l2cpselr) to point the L2 'window'
>>>>>> register (l2cpdr) at what you want to read/write.  Then you
>>>>>> read/write the 'window' register to do what you want. The
>>>>>> l2cpselr register is not banked per-cpu so we must lock around
>>>>>> accesses to it to prevent other CPUs from re-pointing l2cpdr
>>>>>> underneath us.
>>>>>>
>>>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>>>> Cc: Russell King <linux@arm.linux.org.uk>
>>>>>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>>>>>
>>>>> This should have your signed-off-by here as well.
>>>>>
>>>>
>>>>  ok.
>>>>
>>>>> Apart from that:
>>>>>
>>>>> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
>>>>>
>>>>
>>>
>>> Will these patches come around again? I'll do a quick sweep on them
>>> today but I expect them to be resent.
>>
>> Sure, i will have to resend them again, fixing couple of Bjorn's
>> minor comments. Will address your comments that you would give
>> as well along with that.
>>
> 
> Ok. One general comment is that it would be nice if the bindings for all
> the nodes that are introduced included 'clocks' properties and also
> maybe 'clock-names' properties for the clocks that are consumed by each
> node. Right now, we hide those details from DT and rely on the string
> names to hook the clk tree up for us. That sort of prevents us from
> moving away from string easily, so I would just throw the clocks into
> the binding right now and always have them there just in case we want to
> use the binding to figure out the hierarchy in the future.
> 

 ok, understand that mostly. So will try to revamp those patches with
 the 'clocks' property in the binding added, reading them in the driver
 from DT.

> I've been thinking we need to do something similar for the gcc and other
> nodes for any clks they use, but I haven't gotten around to it.
> 
> Otherwise the patches look mostly ok to me. Not sure I'll have any other
> comments.
> 

 Thanks, will respin.

Regards,
 Sricharan
Stephen Boyd June 1, 2018, 5:12 p.m. UTC | #7
Quoting Sricharan R (2018-06-01 06:20:37)
> Hi Stephen,
> 
> On 5/31/2018 1:11 PM, Stephen Boyd wrote:
> > 
> > Ok. One general comment is that it would be nice if the bindings for all
> > the nodes that are introduced included 'clocks' properties and also
> > maybe 'clock-names' properties for the clocks that are consumed by each
> > node. Right now, we hide those details from DT and rely on the string
> > names to hook the clk tree up for us. That sort of prevents us from
> > moving away from string easily, so I would just throw the clocks into
> > the binding right now and always have them there just in case we want to
> > use the binding to figure out the hierarchy in the future.
> > 
> 
>  ok, understand that mostly. So will try to revamp those patches with
>  the 'clocks' property in the binding added, reading them in the driver
>  from DT.

Yeah. You don't even have to actually use the clocks property right now
from the drivers. Just add the properties in the binding.
diff mbox

Patch

diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index e5ad070..c8e1986 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -7,6 +7,9 @@  config DMABOUNCE
 	bool
 	select ZONE_DMA
 
+config KRAIT_L2_ACCESSORS
+	bool
+
 config SHARP_LOCOMO
 	bool
 
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 70b4a14..eec6cd1 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -7,6 +7,7 @@  obj-y				+= firmware.o
 
 obj-$(CONFIG_SA1111)		+= sa1111.o
 obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
 obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
 obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
diff --git a/arch/arm/common/krait-l2-accessors.c b/arch/arm/common/krait-l2-accessors.c
new file mode 100644
index 0000000..9a97dda
--- /dev/null
+++ b/arch/arm/common/krait-l2-accessors.c
@@ -0,0 +1,48 @@ 
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include <linux/spinlock.h>
+#include <linux/export.h>
+
+#include <asm/barrier.h>
+#include <asm/krait-l2-accessors.h>
+
+static DEFINE_RAW_SPINLOCK(krait_l2_lock);
+
+void krait_set_l2_indirect_reg(u32 addr, u32 val)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&krait_l2_lock, flags);
+	/*
+	 * Select the L2 window by poking l2cpselr, then write to the window
+	 * via l2cpdr.
+	 */
+	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+	isb();
+	asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
+	isb();
+
+	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+}
+EXPORT_SYMBOL(krait_set_l2_indirect_reg);
+
+u32 krait_get_l2_indirect_reg(u32 addr)
+{
+	u32 val;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&krait_l2_lock, flags);
+	/*
+	 * Select the L2 window by poking l2cpselr, then read from the window
+	 * via l2cpdr.
+	 */
+	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+	isb();
+	asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
+
+	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL(krait_get_l2_indirect_reg);
diff --git a/arch/arm/include/asm/krait-l2-accessors.h b/arch/arm/include/asm/krait-l2-accessors.h
new file mode 100644
index 0000000..dd7c474
--- /dev/null
+++ b/arch/arm/include/asm/krait-l2-accessors.h
@@ -0,0 +1,10 @@ 
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
+#define __ASMARM_KRAIT_L2_ACCESSORS_H
+
+extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
+extern u32 krait_get_l2_indirect_reg(u32 addr);
+
+#endif