1
0
Fork 0

Microblaze patches for 3.12-rc1

PCI fixes
 Selfmod code removing
 Intc and timer fixes
 Adding new MB versions
 Minor fixes
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (GNU/Linux)
 
 iEYEABECAAYFAlIpmwUACgkQykllyylKDCGuTACgi6LLlEhw+t8/kg7HIlT5FZDK
 5roAn1mnev4didR4F8hbhcCag09vjJJu
 =P5in
 -----END PGP SIGNATURE-----

Merge tag 'microblaze-3.12-rc1' of git://git.monstr.eu/linux-2.6-microblaze

Pull Microblaze patches from Michal Simek:
 - PCI fixes
 - Selfmod code removing
 - Intc and timer fixes
 - Adding new MB versions
 - Minor fixes

* tag 'microblaze-3.12-rc1' of git://git.monstr.eu/linux-2.6-microblaze:
  microblaze: Show message when reset gpio is not present
  microblaze: Add linux.bin.ub target
  microblaze: Add PVR version string for MB v9.0 and v9.1
  microblaze: timer: Replace microblaze_ prefix by xilinx_
  microblaze: timer: Update header
  microblaze: timer: Remove unused header
  microblaze: timer: Clear driver init function
  microblaze: timer: Use CLKSRC_OF initialization
  microblaze: intc: Remove unused header
  microblaze: intc: Clean driver init function
  microblaze: intc: Using irqchip
  microblaze: intc: Update header
  microblaze: intc: Remove unused headers
  microblaze: Remove selfmodified feature
  of/pci: Use of_pci_range_parser
hifive-unleashed-5.1
Linus Torvalds 2013-09-06 10:58:34 -07:00
commit 5872c84027
14 changed files with 177 additions and 366 deletions

View File

@ -29,6 +29,7 @@ config MICROBLAZE
select GENERIC_IDLE_POLL_SETUP
select MODULES_USE_ELF_RELA
select CLONE_BACKWARDS3
select CLKSRC_OF
config SWAP
def_bool n

View File

@ -72,7 +72,7 @@ all: linux.bin
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
linux.bin linux.bin.gz: vmlinux
linux.bin linux.bin.gz linux.bin.ub: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
simpleImage.%: vmlinux
@ -81,6 +81,7 @@ simpleImage.%: vmlinux
define archhelp
echo '* linux.bin - Create raw binary'
echo ' linux.bin.gz - Create compressed raw binary'
echo ' linux.bin.ub - Create U-Boot wrapped raw binary'
echo ' simpleImage.<dt> - ELF image with $(arch)/boot/dts/<dt>.dts linked in'
echo ' - stripped elf with fdt blob'
echo ' simpleImage.<dt>.unstrip - full ELF image with fdt blob'

View File

@ -2,12 +2,15 @@
# arch/microblaze/boot/Makefile
#
targets := linux.bin linux.bin.gz simpleImage.%
targets := linux.bin linux.bin.gz linux.bin.ub simpleImage.%
OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary
$(obj)/linux.bin: vmlinux FORCE
$(call if_changed,objcopy)
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
$(obj)/linux.bin.ub: $(obj)/linux.bin FORCE
$(call if_changed,uimage)
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
@ -22,8 +25,6 @@ quiet_cmd_strip = STRIP $@
cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \
-K _fdt_start vmlinux -o $@
UIMAGE_IN = $@
UIMAGE_OUT = $@.ub
UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR)
$(obj)/simpleImage.%: vmlinux FORCE

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef _ASM_MICROBLAZE_SELFMOD_H
#define _ASM_MICROBLAZE_SELFMOD_H
/*
* BARRIER_BASE_ADDR is constant address for selfmod function.
* do not change this value - selfmod function is in
* arch/microblaze/kernel/selfmod.c: selfmod_function()
*
* last 16 bits is used for storing register offset
*/
#define BARRIER_BASE_ADDR 0x1234ff00
void selfmod_function(const int *arr_fce, const unsigned int base);
#endif /* _ASM_MICROBLAZE_SELFMOD_H */

