ARM: 7547/4: cache-l2x0: add support for Aurora L2 cache ctrl
Aurora Cache Controller was designed to be compatible with the ARM L2 Cache Controller. It comes with some difference or improvement such as: - no cache id part number available through hardware (need to get it by the DT). - always write through mode available. - two flavors of the controller outer cache and system cache (meaning maintenance operations on L1 are broadcasted to the L2 and L2 performs the same operation). - in outer cache mode, the cache maintenance operations are improved and can be done on a range inside a page and are not limited to a cache line. Tested-and-Reviewed-by: Lior Amsalem <alior@marvell.com> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Yehuda Yitschak <yehuday@marvell.com> Reviewed-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
c3545236e8
commit
b8db6b886a
|
@ -102,6 +102,10 @@
|
||||||
|
|
||||||
#define L2X0_ADDR_FILTER_EN 1
|
#define L2X0_ADDR_FILTER_EN 1
|
||||||
|
|
||||||
|
#define L2X0_CTRL_EN 1
|
||||||
|
|
||||||
|
#define L2X0_WAY_SIZE_SHIFT 3
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
|
extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
|
||||||
#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
|
#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* AURORA shared L2 cache controller support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Marvell
|
||||||
|
*
|
||||||
|
* Yehuda Yitschak <yehuday@marvell.com>
|
||||||
|
* Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public
|
||||||
|
* License version 2. This program is licensed "as is" without any
|
||||||
|
* warranty of any kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASM_ARM_HARDWARE_AURORA_L2_H
|
||||||
|
#define __ASM_ARM_HARDWARE_AURORA_L2_H
|
||||||
|
|
||||||
|
#define AURORA_SYNC_REG 0x700
|
||||||
|
#define AURORA_RANGE_BASE_ADDR_REG 0x720
|
||||||
|
#define AURORA_FLUSH_PHY_ADDR_REG 0x7f0
|
||||||
|
#define AURORA_INVAL_RANGE_REG 0x774
|
||||||
|
#define AURORA_CLEAN_RANGE_REG 0x7b4
|
||||||
|
#define AURORA_FLUSH_RANGE_REG 0x7f4
|
||||||
|
|
||||||
|
#define AURORA_ACR_REPLACEMENT_OFFSET 27
|
||||||
|
#define AURORA_ACR_REPLACEMENT_MASK \
|
||||||
|
(0x3 << AURORA_ACR_REPLACEMENT_OFFSET)
|
||||||
|
#define AURORA_ACR_REPLACEMENT_TYPE_WAYRR \
|
||||||
|
(0 << AURORA_ACR_REPLACEMENT_OFFSET)
|
||||||
|
#define AURORA_ACR_REPLACEMENT_TYPE_LFSR \
|
||||||
|
(1 << AURORA_ACR_REPLACEMENT_OFFSET)
|
||||||
|
#define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \
|
||||||
|
(3 << AURORA_ACR_REPLACEMENT_OFFSET)
|
||||||
|
|
||||||
|
#define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET 0
|
||||||
|
#define AURORA_ACR_FORCE_WRITE_POLICY_MASK \
|
||||||
|
(0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
|
||||||
|
#define AURORA_ACR_FORCE_WRITE_POLICY_DIS \
|
||||||
|
(0 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
|
||||||
|
#define AURORA_ACR_FORCE_WRITE_BACK_POLICY \
|
||||||
|
(1 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
|
||||||
|
#define AURORA_ACR_FORCE_WRITE_THRO_POLICY \
|
||||||
|
(2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
|
||||||
|
|
||||||
|
#define MAX_RANGE_SIZE 1024
|
||||||
|
|
||||||
|
#define AURORA_WAY_SIZE_SHIFT 2
|
||||||
|
|
||||||
|
#define AURORA_CTRL_FW 0x100
|
||||||
|
|
||||||
|
/* chose a number outside L2X0_CACHE_ID_PART_MASK to be sure to make
|
||||||
|
* the distinction between a number coming from hardware and a number
|
||||||
|
* coming from the device tree */
|
||||||
|
#define AURORA_CACHE_ID 0x100
|
||||||
|
|
||||||
|
#endif /* __ASM_ARM_HARDWARE_AURORA_L2_H */
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
#include "cache-aurora-l2.h"
|
||||||
|
|
||||||
#define CACHE_LINE_SIZE 32
|
#define CACHE_LINE_SIZE 32
|
||||||
|
|
||||||
|
@ -34,6 +35,10 @@ static u32 l2x0_way_mask; /* Bitmask of active ways */
|
||||||
static u32 l2x0_size;
|
static u32 l2x0_size;
|
||||||
static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
|
static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
|
||||||
|
|
||||||
|
/* Aurora don't have the cache ID register available, so we have to
|
||||||
|
* pass it though the device tree */
|
||||||
|
static u32 cache_id_part_number_from_dt;
|
||||||
|
|
||||||
struct l2x0_regs l2x0_saved_regs;
|
struct l2x0_regs l2x0_saved_regs;
|
||||||
|
|
||||||
struct l2x0_of_data {
|
struct l2x0_of_data {
|
||||||
|
@ -170,7 +175,7 @@ static void l2x0_inv_all(void)
|
||||||
/* invalidate all ways */
|
/* invalidate all ways */
|
||||||
raw_spin_lock_irqsave(&l2x0_lock, flags);
|
raw_spin_lock_irqsave(&l2x0_lock, flags);
|
||||||
/* Invalidating when L2 is enabled is a nono */
|
/* Invalidating when L2 is enabled is a nono */
|
||||||
BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
|
BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN);
|
||||||
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
|
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
|
||||||
cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
|
cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
|
||||||
cache_sync();
|
cache_sync();
|
||||||
|
@ -294,11 +299,18 @@ static void l2x0_unlock(u32 cache_id)
|
||||||
int lockregs;
|
int lockregs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (cache_id == L2X0_CACHE_ID_PART_L310)
|
switch (cache_id) {
|
||||||
|
case L2X0_CACHE_ID_PART_L310:
|
||||||
lockregs = 8;
|
lockregs = 8;
|
||||||
else
|
break;
|
||||||
|
case AURORA_CACHE_ID:
|
||||||
|
lockregs = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
/* L210 and unknown types */
|
/* L210 and unknown types */
|
||||||
lockregs = 1;
|
lockregs = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < lockregs; i++) {
|
for (i = 0; i < lockregs; i++) {
|
||||||
writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
|
writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
|
||||||
|
@ -314,18 +326,22 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
|
||||||
u32 cache_id;
|
u32 cache_id;
|
||||||
u32 way_size = 0;
|
u32 way_size = 0;
|
||||||
int ways;
|
int ways;
|
||||||
|
int way_size_shift = L2X0_WAY_SIZE_SHIFT;
|
||||||
const char *type;
|
const char *type;
|
||||||
|
|
||||||
l2x0_base = base;
|
l2x0_base = base;
|
||||||
|
if (cache_id_part_number_from_dt)
|
||||||
cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
|
cache_id = cache_id_part_number_from_dt;
|
||||||
|
else
|
||||||
|
cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID)
|
||||||
|
& L2X0_CACHE_ID_PART_MASK;
|
||||||
aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
|
aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
|
||||||
|
|
||||||
aux &= aux_mask;
|
aux &= aux_mask;
|
||||||
aux |= aux_val;
|
aux |= aux_val;
|
||||||
|
|
||||||
/* Determine the number of ways */
|
/* Determine the number of ways */
|
||||||
switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
|
switch (cache_id) {
|
||||||
case L2X0_CACHE_ID_PART_L310:
|
case L2X0_CACHE_ID_PART_L310:
|
||||||
if (aux & (1 << 16))
|
if (aux & (1 << 16))
|
||||||
ways = 16;
|
ways = 16;
|
||||||
|
@ -342,6 +358,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
|
||||||
ways = (aux >> 13) & 0xf;
|
ways = (aux >> 13) & 0xf;
|
||||||
type = "L210";
|
type = "L210";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AURORA_CACHE_ID:
|
||||||
|
sync_reg_offset = AURORA_SYNC_REG;
|
||||||
|
ways = (aux >> 13) & 0xf;
|
||||||
|
ways = 2 << ((ways + 1) >> 2);
|
||||||
|
way_size_shift = AURORA_WAY_SIZE_SHIFT;
|
||||||
|
type = "Aurora";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Assume unknown chips have 8 ways */
|
/* Assume unknown chips have 8 ways */
|
||||||
ways = 8;
|
ways = 8;
|
||||||
|
@ -355,7 +379,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
|
||||||
* L2 cache Size = Way size * Number of ways
|
* L2 cache Size = Way size * Number of ways
|
||||||
*/
|
*/
|
||||||
way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
|
way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
|
||||||
way_size = 1 << (way_size + 3);
|
way_size = 1 << (way_size + way_size_shift);
|
||||||
|
|
||||||
l2x0_size = ways * way_size * SZ_1K;
|
l2x0_size = ways * way_size * SZ_1K;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -363,7 +388,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
|
||||||
* If you are booting from non-secure mode
|
* If you are booting from non-secure mode
|
||||||
* accessing the below registers will fault.
|
* accessing the below registers will fault.
|
||||||
*/
|
*/
|
||||||
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
|
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
|
||||||
/* Make sure that I&D is not locked down when starting */
|
/* Make sure that I&D is not locked down when starting */
|
||||||
l2x0_unlock(cache_id);
|
l2x0_unlock(cache_id);
|
||||||
|
|
||||||
|
@ -373,7 +398,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
|
||||||
l2x0_inv_all();
|
l2x0_inv_all();
|
||||||
|
|
||||||
/* enable L2X0 */
|
/* enable L2X0 */
|
||||||
writel_relaxed(1, l2x0_base + L2X0_CTRL);
|
writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-read it in case some bits are reserved. */
|
/* Re-read it in case some bits are reserved. */
|
||||||
|
@ -398,6 +423,100 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
|
static int l2_wt_override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the end addresses passed to Linux primitives are
|
||||||
|
* noninclusive, while the hardware cache range operations use
|
||||||
|
* inclusive start and end addresses.
|
||||||
|
*/
|
||||||
|
static unsigned long calc_range_end(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Limit the number of cache lines processed at once,
|
||||||
|
* since cache range operations stall the CPU pipeline
|
||||||
|
* until completion.
|
||||||
|
*/
|
||||||
|
if (end > start + MAX_RANGE_SIZE)
|
||||||
|
end = start + MAX_RANGE_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache range operations can't straddle a page boundary.
|
||||||
|
*/
|
||||||
|
if (end > PAGE_ALIGN(start+1))
|
||||||
|
end = PAGE_ALIGN(start+1);
|
||||||
|
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure 'start' and 'end' reference the same page, as L2 is PIPT
|
||||||
|
* and range operations only do a TLB lookup on the start address.
|
||||||
|
*/
|
||||||
|
static void aurora_pa_range(unsigned long start, unsigned long end,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&l2x0_lock, flags);
|
||||||
|
writel(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
|
||||||
|
writel(end, l2x0_base + offset);
|
||||||
|
raw_spin_unlock_irqrestore(&l2x0_lock, flags);
|
||||||
|
|
||||||
|
cache_sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aurora_inv_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* round start and end adresses up to cache line size
|
||||||
|
*/
|
||||||
|
start &= ~(CACHE_LINE_SIZE - 1);
|
||||||
|
end = ALIGN(end, CACHE_LINE_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invalidate all full cache lines between 'start' and 'end'.
|
||||||
|
*/
|
||||||
|
while (start < end) {
|
||||||
|
unsigned long range_end = calc_range_end(start, end);
|
||||||
|
aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
|
||||||
|
AURORA_INVAL_RANGE_REG);
|
||||||
|
start = range_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aurora_clean_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If L2 is forced to WT, the L2 will always be clean and we
|
||||||
|
* don't need to do anything here.
|
||||||
|
*/
|
||||||
|
if (!l2_wt_override) {
|
||||||
|
start &= ~(CACHE_LINE_SIZE - 1);
|
||||||
|
end = ALIGN(end, CACHE_LINE_SIZE);
|
||||||
|
while (start != end) {
|
||||||
|
unsigned long range_end = calc_range_end(start, end);
|
||||||
|
aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
|
||||||
|
AURORA_CLEAN_RANGE_REG);
|
||||||
|
start = range_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aurora_flush_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
if (!l2_wt_override) {
|
||||||
|
start &= ~(CACHE_LINE_SIZE - 1);
|
||||||
|
end = ALIGN(end, CACHE_LINE_SIZE);
|
||||||
|
while (start != end) {
|
||||||
|
unsigned long range_end = calc_range_end(start, end);
|
||||||
|
aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
|
||||||
|
AURORA_FLUSH_RANGE_REG);
|
||||||
|
start = range_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __init l2x0_of_setup(const struct device_node *np,
|
static void __init l2x0_of_setup(const struct device_node *np,
|
||||||
u32 *aux_val, u32 *aux_mask)
|
u32 *aux_val, u32 *aux_mask)
|
||||||
{
|
{
|
||||||
|
@ -495,9 +614,15 @@ static void __init pl310_save(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aurora_save(void)
|
||||||
|
{
|
||||||
|
l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
|
||||||
|
l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
static void l2x0_resume(void)
|
static void l2x0_resume(void)
|
||||||
{
|
{
|
||||||
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
|
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
|
||||||
/* restore aux ctrl and enable l2 */
|
/* restore aux ctrl and enable l2 */
|
||||||
l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
|
l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
|
||||||
|
|
||||||
|
@ -506,7 +631,7 @@ static void l2x0_resume(void)
|
||||||
|
|
||||||
l2x0_inv_all();
|
l2x0_inv_all();
|
||||||
|
|
||||||
writel_relaxed(1, l2x0_base + L2X0_CTRL);
|
writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +639,7 @@ static void pl310_resume(void)
|
||||||
{
|
{
|
||||||
u32 l2x0_revision;
|
u32 l2x0_revision;
|
||||||
|
|
||||||
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
|
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
|
||||||
/* restore pl310 setup */
|
/* restore pl310 setup */
|
||||||
writel_relaxed(l2x0_saved_regs.tag_latency,
|
writel_relaxed(l2x0_saved_regs.tag_latency,
|
||||||
l2x0_base + L2X0_TAG_LATENCY_CTRL);
|
l2x0_base + L2X0_TAG_LATENCY_CTRL);
|
||||||
|
@ -540,6 +665,46 @@ static void pl310_resume(void)
|
||||||
l2x0_resume();
|
l2x0_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aurora_resume(void)
|
||||||
|
{
|
||||||
|
if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
|
||||||
|
writel(l2x0_saved_regs.aux_ctrl, l2x0_base + L2X0_AUX_CTRL);
|
||||||
|
writel(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init aurora_broadcast_l2_commands(void)
|
||||||
|
{
|
||||||
|
__u32 u;
|
||||||
|
/* Enable Broadcasting of cache commands to L2*/
|
||||||
|
__asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u));
|
||||||
|
u |= AURORA_CTRL_FW; /* Set the FW bit */
|
||||||
|
__asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u));
|
||||||
|
isb();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init aurora_of_setup(const struct device_node *np,
|
||||||
|
u32 *aux_val, u32 *aux_mask)
|
||||||
|
{
|
||||||
|
u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
|
||||||
|
u32 mask = AURORA_ACR_REPLACEMENT_MASK;
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cache-id-part",
|
||||||
|
&cache_id_part_number_from_dt);
|
||||||
|
|
||||||
|
/* Determine and save the write policy */
|
||||||
|
l2_wt_override = of_property_read_bool(np, "wt-override");
|
||||||
|
|
||||||
|
if (l2_wt_override) {
|
||||||
|
val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
|
||||||
|
mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aux_val &= ~mask;
|
||||||
|
*aux_val |= val;
|
||||||
|
*aux_mask &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct l2x0_of_data pl310_data = {
|
static const struct l2x0_of_data pl310_data = {
|
||||||
.setup = pl310_of_setup,
|
.setup = pl310_of_setup,
|
||||||
.save = pl310_save,
|
.save = pl310_save,
|
||||||
|
@ -571,10 +736,37 @@ static const struct l2x0_of_data l2x0_data = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct l2x0_of_data aurora_with_outer_data = {
|
||||||
|
.setup = aurora_of_setup,
|
||||||
|
.save = aurora_save,
|
||||||
|
.outer_cache = {
|
||||||
|
.resume = aurora_resume,
|
||||||
|
.inv_range = aurora_inv_range,
|
||||||
|
.clean_range = aurora_clean_range,
|
||||||
|
.flush_range = aurora_flush_range,
|
||||||
|
.sync = l2x0_cache_sync,
|
||||||
|
.flush_all = l2x0_flush_all,
|
||||||
|
.inv_all = l2x0_inv_all,
|
||||||
|
.disable = l2x0_disable,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct l2x0_of_data aurora_no_outer_data = {
|
||||||
|
.setup = aurora_of_setup,
|
||||||
|
.save = aurora_save,
|
||||||
|
.outer_cache = {
|
||||||
|
.resume = aurora_resume,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id l2x0_ids[] __initconst = {
|
static const struct of_device_id l2x0_ids[] __initconst = {
|
||||||
{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
|
{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
|
||||||
{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
|
{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
|
||||||
{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
|
{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
|
||||||
|
{ .compatible = "marvell,aurora-system-cache",
|
||||||
|
.data = (void *)&aurora_no_outer_data},
|
||||||
|
{ .compatible = "marvell,aurora-outer-cache",
|
||||||
|
.data = (void *)&aurora_with_outer_data},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -600,9 +792,14 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
|
||||||
data = of_match_node(l2x0_ids, np)->data;
|
data = of_match_node(l2x0_ids, np)->data;
|
||||||
|
|
||||||
/* L2 configuration can only be changed if the cache is disabled */
|
/* L2 configuration can only be changed if the cache is disabled */
|
||||||
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
|
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
|
||||||
if (data->setup)
|
if (data->setup)
|
||||||
data->setup(np, &aux_val, &aux_mask);
|
data->setup(np, &aux_val, &aux_mask);
|
||||||
|
|
||||||
|
/* For aurora cache in no outer mode select the
|
||||||
|
* correct mode using the coprocessor*/
|
||||||
|
if (data == &aurora_no_outer_data)
|
||||||
|
aurora_broadcast_l2_commands();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->save)
|
if (data->save)
|
||||||
|
|
Loading…
Reference in New Issue