aboutsummaryrefslogtreecommitdiff
path: root/arch/microblaze/kernel/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel/cpu')
-rw-r--r--arch/microblaze/kernel/cpu/Makefile2
-rw-r--r--arch/microblaze/kernel/cpu/cache.c168
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c25
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-static.c3
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo.c50
-rw-r--r--arch/microblaze/kernel/cpu/mb.c9
-rw-r--r--arch/microblaze/kernel/cpu/pvr.c3
7 files changed, 141 insertions, 119 deletions
diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile
index 59cc7bceaf8..fceed4edea4 100644
--- a/arch/microblaze/kernel/cpu/Makefile
+++ b/arch/microblaze/kernel/cpu/Makefile
@@ -6,7 +6,7 @@ ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_cache.o = -pg
endif
-EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
+ccflags-y := -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
-DCPU_REV=$(CPU_REV)
obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
index 109876e8d64..a6e44410672 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -17,82 +17,70 @@
static inline void __enable_icache_msr(void)
{
- __asm__ __volatile__ (" msrset r0, %0; \
- nop; " \
+ __asm__ __volatile__ (" msrset r0, %0;" \
+ "nop;" \
: : "i" (MSR_ICE) : "memory");
}
static inline void __disable_icache_msr(void)
{
- __asm__ __volatile__ (" msrclr r0, %0; \
- nop; " \
+ __asm__ __volatile__ (" msrclr r0, %0;" \
+ "nop;" \
: : "i" (MSR_ICE) : "memory");
}
static inline void __enable_dcache_msr(void)
{
- __asm__ __volatile__ (" msrset r0, %0; \
- nop; " \
- : \
- : "i" (MSR_DCE) \
- : "memory");
+ __asm__ __volatile__ (" msrset r0, %0;" \
+ "nop;" \
+ : : "i" (MSR_DCE) : "memory");
}
static inline void __disable_dcache_msr(void)
{
- __asm__ __volatile__ (" msrclr r0, %0; \
- nop; " \
- : \
- : "i" (MSR_DCE) \
- : "memory");
+ __asm__ __volatile__ (" msrclr r0, %0;" \
+ "nop; " \
+ : : "i" (MSR_DCE) : "memory");
}
static inline void __enable_icache_nomsr(void)
{
- __asm__ __volatile__ (" mfs r12, rmsr; \
- nop; \
- ori r12, r12, %0; \
- mts rmsr, r12; \
- nop; " \
- : \
- : "i" (MSR_ICE) \
- : "memory", "r12");
+ __asm__ __volatile__ (" mfs r12, rmsr;" \
+ "nop;" \
+ "ori r12, r12, %0;" \
+ "mts rmsr, r12;" \
+ "nop;" \
+ : : "i" (MSR_ICE) : "memory", "r12");
}
static inline void __disable_icache_nomsr(void)
{
- __asm__ __volatile__ (" mfs r12, rmsr; \
- nop; \
- andi r12, r12, ~%0; \
- mts rmsr, r12; \
- nop; " \
- : \
- : "i" (MSR_ICE) \
- : "memory", "r12");
+ __asm__ __volatile__ (" mfs r12, rmsr;" \
+ "nop;" \
+ "andi r12, r12, ~%0;" \
+ "mts rmsr, r12;" \
+ "nop;" \
+ : : "i" (MSR_ICE) : "memory", "r12");
}
static inline void __enable_dcache_nomsr(void)
{
- __asm__ __volatile__ (" mfs r12, rmsr; \
- nop; \
- ori r12, r12, %0; \
- mts rmsr, r12; \
- nop; " \
- : \
- : "i" (MSR_DCE) \
- : "memory", "r12");
+ __asm__ __volatile__ (" mfs r12, rmsr;" \
+ "nop;" \
+ "ori r12, r12, %0;" \
+ "mts rmsr, r12;" \
+ "nop;" \
+ : : "i" (MSR_DCE) : "memory", "r12");
}
static inline void __disable_dcache_nomsr(void)
{
- __asm__ __volatile__ (" mfs r12, rmsr; \
- nop; \
- andi r12, r12, ~%0; \
- mts rmsr, r12; \
- nop; " \
- : \
- : "i" (MSR_DCE) \
- : "memory", "r12");
+ __asm__ __volatile__ (" mfs r12, rmsr;" \
+ "nop;" \
+ "andi r12, r12, ~%0;" \
+ "mts rmsr, r12;" \
+ "nop;" \
+ : : "i" (MSR_DCE) : "memory", "r12");
}
@@ -106,7 +94,7 @@ do { \
int align = ~(cache_line_length - 1); \
end = min(start + cache_size, end); \
start &= align; \
-} while (0);
+} while (0)
/*
* Helper macro to loop over the specified cache_size/line_length and
@@ -118,18 +106,18 @@ do { \
int step = -line_length; \
WARN_ON(step >= 0); \
\
- __asm__ __volatile__ (" 1: " #op " %0, r0; \
- bgtid %0, 1b; \
- addk %0, %0, %1; \
- " : : "r" (len), "r" (step) \
+ __asm__ __volatile__ (" 1: " #op " %0, r0;" \
+ "bgtid %0, 1b;" \
+ "addk %0, %0, %1;" \
+ : : "r" (len), "r" (step) \
: "memory"); \
-} while (0);
+} while (0)
/* Used for wdc.flush/clear which can use rB for offset which is not possible
* to use for simple wdc or wic.
*
* start address is cache aligned
- * end address is not aligned, if end is aligned then I have to substract
+ * end address is not aligned, if end is aligned then I have to subtract
* cacheline length because I can't flush/invalidate the next cacheline.
* If is not, I align it because I will flush/invalidate whole line.
*/
@@ -142,28 +130,28 @@ do { \
count = end - start; \
WARN_ON(count < 0); \
\
- __asm__ __volatile__ (" 1: " #op " %0, %1; \
- bgtid %1, 1b; \
- addk %1, %1, %2; \
- " : : "r" (start), "r" (count), \
+ __asm__ __volatile__ (" 1: " #op " %0, %1;" \
+ "bgtid %1, 1b;" \
+ "addk %1, %1, %2;" \
+ : : "r" (start), "r" (count), \
"r" (step) : "memory"); \
-} while (0);
+} while (0)
/* It is used only first parameter for OP - for wic, wdc */
#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \
do { \
- int volatile temp; \
+ int volatile temp = 0; \
int align = ~(line_length - 1); \
end = ((end & align) == end) ? end - line_length : end & align; \
WARN_ON(end - start < 0); \
\
- __asm__ __volatile__ (" 1: " #op " %1, r0; \
- cmpu %0, %1, %2; \
- bgtid %0, 1b; \
- addk %1, %1, %3; \
- " : : "r" (temp), "r" (start), "r" (end),\
+ __asm__ __volatile__ (" 1: " #op " %1, r0;" \
+ "cmpu %0, %1, %2;" \
+ "bgtid %0, 1b;" \
+ "addk %1, %1, %3;" \
+ : : "r" (temp), "r" (start), "r" (end), \
"r" (line_length) : "memory"); \
-} while (0);
+} while (0)
#define ASM_LOOP
@@ -352,7 +340,7 @@ static void __invalidate_dcache_all_noirq_wt(void)
#endif
pr_debug("%s\n", __func__);
#ifdef ASM_LOOP
- CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc)
+ CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
#else
for (i = 0; i < cpuinfo.dcache_size;
i += cpuinfo.dcache_line_length)
@@ -361,7 +349,8 @@ static void __invalidate_dcache_all_noirq_wt(void)
#endif
}
-/* FIXME It is blindly invalidation as is expected
+/*
+ * FIXME It is blindly invalidation as is expected
* but can't be called on noMMU in microblaze_cache_init below
*
* MS: noMMU kernel won't boot if simple wdc is used
@@ -375,7 +364,7 @@ static void __invalidate_dcache_all_wb(void)
pr_debug("%s\n", __func__);
#ifdef ASM_LOOP
CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
- wdc)
+ wdc);
#else
for (i = 0; i < cpuinfo.dcache_size;
i += cpuinfo.dcache_line_length)
@@ -519,7 +508,7 @@ static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
struct scache *mbc;
/* new wb cache model */
-const struct scache wb_msr = {
+static const struct scache wb_msr = {
.ie = __enable_icache_msr,
.id = __disable_icache_msr,
.ifl = __flush_icache_all_noirq,
@@ -535,7 +524,7 @@ const struct scache wb_msr = {
};
/* There is only difference in ie, id, de, dd functions */
-const struct scache wb_nomsr = {
+static const struct scache wb_nomsr = {
.ie = __enable_icache_nomsr,
.id = __disable_icache_nomsr,
.ifl = __flush_icache_all_noirq,
@@ -551,7 +540,7 @@ const struct scache wb_nomsr = {
};
/* Old wt cache model with disabling irq and turn off cache */
-const struct scache wt_msr = {
+static const struct scache wt_msr = {
.ie = __enable_icache_msr,
.id = __disable_icache_msr,
.ifl = __flush_icache_all_msr_irq,
@@ -566,7 +555,7 @@ const struct scache wt_msr = {
.dinr = __invalidate_dcache_range_msr_irq_wt,
};
-const struct scache wt_nomsr = {
+static const struct scache wt_nomsr = {
.ie = __enable_icache_nomsr,
.id = __disable_icache_nomsr,
.ifl = __flush_icache_all_nomsr_irq,
@@ -582,7 +571,7 @@ const struct scache wt_nomsr = {
};
/* New wt cache model for newer Microblaze versions */
-const struct scache wt_msr_noirq = {
+static const struct scache wt_msr_noirq = {
.ie = __enable_icache_msr,
.id = __disable_icache_msr,
.ifl = __flush_icache_all_noirq,
@@ -597,7 +586,7 @@ const struct scache wt_msr_noirq = {
.dinr = __invalidate_dcache_range_nomsr_wt,
};
-const struct scache wt_nomsr_noirq = {
+static const struct scache wt_nomsr_noirq = {
.ie = __enable_icache_nomsr,
.id = __disable_icache_nomsr,
.ifl = __flush_icache_all_noirq,
@@ -616,49 +605,48 @@ const struct scache wt_nomsr_noirq = {
#define CPUVER_7_20_A 0x0c
#define CPUVER_7_20_D 0x0f
-#define INFO(s) printk(KERN_INFO "cache: " s "\n");
-
void microblaze_cache_init(void)
{
if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
if (cpuinfo.dcache_wb) {
- INFO("wb_msr");
+ pr_info("wb_msr\n");
mbc = (struct scache *)&wb_msr;
- if (cpuinfo.ver_code < CPUVER_7_20_D) {
+ if (cpuinfo.ver_code <= CPUVER_7_20_D) {
/* MS: problem with signal handling - hw bug */
- INFO("WB won't work properly");
+ pr_info("WB won't work properly\n");
}
} else {
if (cpuinfo.ver_code >= CPUVER_7_20_A) {
- INFO("wt_msr_noirq");
+ pr_info("wt_msr_noirq\n");
mbc = (struct scache *)&wt_msr_noirq;
} else {
- INFO("wt_msr");
+ pr_info("wt_msr\n");
mbc = (struct scache *)&wt_msr;
}
}
} else {
if (cpuinfo.dcache_wb) {
- INFO("wb_nomsr");
+ pr_info("wb_nomsr\n");
mbc = (struct scache *)&wb_nomsr;
- if (cpuinfo.ver_code < CPUVER_7_20_D) {
+ if (cpuinfo.ver_code <= CPUVER_7_20_D) {
/* MS: problem with signal handling - hw bug */
- INFO("WB won't work properly");
+ pr_info("WB won't work properly\n");
}
} else {
if (cpuinfo.ver_code >= CPUVER_7_20_A) {
- INFO("wt_nomsr_noirq");
+ pr_info("wt_nomsr_noirq\n");
mbc = (struct scache *)&wt_nomsr_noirq;
} else {
- INFO("wt_nomsr");
+ pr_info("wt_nomsr\n");
mbc = (struct scache *)&wt_nomsr;
}
}
}
-/* FIXME Invalidation is done in U-BOOT
- * WT cache: Data is already written to main memory
- * WB cache: Discard data on noMMU which caused that kernel doesn't boot
- */
+ /*
+ * FIXME Invalidation is done in U-BOOT
+ * WT cache: Data is already written to main memory
+ * WB cache: Discard data on noMMU which caused that kernel doesn't boot
+ */
/* invalidate_dcache(); */
enable_dcache();
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
index f70a6047f08..93c26cf50de 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -27,7 +27,7 @@
early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
#else
#define err_printk(x) \
- printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n");
+ pr_info("ERROR: Microblaze " x "-different for PVR and DTS\n");
#endif
void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
@@ -38,12 +38,11 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
CI(ver_code, VERSION);
if (!ci->ver_code) {
- printk(KERN_ERR "ERROR: MB has broken PVR regs "
- "-> use DTS setting\n");
+ pr_err("ERROR: MB has broken PVR regs -> use DTS setting\n");
return;
}
- temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |\
+ temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |
PVR_USE_PCMP_INSTR(pvr) | PVR_USE_DIV(pvr);
if (ci->use_instr != temp)
err_printk("BARREL, MSR, PCMP or DIV");
@@ -59,19 +58,20 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
err_printk("HW_FPU");
ci->use_fpu = temp;
- ci->use_exc = PVR_OPCODE_0x0_ILLEGAL(pvr) |\
- PVR_UNALIGNED_EXCEPTION(pvr) |\
- PVR_ILL_OPCODE_EXCEPTION(pvr) |\
- PVR_IOPB_BUS_EXCEPTION(pvr) |\
- PVR_DOPB_BUS_EXCEPTION(pvr) |\
- PVR_DIV_ZERO_EXCEPTION(pvr) |\
- PVR_FPU_EXCEPTION(pvr) |\
+ ci->use_exc = PVR_OPCODE_0x0_ILLEGAL(pvr) |
+ PVR_UNALIGNED_EXCEPTION(pvr) |
+ PVR_ILL_OPCODE_EXCEPTION(pvr) |
+ PVR_IOPB_BUS_EXCEPTION(pvr) |
+ PVR_DOPB_BUS_EXCEPTION(pvr) |
+ PVR_DIV_ZERO_EXCEPTION(pvr) |
+ PVR_FPU_EXCEPTION(pvr) |
PVR_FSL_EXCEPTION(pvr);
CI(pvr_user1, USER1);
CI(pvr_user2, USER2);
CI(mmu, USE_MMU);
+ CI(mmu_privins, MMU_PRIVINS);
CI(endian, ENDIAN);
CI(use_icache, USE_ICACHE);
@@ -112,7 +112,4 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK);
CI(fpga_family_code, TARGET_FAMILY);
-
- /* take timebase-frequency from DTS */
- ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
}
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
index b16b994ca3d..4854285b26e 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -113,12 +113,11 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
ci->num_rd_brk = fcpu(cpu, "xlnx,number-of-rd-addr-brk");
ci->num_wr_brk = fcpu(cpu, "xlnx,number-of-wr-addr-brk");
- ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
-
ci->pvr_user1 = fcpu(cpu, "xlnx,pvr-user1");
ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+ ci->mmu_privins = fcpu(cpu, "xlnx,mmu-privileged-instr");
ci->endian = fcpu(cpu, "xlnx,endianness");
ci->ver_code = 0;
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index 2c309fccf23..234acad79b9 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -8,6 +8,7 @@
* for more details.
*/
+#include <linux/clk.h>
#include <linux/init.h>
#include <asm/cpuinfo.h>
#include <asm/pvr.h>
@@ -33,6 +34,15 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
{"7.30.b", 0x11},
{"8.00.a", 0x12},
{"8.00.b", 0x13},
+ {"8.10.a", 0x14},
+ {"8.20.a", 0x15},
+ {"8.20.b", 0x16},
+ {"8.30.a", 0x17},
+ {"8.40.a", 0x18},
+ {"8.40.b", 0x19},
+ {"8.50.a", 0x1a},
+ {"9.0", 0x1b},
+ {"9.1", 0x1d},
{NULL, 0},
};
@@ -53,38 +63,62 @@ const struct family_string_key family_string_lookup[] = {
{"virtex6", 0xe},
/* FIXME There is no key code defined for spartan2 */
{"spartan2", 0xf0},
+ {"kintex7", 0x10},
+ {"artix7", 0x11},
+ {"zynq7000", 0x12},
{NULL, 0},
};
struct cpuinfo cpuinfo;
+static struct device_node *cpu;
void __init setup_cpuinfo(void)
{
- struct device_node *cpu = NULL;
-
cpu = (struct device_node *) of_find_node_by_type(NULL, "cpu");
if (!cpu)
- printk(KERN_ERR "You don't have cpu!!!\n");
+ pr_err("You don't have cpu!!!\n");
- printk(KERN_INFO "%s: initialising\n", __func__);
+ pr_info("%s: initialising\n", __func__);
switch (cpu_has_pvr()) {
case 0:
- printk(KERN_WARNING
- "%s: No PVR support. Using static CPU info from FDT\n",
+ pr_warn("%s: No PVR support. Using static CPU info from FDT\n",
__func__);
set_cpuinfo_static(&cpuinfo, cpu);
break;
/* FIXME I found weird behavior with MB 7.00.a/b 7.10.a
* please do not use FULL PVR with MMU */
case 1:
- printk(KERN_INFO "%s: Using full CPU PVR support\n",
+ pr_info("%s: Using full CPU PVR support\n",
__func__);
set_cpuinfo_static(&cpuinfo, cpu);
set_cpuinfo_pvr_full(&cpuinfo, cpu);
break;
default:
- printk(KERN_WARNING "%s: Unsupported PVR setting\n", __func__);
+ pr_warn("%s: Unsupported PVR setting\n", __func__);
set_cpuinfo_static(&cpuinfo, cpu);
}
+
+ if (cpuinfo.mmu_privins)
+ pr_warn("%s: Stream instructions enabled"
+ " - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
+}
+
+void __init setup_cpuinfo_clk(void)
+{
+ struct clk *clk;
+
+ clk = of_clk_get(cpu, 0);
+ if (IS_ERR(clk)) {
+ pr_err("ERROR: CPU CCF input clock not found\n");
+ /* take timebase-frequency from DTS */
+ cpuinfo.cpu_clock_freq = fcpu(cpu, "timebase-frequency");
+ } else {
+ cpuinfo.cpu_clock_freq = clk_get_rate(clk);
+ }
+
+ if (!cpuinfo.cpu_clock_freq) {
+ pr_err("ERROR: CPU clock frequency not setup\n");
+ BUG();
+ }
}
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index b4048af0261..7b5dca7ed39 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -97,6 +97,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
(cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
(cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
+ count += seq_printf(m,
+ "Stream-insns:\t%sprivileged\n",
+ cpuinfo.mmu_privins ? "un" : "");
+
if (cpuinfo.use_icache)
count += seq_printf(m,
"Icache:\t\t%ukB\tline length:\t%dB\n",
@@ -110,10 +114,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"Dcache:\t\t%ukB\tline length:\t%dB\n",
cpuinfo.dcache_size >> 10,
cpuinfo.dcache_line_length);
+ seq_printf(m, "Dcache-Policy:\t");
if (cpuinfo.dcache_wb)
- count += seq_printf(m, "\t\twrite-back\n");
+ count += seq_printf(m, "write-back\n");
else
- count += seq_printf(m, "\t\twrite-through\n");
+ count += seq_printf(m, "write-through\n");
} else
count += seq_printf(m, "Dcache:\t\tno\n");
diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c
index 488c1ed24e3..8d0dc6db48c 100644
--- a/arch/microblaze/kernel/cpu/pvr.c
+++ b/arch/microblaze/kernel/cpu/pvr.c
@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/compiler.h>
-#include <asm/system.h>
#include <asm/exceptions.h>
#include <asm/pvr.h>
@@ -28,7 +27,7 @@
tmp = 0x0; /* Prevent warning about unused */ \
__asm__ __volatile__ ( \
"mfs %0, rpvr" #pvrid ";" \
- : "=r" (tmp) : : "memory"); \
+ : "=r" (tmp) : : "memory"); \
val = tmp; \
}