View File

@ -7,7 +7,6 @@ ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_timer.o = -pg
CFLAGS_REMOVE_intc.o = -pg
CFLAGS_REMOVE_early_printk.o = -pg
CFLAGS_REMOVE_selfmod.o = -pg
CFLAGS_REMOVE_heartbeat.o = -pg
CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_process.o = -pg
@ -23,7 +22,6 @@ obj-y += dma.o exceptions.o \
obj-y += cpu/
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SELFMOD) += selfmod.o
obj-$(CONFIG_HEART_BEAT) += heartbeat.o
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
obj-$(CONFIG_MMU) += misc.o

View File

@ -39,6 +39,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
{"8.30.a", 0x17},
{"8.40.a", 0x18},
{"8.40.b", 0x19},
{"9.0", 0x1b},
{"9.1", 0x1d},
{NULL, 0},
};

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
* Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
* Copyright (C) 2012-2013 Xilinx, Inc.
* Copyright (C) 2007-2009 PetaLogix
* Copyright (C) 2006 Atmark Techno, Inc.
*
@ -8,23 +9,15 @@
* for more details.
*/
#include <linux/init.h>
#include <linux/irqdomain.h>
#include <linux/irq.h>
#include <asm/page.h>
#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/bug.h>
#include <asm/prom.h>
#include <asm/irq.h>
#include "../../drivers/irqchip/irqchip.h"
#ifdef CONFIG_SELFMOD_INTC
#include <asm/selfmod.h>
#define INTC_BASE BARRIER_BASE_ADDR
#else
static unsigned int intc_baseaddr;
#define INTC_BASE intc_baseaddr
#endif
static void __iomem *intc_baseaddr;
/* No one else should require these constants, so define them locally here. */
#define ISR 0x00 /* Interrupt Status Register */
@ -50,21 +43,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_BASE + IAR, mask);
out_be32(intc_baseaddr + IAR, mask);
out_be32(INTC_BASE + SIE, mask);
out_be32(intc_baseaddr + SIE, mask);
}
static void intc_disable_or_mask(struct irq_data *d)
{
pr_debug("disable: %ld\n", d->hwirq);
out_be32(INTC_BASE + CIE, 1 << d->hwirq);
out_be32(intc_baseaddr + CIE, 1 << d->hwirq);
}
static void intc_ack(struct irq_data *d)
{
pr_debug("ack: %ld\n", d->hwirq);
out_be32(INTC_BASE + IAR, 1 << d->hwirq);
out_be32(intc_baseaddr + IAR, 1 << d->hwirq);
}
static void intc_mask_ack(struct irq_data *d)
@ -72,8 +65,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_BASE + CIE, mask);
out_be32(INTC_BASE + IAR, mask);
out_be32(intc_baseaddr + CIE, mask);
out_be32(intc_baseaddr + IAR, mask);
}
static struct irq_chip intc_dev = {
@ -90,7 +83,7 @@ unsigned int get_irq(void)
{
unsigned int hwirq, irq = -1;
hwirq = in_be32(INTC_BASE + IVR);
hwirq = in_be32(intc_baseaddr + IVR);
if (hwirq != -1U)
irq = irq_find_mapping(root_domain, hwirq);
@ -120,40 +113,32 @@ static const struct irq_domain_ops xintc_irq_domain_ops = {
.map = xintc_map,
};
void __init init_IRQ(void)
static int __init xilinx_intc_of_init(struct device_node *intc,
struct device_node *parent)
{
u32 nr_irq, intr_mask;
struct device_node *intc = NULL;
#ifdef CONFIG_SELFMOD_INTC
unsigned int intc_baseaddr = 0;
static int arr_func[] = {
(int)&get_irq,
(int)&intc_enable_or_unmask,
(int)&intc_disable_or_mask,
(int)&intc_mask_ack,
(int)&intc_ack,
(int)&intc_end,
0
};
#endif
intc = of_find_compatible_node(NULL, NULL, "xlnx,xps-intc-1.00.a");
BUG_ON(!intc);
int ret;
intc_baseaddr = be32_to_cpup(of_get_property(intc, "reg", NULL));
intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
nr_irq = be32_to_cpup(of_get_property(intc,
"xlnx,num-intr-inputs", NULL));
intc_baseaddr = of_iomap(intc, 0);
BUG_ON(!intc_baseaddr);
ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
if (ret < 0) {
pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__);
return -EINVAL;
}
ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask);
if (ret < 0) {
pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__);
return -EINVAL;
}
intr_mask =
be32_to_cpup(of_get_property(intc, "xlnx,kind-of-intr", NULL));
if (intr_mask > (u32)((1ULL << nr_irq) - 1))
pr_info(" ERROR: Mismatch in kind-of-intr param\n");
#ifdef CONFIG_SELFMOD_INTC
selfmod_function((int *) arr_func, intc_baseaddr);
#endif
pr_info("%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
intc->name, intc_baseaddr, nr_irq, intr_mask);
pr_info("%s: num_irq=%d, edge=0x%x\n",
intc->full_name, nr_irq, intr_mask);
/*
* Disable all external interrupts until they are
@ -174,4 +159,8 @@ void __init init_IRQ(void)
(void *)intr_mask);
irq_set_default_host(root_domain);
return 0;
}
IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);

View File

@ -17,10 +17,8 @@
#include <linux/seq_file.h>
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/of_irq.h>
#include <linux/export.h>
#include <asm/prom.h>
static u32 concurrent_irq;
@ -47,3 +45,9 @@ next_irq:
set_irq_regs(old_regs);
trace_hardirqs_on();
}
void __init init_IRQ(void)
{
/* process the entire interrupt tree in one go */
irqchip_init();
}

