summaryrefslogtreecommitdiff
path: root/arch/microblaze/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel')
-rw-r--r--arch/microblaze/kernel/Makefile2
-rw-r--r--arch/microblaze/kernel/heartbeat.c4
-rw-r--r--arch/microblaze/kernel/intc.c51
-rw-r--r--arch/microblaze/kernel/platform.c30
-rw-r--r--arch/microblaze/kernel/process.c1
-rw-r--r--arch/microblaze/kernel/signal.c2
-rw-r--r--arch/microblaze/kernel/syscall_table.S8
-rw-r--r--arch/microblaze/kernel/timer.c66
8 files changed, 130 insertions, 34 deletions
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index 5b0e512c78e5..08d50cc55e7d 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -16,7 +16,7 @@ extra-y := head.o vmlinux.lds
obj-y += dma.o exceptions.o \
hw_exception_handler.o intc.o irq.o \
- process.o prom.o prom_parse.o ptrace.o \
+ platform.o process.o prom.o prom_parse.o ptrace.o \
reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
obj-y += cpu/
diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c
index 1879a0527776..4643e3ab9414 100644
--- a/arch/microblaze/kernel/heartbeat.c
+++ b/arch/microblaze/kernel/heartbeat.c
@@ -17,7 +17,7 @@
static unsigned int base_addr;
-void heartbeat(void)
+void microblaze_heartbeat(void)
{
static unsigned int cnt, period, dist;
@@ -42,7 +42,7 @@ void heartbeat(void)
}
}
-void setup_heartbeat(void)
+void microblaze_setup_heartbeat(void)
{
struct device_node *gpio = NULL;
int *prop;
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index 581451ad4687..15c7c12ea0e7 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -32,6 +32,29 @@ static void __iomem *intc_baseaddr;
#define MER_ME (1<<0)
#define MER_HIE (1<<1)
+static unsigned int (*read_fn)(void __iomem *);
+static void (*write_fn)(u32, void __iomem *);
+
+static void intc_write32(u32 val, void __iomem *addr)
+{
+ iowrite32(val, addr);
+}
+
+static unsigned int intc_read32(void __iomem *addr)
+{
+ return ioread32(addr);
+}
+
+static void intc_write32_be(u32 val, void __iomem *addr)
+{
+ iowrite32be(val, addr);
+}
+
+static unsigned int intc_read32_be(void __iomem *addr)
+{
+ return ioread32be(addr);
+}
+
static void intc_enable_or_unmask(struct irq_data *d)
{
unsigned long mask = 1 << d->hwirq;
@@ -43,21 +66,21 @@ static void intc_enable_or_unmask(struct irq_data *d)
* acks the irq before calling the interrupt handler
*/
if (irqd_is_level_type(d))
- out_be32(intc_baseaddr + IAR, mask);
+ write_fn(mask, intc_baseaddr + IAR);
- out_be32(intc_baseaddr + SIE, mask);
+ write_fn(mask, intc_baseaddr + SIE);
}
static void intc_disable_or_mask(struct irq_data *d)
{
pr_debug("disable: %ld\n", d->hwirq);
- out_be32(intc_baseaddr + CIE, 1 << d->hwirq);
+ write_fn(1 << d->hwirq, intc_baseaddr + CIE);
}
static void intc_ack(struct irq_data *d)
{
pr_debug("ack: %ld\n", d->hwirq);
- out_be32(intc_baseaddr + IAR, 1 << d->hwirq);
+ write_fn(1 << d->hwirq, intc_baseaddr + IAR);
}
static void intc_mask_ack(struct irq_data *d)
@@ -65,8 +88,8 @@ static void intc_mask_ack(struct irq_data *d)
unsigned long mask = 1 << d->hwirq;
pr_debug("disable_and_ack: %ld\n", d->hwirq);
- out_be32(intc_baseaddr + CIE, mask);
- out_be32(intc_baseaddr + IAR, mask);
+ write_fn(mask, intc_baseaddr + CIE);
+ write_fn(mask, intc_baseaddr + IAR);
}
static struct irq_chip intc_dev = {
@@ -83,7 +106,7 @@ unsigned int get_irq(void)
{
unsigned int hwirq, irq = -1;
- hwirq = in_be32(intc_baseaddr + IVR);
+ hwirq = read_fn(intc_baseaddr + IVR);
if (hwirq != -1U)
irq = irq_find_mapping(root_domain, hwirq);
@@ -140,17 +163,25 @@ static int __init xilinx_intc_of_init(struct device_node *intc,
pr_info("%s: num_irq=%d, edge=0x%x\n",
intc->full_name, nr_irq, intr_mask);
+ write_fn = intc_write32;
+ read_fn = intc_read32;
+
/*
* Disable all external interrupts until they are
* explicity requested.
*/
- out_be32(intc_baseaddr + IER, 0);
+ write_fn(0, intc_baseaddr + IER);
/* Acknowledge any pending interrupts just in case. */
- out_be32(intc_baseaddr + IAR, 0xffffffff);
+ write_fn(0xffffffff, intc_baseaddr + IAR);
/* Turn on the Master Enable. */
- out_be32(intc_baseaddr + MER, MER_HIE | MER_ME);
+ write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
+ if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
+ write_fn = intc_write32_be;
+ read_fn = intc_read32_be;
+ write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
+ }
/* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
* lazy and Michal can clean it up to something nicer when he tests
diff --git a/arch/microblaze/kernel/platform.c b/arch/microblaze/kernel/platform.c
new file mode 100644
index 000000000000..b9529caa507a
--- /dev/null
+++ b/arch/microblaze/kernel/platform.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Michal Simek <monstr@monstr.eu>
+ *
+ * based on virtex.c file
+ *
+ * Copyright 2007 Secret Lab Technologies Ltd.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+#include <asm/setup.h>
+
+static struct of_device_id xilinx_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ { .compatible = "xlnx,compound", },
+ {}
+};
+
+static int __init microblaze_device_probe(void)
+{
+ of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
+ of_platform_reset_gpio_probe();
+ return 0;
+}
+device_initcall(microblaze_device_probe);
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 7d1a9c8b1f3d..b2dd37196b3b 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -8,6 +8,7 @@
* for more details.
*/
+#include <linux/cpu.h>
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/pm.h>
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index d26d7e7a6913..49a07a4d76d0 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -216,7 +216,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* MS: I need add offset in page */
address += ((unsigned long)frame->tramp) & ~PAGE_MASK;
/* MS address is virtual */
- address = virt_to_phys(address);
+ address = __virt_to_phys(address);
invalidate_icache_range(address, address + 8);
flush_dcache_range(address, address + 8);
}
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index b882ad50535b..329dfbad810b 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -308,7 +308,7 @@ ENTRY(sys_call_table)
.long sys_readlinkat /* 305 */
.long sys_fchmodat
.long sys_faccessat
- .long sys_ni_syscall /* pselect6 */
+ .long sys_pselect6
.long sys_ppoll
.long sys_unshare /* 310 */
.long sys_set_robust_list
@@ -363,8 +363,8 @@ ENTRY(sys_call_table)
.long sys_sendmsg /* 360 */
.long sys_recvmsg
.long sys_accept4
- .long sys_ni_syscall
- .long sys_ni_syscall
+ .long sys_preadv
+ .long sys_pwritev
.long sys_rt_tgsigqueueinfo /* 365 */
.long sys_perf_event_open
.long sys_recvmmsg
@@ -381,3 +381,5 @@ ENTRY(sys_call_table)
.long sys_process_vm_writev
.long sys_kcmp
.long sys_finit_module
+ .long sys_sched_setattr
+ .long sys_sched_getattr
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index fb0c61443f19..dd96f0e4bfa2 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -43,10 +43,33 @@ static unsigned int timer_clock_freq;
#define TCSR_PWMA (1<<9)
#define TCSR_ENALL (1<<10)
+static unsigned int (*read_fn)(void __iomem *);
+static void (*write_fn)(u32, void __iomem *);
+
+static void timer_write32(u32 val, void __iomem *addr)
+{
+ iowrite32(val, addr);
+}
+
+static unsigned int timer_read32(void __iomem *addr)
+{
+ return ioread32(addr);
+}
+
+static void timer_write32_be(u32 val, void __iomem *addr)
+{
+ iowrite32be(val, addr);
+}
+
+static unsigned int timer_read32_be(void __iomem *addr)
+{
+ return ioread32be(addr);
+}
+
static inline void xilinx_timer0_stop(void)
{
- out_be32(timer_baseaddr + TCSR0,
- in_be32(timer_baseaddr + TCSR0) & ~TCSR_ENT);
+ write_fn(read_fn(timer_baseaddr + TCSR0) & ~TCSR_ENT,
+ timer_baseaddr + TCSR0);
}
static inline void xilinx_timer0_start_periodic(unsigned long load_val)
@@ -54,10 +77,10 @@ static inline void xilinx_timer0_start_periodic(unsigned long load_val)
if (!load_val)
load_val = 1;
/* loading value to timer reg */
- out_be32(timer_baseaddr + TLR0, load_val);
+ write_fn(load_val, timer_baseaddr + TLR0);
/* load the initial value */
- out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
+ write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);
/* see timer data sheet for detail
* !ENALL - don't enable 'em all
@@ -72,8 +95,8 @@ static inline void xilinx_timer0_start_periodic(unsigned long load_val)
* UDT - set the timer as down counter
* !MDT0 - generate mode
*/
- out_be32(timer_baseaddr + TCSR0,
- TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
+ write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
+ timer_baseaddr + TCSR0);
}
static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
@@ -81,13 +104,13 @@ static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
if (!load_val)
load_val = 1;
/* loading value to timer reg */
- out_be32(timer_baseaddr + TLR0, load_val);
+ write_fn(load_val, timer_baseaddr + TLR0);
/* load the initial value */
- out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
+ write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);
- out_be32(timer_baseaddr + TCSR0,
- TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
+ write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
+ timer_baseaddr + TCSR0);
}
static int xilinx_timer_set_next_event(unsigned long delta,
@@ -133,14 +156,14 @@ static struct clock_event_device clockevent_xilinx_timer = {
static inline void timer_ack(void)
{
- out_be32(timer_baseaddr + TCSR0, in_be32(timer_baseaddr + TCSR0));
+ write_fn(read_fn(timer_baseaddr + TCSR0), timer_baseaddr + TCSR0);
}
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = &clockevent_xilinx_timer;
#ifdef CONFIG_HEART_BEAT
- heartbeat();
+ microblaze_heartbeat();
#endif
timer_ack();
evt->event_handler(evt);
@@ -169,7 +192,7 @@ static __init void xilinx_clockevent_init(void)
static u64 xilinx_clock_read(void)
{
- return in_be32(timer_baseaddr + TCR1);
+ return read_fn(timer_baseaddr + TCR1);
}
static cycle_t xilinx_read(struct clocksource *cs)
@@ -217,10 +240,10 @@ static int __init xilinx_clocksource_init(void)
panic("failed to register clocksource");
/* stop timer1 */
- out_be32(timer_baseaddr + TCSR1,
- in_be32(timer_baseaddr + TCSR1) & ~TCSR_ENT);
+ write_fn(read_fn(timer_baseaddr + TCSR1) & ~TCSR_ENT,
+ timer_baseaddr + TCSR1);
/* start timer1 - up counting without interrupt */
- out_be32(timer_baseaddr + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
+ write_fn(TCSR_TINT|TCSR_ENT|TCSR_ARHT, timer_baseaddr + TCSR1);
/* register timecounter - for ftrace support */
init_xilinx_timecounter();
@@ -245,6 +268,15 @@ static void __init xilinx_timer_init(struct device_node *timer)
BUG();
}
+ write_fn = timer_write32;
+ read_fn = timer_read32;
+
+ write_fn(TCSR_MDT, timer_baseaddr + TCSR0);
+ if (!(read_fn(timer_baseaddr + TCSR0) & TCSR_MDT)) {
+ write_fn = timer_write32_be;
+ read_fn = timer_read32_be;
+ }
+
irq = irq_of_parse_and_map(timer, 0);
of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
@@ -274,7 +306,7 @@ static void __init xilinx_timer_init(struct device_node *timer)
setup_irq(irq, &timer_irqaction);
#ifdef CONFIG_HEART_BEAT
- setup_heartbeat();
+ microblaze_setup_heartbeat();
#endif
xilinx_clocksource_init();
xilinx_clockevent_init();