Sync register macros with Linux code. This will be helpful to develop the counterpart of Linux. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>master
parent
ebab100a98
commit
4bab70a77d
@ -0,0 +1,165 @@ |
||||
/*
|
||||
* Copyright (C) 2012-2014 Panasonic Corporation |
||||
* Copyright (C) 2015-2016 Socionext Inc. |
||||
* Author: Masahiro Yamada <yamada.masahiro@socionext.com> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <linux/io.h> |
||||
#include <asm/armv7.h> |
||||
|
||||
#include "ssc-regs.h" |
||||
|
||||
#ifdef CONFIG_UNIPHIER_L2CACHE_ON |
||||
static void uniphier_cache_sync(void) |
||||
{ |
||||
/* drain internal buffers */ |
||||
writel(UNIPHIER_SSCOPE_CM_SYNC, UNIPHIER_SSCOPE); |
||||
/* need a read back to confirm */ |
||||
readl(UNIPHIER_SSCOPE); |
||||
} |
||||
|
||||
static void uniphier_cache_maint_all(u32 operation) |
||||
{ |
||||
/* clear the complete notification flag */ |
||||
writel(UNIPHIER_SSCOLPQS_EF, UNIPHIER_SSCOLPQS); |
||||
|
||||
/* try until the command is successfully set */ |
||||
do { |
||||
writel(UNIPHIER_SSCOQM_S_ALL | UNIPHIER_SSCOQM_CE | operation, |
||||
UNIPHIER_SSCOQM); |
||||
} while (readl(UNIPHIER_SSCOPPQSEF) & |
||||
(UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)); |
||||
|
||||
/* wait until the operation is completed */ |
||||
while (readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF) |
||||
; |
||||
|
||||
uniphier_cache_sync(); |
||||
} |
||||
|
||||
void v7_outer_cache_flush_all(void) |
||||
{ |
||||
uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH); |
||||
} |
||||
|
||||
void v7_outer_cache_inval_all(void) |
||||
{ |
||||
uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV); |
||||
} |
||||
|
||||
static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation) |
||||
{ |
||||
/* clear the complete notification flag */ |
||||
writel(UNIPHIER_SSCOLPQS_EF, UNIPHIER_SSCOLPQS); |
||||
|
||||
/* try until the command is successfully set */ |
||||
do { |
||||
writel(UNIPHIER_SSCOQM_S_RANGE | UNIPHIER_SSCOQM_CE | operation, |
||||
UNIPHIER_SSCOQM); |
||||
writel(start, UNIPHIER_SSCOQAD); |
||||
writel(size, UNIPHIER_SSCOQSZ); |
||||
|
||||
} while (readl(UNIPHIER_SSCOPPQSEF) & |
||||
(UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)); |
||||
|
||||
/* wait until the operation is completed */ |
||||
while (readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF) |
||||
; |
||||
} |
||||
|
||||
static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation) |
||||
{ |
||||
u32 size; |
||||
|
||||
/*
|
||||
* If start address is not aligned to cache-line, |
||||
* do cache operation for the first cache-line |
||||
*/ |
||||
start = start & ~(UNIPHIER_SSC_LINE_SIZE - 1); |
||||
|
||||
size = end - start; |
||||
|
||||
if (unlikely(size >= (u32)(-UNIPHIER_SSC_LINE_SIZE))) { |
||||
/* this means cache operation for all range */ |
||||
uniphier_cache_maint_all(operation); |
||||
return; |
||||
} |
||||
|
||||
/*
|
||||
* If end address is not aligned to cache-line, |
||||
* do cache operation for the last cache-line |
||||
*/ |
||||
size = ALIGN(size, UNIPHIER_SSC_LINE_SIZE); |
||||
|
||||
while (size) { |
||||
u32 chunk_size = size > UNIPHIER_SSC_RANGE_OP_MAX_SIZE ? |
||||
UNIPHIER_SSC_RANGE_OP_MAX_SIZE : size; |
||||
__uniphier_cache_maint_range(start, chunk_size, operation); |
||||
|
||||
start += chunk_size; |
||||
size -= chunk_size; |
||||
} |
||||
|
||||
uniphier_cache_sync(); |
||||
} |
||||
|
||||
void v7_outer_cache_flush_range(u32 start, u32 end) |
||||
{ |
||||
uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_FLUSH); |
||||
} |
||||
|
||||
void v7_outer_cache_inval_range(u32 start, u32 end) |
||||
{ |
||||
if (start & (UNIPHIER_SSC_LINE_SIZE - 1)) { |
||||
start &= ~(UNIPHIER_SSC_LINE_SIZE - 1); |
||||
__uniphier_cache_maint_range(start, UNIPHIER_SSC_LINE_SIZE, |
||||
UNIPHIER_SSCOQM_CM_FLUSH); |
||||
start += UNIPHIER_SSC_LINE_SIZE; |
||||
} |
||||
|
||||
if (start >= end) { |
||||
uniphier_cache_sync(); |
||||
return; |
||||
} |
||||
|
||||
if (end & (UNIPHIER_SSC_LINE_SIZE - 1)) { |
||||
end &= ~(UNIPHIER_SSC_LINE_SIZE - 1); |
||||
__uniphier_cache_maint_range(end, UNIPHIER_SSC_LINE_SIZE, |
||||
UNIPHIER_SSCOQM_CM_FLUSH); |
||||
} |
||||
|
||||
if (start >= end) { |
||||
uniphier_cache_sync(); |
||||
return; |
||||
} |
||||
|
||||
uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_INV); |
||||
} |
||||
|
||||
void v7_outer_cache_enable(void) |
||||
{ |
||||
u32 tmp; |
||||
|
||||
writel(U32_MAX, UNIPHIER_SSCLPDAWCR); /* activate all ways */ |
||||
tmp = readl(UNIPHIER_SSCC); |
||||
tmp |= UNIPHIER_SSCC_ON; |
||||
writel(tmp, UNIPHIER_SSCC); |
||||
} |
||||
#endif |
||||
|
||||
void v7_outer_cache_disable(void) |
||||
{ |
||||
u32 tmp; |
||||
|
||||
tmp = readl(UNIPHIER_SSCC); |
||||
tmp &= ~UNIPHIER_SSCC_ON; |
||||
writel(tmp, UNIPHIER_SSCC); |
||||
} |
||||
|
||||
void enable_caches(void) |
||||
{ |
||||
dcache_enable(); |
||||
} |
@ -1,156 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <linux/io.h> |
||||
#include <asm/armv7.h> |
||||
|
||||
#include "ssc-regs.h" |
||||
|
||||
#ifdef CONFIG_UNIPHIER_L2CACHE_ON |
||||
static void uniphier_cache_sync(void) |
||||
{ |
||||
writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */ |
||||
readl(SSCOPE); /* need a read back to confirm */ |
||||
} |
||||
|
||||
static void uniphier_cache_maint_all(u32 operation) |
||||
{ |
||||
/* clear the complete notification flag */ |
||||
writel(SSCOLPQS_EF, SSCOLPQS); |
||||
|
||||
/* try until the command is successfully set */ |
||||
do { |
||||
writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM); |
||||
} while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE)); |
||||
|
||||
/* wait until the operation is completed */ |
||||
while (readl(SSCOLPQS) != SSCOLPQS_EF) |
||||
; |
||||
|
||||
uniphier_cache_sync(); |
||||
} |
||||
|
||||
void v7_outer_cache_flush_all(void) |
||||
{ |
||||
uniphier_cache_maint_all(SSCOQM_CM_WB_INV); |
||||
} |
||||
|
||||
void v7_outer_cache_inval_all(void) |
||||
{ |
||||
uniphier_cache_maint_all(SSCOQM_CM_INV); |
||||
} |
||||
|
||||
static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation) |
||||
{ |
||||
/* clear the complete notification flag */ |
||||
writel(SSCOLPQS_EF, SSCOLPQS); |
||||
|
||||
/* try until the command is successfully set */ |
||||
do { |
||||
writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM); |
||||
writel(start, SSCOQAD); |
||||
writel(size, SSCOQSZ); |
||||
|
||||
} while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE)); |
||||
|
||||
/* wait until the operation is completed */ |
||||
while (readl(SSCOLPQS) != SSCOLPQS_EF) |
||||
; |
||||
} |
||||
|
||||
static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation) |
||||
{ |
||||
u32 size; |
||||
|
||||
/*
|
||||
* If start address is not aligned to cache-line, |
||||
* do cache operation for the first cache-line |
||||
*/ |
||||
start = start & ~(SSC_LINE_SIZE - 1); |
||||
|
||||
size = end - start; |
||||
|
||||
if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) { |
||||
/* this means cache operation for all range */ |
||||
uniphier_cache_maint_all(operation); |
||||
return; |
||||
} |
||||
|
||||
/*
|
||||
* If end address is not aligned to cache-line, |
||||
* do cache operation for the last cache-line |
||||
*/ |
||||
size = ALIGN(size, SSC_LINE_SIZE); |
||||
|
||||
while (size) { |
||||
u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ? |
||||
SSC_RANGE_OP_MAX_SIZE : size; |
||||
__uniphier_cache_maint_range(start, chunk_size, operation); |
||||
|
||||
start += chunk_size; |
||||
size -= chunk_size; |
||||
} |
||||
|
||||
uniphier_cache_sync(); |
||||
} |
||||
|
||||
void v7_outer_cache_flush_range(u32 start, u32 end) |
||||
{ |
||||
uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV); |
||||
} |
||||
|
||||
void v7_outer_cache_inval_range(u32 start, u32 end) |
||||
{ |
||||
if (start & (SSC_LINE_SIZE - 1)) { |
||||
start &= ~(SSC_LINE_SIZE - 1); |
||||
__uniphier_cache_maint_range(start, SSC_LINE_SIZE, |
||||
SSCOQM_CM_WB_INV); |
||||
start += SSC_LINE_SIZE; |
||||
} |
||||
|
||||
if (start >= end) { |
||||
uniphier_cache_sync(); |
||||
return; |
||||
} |
||||
|
||||
if (end & (SSC_LINE_SIZE - 1)) { |
||||
end &= ~(SSC_LINE_SIZE - 1); |
||||
__uniphier_cache_maint_range(end, SSC_LINE_SIZE, |
||||
SSCOQM_CM_WB_INV); |
||||
} |
||||
|
||||
if (start >= end) { |
||||
uniphier_cache_sync(); |
||||
return; |
||||
} |
||||
|
||||
uniphier_cache_maint_range(start, end, SSCOQM_CM_INV); |
||||
} |
||||
|
||||
void v7_outer_cache_enable(void) |
||||
{ |
||||
u32 tmp; |
||||
|
||||
writel(U32_MAX, SSCLPDAWCR); /* activate all ways */ |
||||
tmp = readl(SSCC); |
||||
tmp |= SSCC_ON; |
||||
writel(tmp, SSCC); |
||||
} |
||||
#endif |
||||
|
||||
void v7_outer_cache_disable(void) |
||||
{ |
||||
u32 tmp; |
||||
tmp = readl(SSCC); |
||||
tmp &= ~SSCC_ON; |
||||
writel(tmp, SSCC); |
||||
} |
||||
|
||||
void enable_caches(void) |
||||
{ |
||||
dcache_enable(); |
||||
} |
Loading…
Reference in new issue