View File

@ -67,7 +67,11 @@ static void gpio_system_reset(void)
pr_notice("Reset GPIO unavailable - halting!\n");
}
#else
#define gpio_system_reset() do {} while (0)
static void gpio_system_reset(void)
{
pr_notice("No reset GPIO present - halting!\n");
}
void of_platform_reset_gpio_probe(void)
{
return;

View File

@ -1,81 +0,0 @@
/*
* Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
* Copyright (C) 2009 PetaLogix
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/interrupt.h>
#include <asm/selfmod.h>
#undef DEBUG
#if __GNUC__ > 3
#error GCC 4 unsupported SELFMOD. Please disable SELFMOD from menuconfig.
#endif
#define OPCODE_IMM 0xB0000000
#define OPCODE_LWI 0xE8000000
#define OPCODE_LWI_MASK 0xEC000000
#define OPCODE_RTSD 0xB60F0008 /* return from func: rtsd r15, 8 */
#define OPCODE_ADDIK 0x30000000
#define OPCODE_ADDIK_MASK 0xFC000000
#define IMM_BASE (OPCODE_IMM | (BARRIER_BASE_ADDR >> 16))
#define LWI_BASE (OPCODE_LWI | (BARRIER_BASE_ADDR & 0x0000ff00))
#define LWI_BASE_MASK (OPCODE_LWI_MASK | (BARRIER_BASE_ADDR & 0x0000ff00))
#define ADDIK_BASE (OPCODE_ADDIK | (BARRIER_BASE_ADDR & 0x0000ff00))
#define ADDIK_BASE_MASK (OPCODE_ADDIK_MASK | (BARRIER_BASE_ADDR & 0x0000ff00))
#define MODIFY_INSTR { \
pr_debug("%s: curr instr, (%d):0x%x, next(%d):0x%x\n", \
__func__, i, addr[i], i + 1, addr[i + 1]); \
addr[i] = OPCODE_IMM + (base >> 16); \
/* keep instruction opcode and add only last 16bits */ \
addr[i + 1] = (addr[i + 1] & 0xffff00ff) + (base & 0xffff); \
__invalidate_icache(addr[i]); \
__invalidate_icache(addr[i + 1]); \
pr_debug("%s: hack instr, (%d):0x%x, next(%d):0x%x\n", \
__func__, i, addr[i], i + 1, addr[i + 1]); }
/* NOTE
* self-modified part of code for improvement of interrupt controller
* save instruction in interrupt rutine
*/
void selfmod_function(const int *arr_fce, const unsigned int base)
{
unsigned int flags, i, j, *addr = NULL;
local_irq_save(flags);
__disable_icache();
/* zero terminated array */
for (j = 0; arr_fce[j] != 0; j++) {
/* get start address of function */
addr = (unsigned int *) arr_fce[j];
pr_debug("%s: func(%d) at 0x%x\n",
__func__, j, (unsigned int) addr);
for (i = 0; ; i++) {
pr_debug("%s: instruction code at %d: 0x%x\n",
__func__, i, addr[i]);
if (addr[i] == IMM_BASE) {
/* detecting of lwi (0xE8) or swi (0xF8) instr
* I can detect both opcode with one mask */
if ((addr[i + 1] & LWI_BASE_MASK) == LWI_BASE) {
MODIFY_INSTR;
} else /* detection addik for ack */
if ((addr[i + 1] & ADDIK_BASE_MASK) ==
ADDIK_BASE) {
MODIFY_INSTR;
}
} else if (addr[i] == OPCODE_RTSD) {
/* return from function means end of function */
pr_debug("%s: end of array %d\n", __func__, i);
break;
}
}
}
local_irq_restore(flags);
} /* end of self-modified code */

View File

@ -9,6 +9,7 @@
*/
#include <linux/init.h>
#include <linux/clocksource.h>
#include <linux/string.h>
#include <linux/seq_file.h>
#include <linux/cpu.h>
@ -68,10 +69,6 @@ void __init setup_arch(char **cmdline_p)
xilinx_pci_init();
#if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
pr_notice("Self modified code enable\n");
#endif
#ifdef CONFIG_VT
#if defined(CONFIG_XILINX_CONSOLE)
conswitchp = &xil_con;
@ -196,6 +193,11 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
per_cpu(CURRENT_SAVE, 0) = (unsigned long)current;
}
void __init time_init(void)
{
clocksource_of_init();
}
#ifdef CONFIG_DEBUG_FS
struct dentry *of_debugfs_root;

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
* Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
* Copyright (C) 2012-2013 Xilinx, Inc.
* Copyright (C) 2007-2009 PetaLogix
* Copyright (C) 2006 Atmark Techno, Inc.
*
@ -8,34 +9,16 @@
* for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/interrupt.h>
#include <linux/profile.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/io.h>
#include <linux/bug.h>
#include <linux/of_address.h>
#include <asm/cpuinfo.h>
#include <asm/setup.h>
#include <asm/prom.h>
#include <asm/irq.h>
#include <linux/cnt32_to_63.h>
#ifdef CONFIG_SELFMOD_TIMER
#include <asm/selfmod.h>
#define TIMER_BASE BARRIER_BASE_ADDR
#else
static unsigned int timer_baseaddr;
#define TIMER_BASE timer_baseaddr
#endif
static void __iomem *timer_baseaddr;
static unsigned int freq_div_hz;
static unsigned int timer_clock_freq;
@ -59,19 +42,21 @@ static unsigned int timer_clock_freq;
#define TCSR_PWMA (1<<9)
#define TCSR_ENALL (1<<10)
static inline void microblaze_timer0_stop(void)
static inline void xilinx_timer0_stop(void)
{
out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0) & ~TCSR_ENT);
out_be32(timer_baseaddr + TCSR0,
in_be32(timer_baseaddr + TCSR0) & ~TCSR_ENT);
}
static inline void microblaze_timer0_start_periodic(unsigned long load_val)
static inline void xilinx_timer0_start_periodic(unsigned long load_val)
{
if (!load_val)
load_val = 1;
out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */
/* loading value to timer reg */
out_be32(timer_baseaddr + TLR0, load_val);
/* load the initial value */
out_be32(TIMER_BASE + TCSR0, TCSR_LOAD);
out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
/* see timer data sheet for detail
* !ENALL - don't enable 'em all
@ -86,38 +71,39 @@ static inline void microblaze_timer0_start_periodic(unsigned long load_val)
* UDT - set the timer as down counter
* !MDT0 - generate mode
*/
out_be32(TIMER_BASE + TCSR0,
out_be32(timer_baseaddr + TCSR0,
TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
}
static inline void microblaze_timer0_start_oneshot(unsigned long load_val)
static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
{
if (!load_val)
load_val = 1;
out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */
/* loading value to timer reg */
out_be32(timer_baseaddr + TLR0, load_val);
/* load the initial value */
out_be32(TIMER_BASE + TCSR0, TCSR_LOAD);
out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
out_be32(TIMER_BASE + TCSR0,
out_be32(timer_baseaddr + TCSR0,
TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
}
static int microblaze_timer_set_next_event(unsigned long delta,
static int xilinx_timer_set_next_event(unsigned long delta,
struct clock_event_device *dev)
{
pr_debug("%s: next event, delta %x\n", __func__, (u32)delta);
microblaze_timer0_start_oneshot(delta);
xilinx_timer0_start_oneshot(delta);
return 0;
}
static void microblaze_timer_set_mode(enum clock_event_mode mode,
static void xilinx_timer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
pr_info("%s: periodic\n", __func__);
microblaze_timer0_start_periodic(freq_div_hz);
xilinx_timer0_start_periodic(freq_div_hz);
break;
case CLOCK_EVT_MODE_ONESHOT:
pr_info("%s: oneshot\n", __func__);
@ -127,7 +113,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
break;
case CLOCK_EVT_MODE_SHUTDOWN:
pr_info("%s: shutdown\n", __func__);
microblaze_timer0_stop();
xilinx_timer0_stop();
break;
case CLOCK_EVT_MODE_RESUME:
pr_info("%s: resume\n", __func__);
@ -135,23 +121,23 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
}
}
static struct clock_event_device clockevent_microblaze_timer = {
.name = "microblaze_clockevent",
static struct clock_event_device clockevent_xilinx_timer = {
.name = "xilinx_clockevent",
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
.shift = 8,
.rating = 300,
.set_next_event = microblaze_timer_set_next_event,
.set_mode = microblaze_timer_set_mode,
.set_next_event = xilinx_timer_set_next_event,
.set_mode = xilinx_timer_set_mode,
};
static inline void timer_ack(void)
{
out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0));
out_be32(timer_baseaddr + TCSR0, in_be32(timer_baseaddr + TCSR0));
}
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = &clockevent_microblaze_timer;
struct clock_event_device *evt = &clockevent_xilinx_timer;
#ifdef CONFIG_HEART_BEAT
heartbeat();
#endif
@ -164,73 +150,74 @@ static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED | IRQF_TIMER,
.name = "timer",
.dev_id = &clockevent_microblaze_timer,
.dev_id = &clockevent_xilinx_timer,
};
static __init void microblaze_clockevent_init(void)
static __init void xilinx_clockevent_init(void)
{
clockevent_microblaze_timer.mult =
clockevent_xilinx_timer.mult =
div_sc(timer_clock_freq, NSEC_PER_SEC,
clockevent_microblaze_timer.shift);
clockevent_microblaze_timer.max_delta_ns =
clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
clockevent_microblaze_timer.min_delta_ns =
clockevent_delta2ns(1, &clockevent_microblaze_timer);
clockevent_microblaze_timer.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_microblaze_timer);
clockevent_xilinx_timer.shift);
clockevent_xilinx_timer.max_delta_ns =
clockevent_delta2ns((u32)~0, &clockevent_xilinx_timer);
clockevent_xilinx_timer.min_delta_ns =
clockevent_delta2ns(1, &clockevent_xilinx_timer);
clockevent_xilinx_timer.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_xilinx_timer);
}
static cycle_t microblaze_read(struct clocksource *cs)
static cycle_t xilinx_read(struct clocksource *cs)
{
/* reading actual value of timer 1 */
return (cycle_t) (in_be32(TIMER_BASE + TCR1));
return (cycle_t) (in_be32(timer_baseaddr + TCR1));
}
static struct timecounter microblaze_tc = {
static struct timecounter xilinx_tc = {
.cc = NULL,
};
static cycle_t microblaze_cc_read(const struct cyclecounter *cc)
static cycle_t xilinx_cc_read(const struct cyclecounter *cc)
{
return microblaze_read(NULL);
return xilinx_read(NULL);
}
static struct cyclecounter microblaze_cc = {
.read = microblaze_cc_read,
static struct cyclecounter xilinx_cc = {
.read = xilinx_cc_read,
.mask = CLOCKSOURCE_MASK(32),
.shift = 8,
};
static int __init init_microblaze_timecounter(void)
static int __init init_xilinx_timecounter(void)
{
microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
microblaze_cc.shift);
xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
xilinx_cc.shift);
timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
return 0;
}
static struct clocksource clocksource_microblaze = {
.name = "microblaze_clocksource",
.name = "xilinx_clocksource",
.rating = 300,
.read = microblaze_read,
.read = xilinx_read,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static int __init microblaze_clocksource_init(void)
static int __init xilinx_clocksource_init(void)
{
if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq))
panic("failed to register clocksource");
/* stop timer1 */
out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT);
out_be32(timer_baseaddr + TCSR1,
in_be32(timer_baseaddr + TCSR1) & ~TCSR_ENT);
/* start timer1 - up counting without interrupt */
out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
out_be32(timer_baseaddr + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
/* register timecounter - for ftrace support */
init_microblaze_timecounter();
init_xilinx_timecounter();
return 0;
}
@ -240,55 +227,31 @@ static int __init microblaze_clocksource_init(void)
*/
static int timer_initialized;
void __init time_init(void)
static void __init xilinx_timer_init(struct device_node *timer)
{
u32 irq;
u32 timer_num = 1;
struct device_node *timer = NULL;
const void *prop;
#ifdef CONFIG_SELFMOD_TIMER
unsigned int timer_baseaddr = 0;
int arr_func[] = {
(int)&microblaze_read,
(int)&timer_interrupt,
(int)&microblaze_clocksource_init,
(int)&microblaze_timer_set_mode,
(int)&microblaze_timer_set_next_event,
0
};
#endif
prop = of_get_property(of_chosen, "system-timer", NULL);
if (prop)
timer = of_find_node_by_phandle(be32_to_cpup(prop));
else
pr_info("No chosen timer found, using default\n");
int ret;
if (!timer)
timer = of_find_compatible_node(NULL, NULL,
"xlnx,xps-timer-1.00.a");
BUG_ON(!timer);
timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
irq = irq_of_parse_and_map(timer, 0);
timer_num = be32_to_cpup(of_get_property(timer,
"xlnx,one-timer-only", NULL));
if (timer_num) {
pr_emerg("Please enable two timers in HW\n");
timer_baseaddr = of_iomap(timer, 0);
if (!timer_baseaddr) {
pr_err("ERROR: invalid timer base address\n");
BUG();
}
#ifdef CONFIG_SELFMOD_TIMER
selfmod_function((int *) arr_func, timer_baseaddr);
#endif
pr_info("%s #0 at 0x%08x, irq=%d\n",
timer->name, timer_baseaddr, irq);
irq = irq_of_parse_and_map(timer, 0);
of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
if (timer_num) {
pr_emerg("Please enable two timers in HW\n");
BUG();
}
pr_info("%s: irq=%d\n", timer->full_name, irq);
/* If there is clock-frequency property than use it */
prop = of_get_property(timer, "clock-frequency", NULL);
if (prop)
timer_clock_freq = be32_to_cpup(prop);
else
ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq);
if (ret < 0)
timer_clock_freq = cpuinfo.cpu_clock_freq;
freq_div_hz = timer_clock_freq / HZ;
@ -297,8 +260,8 @@ void __init time_init(void)
#ifdef CONFIG_HEART_BEAT
setup_heartbeat();
#endif
microblaze_clocksource_init();
microblaze_clockevent_init();
xilinx_clocksource_init();
xilinx_clockevent_init();
timer_initialized = 1;
}
@ -312,3 +275,6 @@ unsigned long long notrace sched_clock(void)
}
return 0;
}
CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a",
xilinx_timer_init);

View File

@ -657,67 +657,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
void pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev, int primary)
{
const u32 *ranges;
int rlen;
int pna = of_n_addr_cells(dev);
int np = pna + 5;
int memno = 0, isa_hole = -1;
u32 pci_space;
unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
unsigned long long isa_mb = 0;
struct resource *res;
struct of_pci_range range;
struct of_pci_range_parser parser;
pr_info("PCI host bridge %s %s ranges:\n",
dev->full_name, primary ? "(primary)" : "");
/* Get ranges property */
ranges = of_get_property(dev, "ranges", &rlen);
if (ranges == NULL)
/* Check for ranges property */
if (of_pci_range_parser_init(&parser, dev))
return;
/* Parse it */
pr_debug("Parsing ranges property...\n");
while ((rlen -= np * 4) >= 0) {
for_each_of_pci_range(&parser, &range) {
/* Read next ranges element */
pci_space = ranges[0];
pci_addr = of_read_number(ranges + 1, 2);
cpu_addr = of_translate_address(dev, ranges + 3);
size = of_read_number(ranges + pna + 3, 2);
pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
pci_space, pci_addr);
range.pci_space, range.pci_addr);
pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
cpu_addr, size);
ranges += np;
range.cpu_addr, range.size);
/* If we failed translation or got a zero-sized region
* (some FW try to feed us with non sensical zero sized regions
* such as power3 which look like some kind of attempt
* at exposing the VGA memory hole)
*/
if (cpu_addr == OF_BAD_ADDR || size == 0)
if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
continue;
/* Now consume following elements while they are contiguous */
for (; rlen >= np * sizeof(u32);
ranges += np, rlen -= np * 4) {
if (ranges[0] != pci_space)
break;
pci_next = of_read_number(ranges + 1, 2);
cpu_next = of_translate_address(dev, ranges + 3);
if (pci_next != pci_addr + size ||
cpu_next != cpu_addr + size)
break;
size += of_read_number(ranges + pna + 3, 2);
}
/* Act based on address space type */
res = NULL;
switch ((pci_space >> 24) & 0x3) {
case 1: /* PCI IO space */
switch (range.flags & IORESOURCE_TYPE_BITS) {
case IORESOURCE_IO:
pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n",
cpu_addr, cpu_addr + size - 1, pci_addr);
range.cpu_addr, range.cpu_addr + range.size - 1,
range.pci_addr);
/* We support only one IO range */
if (hose->pci_io_size) {
@ -725,11 +700,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
continue;
}
/* On 32 bits, limit I/O space to 16MB */
if (size > 0x01000000)
size = 0x01000000;
if (range.size > 0x01000000)
range.size = 0x01000000;
/* 32 bits needs to map IOs here */
hose->io_base_virt = ioremap(cpu_addr, size);
hose->io_base_virt = ioremap(range.cpu_addr,
range.size);
/* Expect trouble if pci_addr is not 0 */
if (primary)
@ -738,19 +714,20 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
/* pci_io_size and io_base_phys always represent IO
* space starting at 0 so we factor in pci_addr
*/
hose->pci_io_size = pci_addr + size;
hose->io_base_phys = cpu_addr - pci_addr;
hose->pci_io_size = range.pci_addr + range.size;
hose->io_base_phys = range.cpu_addr - range.pci_addr;
/* Build resource */
res = &hose->io_resource;
res->flags = IORESOURCE_IO;
res->start = pci_addr;
range.cpu_addr = range.pci_addr;
break;
case 2: /* PCI Memory space */
case 3: /* PCI 64 bits Memory space */
case IORESOURCE_MEM:
pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
cpu_addr, cpu_addr + size - 1, pci_addr,
(pci_space & 0x40000000) ? "Prefetch" : "");
range.cpu_addr, range.cpu_addr + range.size - 1,
range.pci_addr,
(range.pci_space & 0x40000000) ?
"Prefetch" : "");
/* We support only 3 memory ranges */
if (memno >= 3) {
@ -758,13 +735,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
continue;
}
/* Handles ISA memory hole space here */
if (pci_addr == 0) {
isa_mb = cpu_addr;
if (range.pci_addr == 0) {
isa_mb = range.cpu_addr;
isa_hole = memno;
if (primary || isa_mem_base == 0)
isa_mem_base = cpu_addr;
hose->isa_mem_phys = cpu_addr;
hose->isa_mem_size = size;
isa_mem_base = range.cpu_addr;
hose->isa_mem_phys = range.cpu_addr;
hose->isa_mem_size = range.size;
}
/* We get the PCI/Mem offset from the first range or
@ -772,30 +749,23 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
* hole. If they don't match, bugger.
*/
if (memno == 0 ||
(isa_hole >= 0 && pci_addr != 0 &&
(isa_hole >= 0 && range.pci_addr != 0 &&
hose->pci_mem_offset == isa_mb))
hose->pci_mem_offset = cpu_addr - pci_addr;
else if (pci_addr != 0 &&
hose->pci_mem_offset != cpu_addr - pci_addr) {
hose->pci_mem_offset = range.cpu_addr -
range.pci_addr;
else if (range.pci_addr != 0 &&
hose->pci_mem_offset != range.cpu_addr -
range.pci_addr) {
pr_info(" \\--> Skipped (offset mismatch) !\n");
continue;
}
/* Build resource */
res = &hose->mem_resources[memno++];
res->flags = IORESOURCE_MEM;
if (pci_space & 0x40000000)
res->flags |= IORESOURCE_PREFETCH;
res->start = cpu_addr;
break;
}
if (res != NULL) {
res->name = dev->full_name;
res->end = res->start + size - 1;
res->parent = NULL;
res->sibling = NULL;
res->child = NULL;
}
if (res != NULL)
of_pci_range_to_resource(&range, dev, res);
}
/* If there's an ISA hole and the pci_mem_offset is -not- matching

View File

@ -18,28 +18,6 @@ config PLATFORM_GENERIC
endchoice
config SELFMOD
bool "Use self modified code for intc/timer"
depends on NO_MMU
default n
help
This choice enables self-modified code for interrupt controller
and timer.
config SELFMOD_INTC
bool "Use self modified code for intc"
depends on SELFMOD
default y
help
This choice enables self-modified code for interrupt controller.
config SELFMOD_TIMER
bool "Use self modified code for timer"
depends on SELFMOD
default y
help
This choice enables self-modified code for timer.
config OPT_LIB_FUNCTION
bool "Optimalized lib function"
default y