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
This commit is contained in:
commit
5872c84027
@ -29,6 +29,7 @@ config MICROBLAZE
|
|||||||
select GENERIC_IDLE_POLL_SETUP
|
select GENERIC_IDLE_POLL_SETUP
|
||||||
select MODULES_USE_ELF_RELA
|
select MODULES_USE_ELF_RELA
|
||||||
select CLONE_BACKWARDS3
|
select CLONE_BACKWARDS3
|
||||||
|
select CLKSRC_OF
|
||||||
|
|
||||||
config SWAP
|
config SWAP
|
||||||
def_bool n
|
def_bool n
|
||||||
|
@ -72,7 +72,7 @@ all: linux.bin
|
|||||||
archclean:
|
archclean:
|
||||||
$(Q)$(MAKE) $(clean)=$(boot)
|
$(Q)$(MAKE) $(clean)=$(boot)
|
||||||
|
|
||||||
linux.bin linux.bin.gz: vmlinux
|
linux.bin linux.bin.gz linux.bin.ub: vmlinux
|
||||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||||
|
|
||||||
simpleImage.%: vmlinux
|
simpleImage.%: vmlinux
|
||||||
@ -81,6 +81,7 @@ simpleImage.%: vmlinux
|
|||||||
define archhelp
|
define archhelp
|
||||||
echo '* linux.bin - Create raw binary'
|
echo '* linux.bin - Create raw binary'
|
||||||
echo ' linux.bin.gz - Create compressed 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 ' simpleImage.<dt> - ELF image with $(arch)/boot/dts/<dt>.dts linked in'
|
||||||
echo ' - stripped elf with fdt blob'
|
echo ' - stripped elf with fdt blob'
|
||||||
echo ' simpleImage.<dt>.unstrip - full ELF image with fdt blob'
|
echo ' simpleImage.<dt>.unstrip - full ELF image with fdt blob'
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
# arch/microblaze/boot/Makefile
|
# 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
|
OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary
|
||||||
|
|
||||||
$(obj)/linux.bin: vmlinux FORCE
|
$(obj)/linux.bin: vmlinux FORCE
|
||||||
$(call if_changed,objcopy)
|
$(call if_changed,objcopy)
|
||||||
|
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
||||||
|
|
||||||
|
$(obj)/linux.bin.ub: $(obj)/linux.bin FORCE
|
||||||
$(call if_changed,uimage)
|
$(call if_changed,uimage)
|
||||||
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
@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 \
|
cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \
|
||||||
-K _fdt_start vmlinux -o $@
|
-K _fdt_start vmlinux -o $@
|
||||||
|
|
||||||
UIMAGE_IN = $@
|
|
||||||
UIMAGE_OUT = $@.ub
|
|
||||||
UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR)
|
UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR)
|
||||||
|
|
||||||
$(obj)/simpleImage.%: vmlinux FORCE
|
$(obj)/simpleImage.%: vmlinux FORCE
|
||||||
|
@ -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 */
|
|
@ -7,7 +7,6 @@ ifdef CONFIG_FUNCTION_TRACER
|
|||||||
CFLAGS_REMOVE_timer.o = -pg
|
CFLAGS_REMOVE_timer.o = -pg
|
||||||
CFLAGS_REMOVE_intc.o = -pg
|
CFLAGS_REMOVE_intc.o = -pg
|
||||||
CFLAGS_REMOVE_early_printk.o = -pg
|
CFLAGS_REMOVE_early_printk.o = -pg
|
||||||
CFLAGS_REMOVE_selfmod.o = -pg
|
|
||||||
CFLAGS_REMOVE_heartbeat.o = -pg
|
CFLAGS_REMOVE_heartbeat.o = -pg
|
||||||
CFLAGS_REMOVE_ftrace.o = -pg
|
CFLAGS_REMOVE_ftrace.o = -pg
|
||||||
CFLAGS_REMOVE_process.o = -pg
|
CFLAGS_REMOVE_process.o = -pg
|
||||||
@ -23,7 +22,6 @@ obj-y += dma.o exceptions.o \
|
|||||||
obj-y += cpu/
|
obj-y += cpu/
|
||||||
|
|
||||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
obj-$(CONFIG_SELFMOD) += selfmod.o
|
|
||||||
obj-$(CONFIG_HEART_BEAT) += heartbeat.o
|
obj-$(CONFIG_HEART_BEAT) += heartbeat.o
|
||||||
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
|
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
|
||||||
obj-$(CONFIG_MMU) += misc.o
|
obj-$(CONFIG_MMU) += misc.o
|
||||||
|
@ -39,6 +39,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
|
|||||||
{"8.30.a", 0x17},
|
{"8.30.a", 0x17},
|
||||||
{"8.40.a", 0x18},
|
{"8.40.a", 0x18},
|
||||||
{"8.40.b", 0x19},
|
{"8.40.b", 0x19},
|
||||||
|
{"9.0", 0x1b},
|
||||||
|
{"9.1", 0x1d},
|
||||||
{NULL, 0},
|
{NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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) 2007-2009 PetaLogix
|
||||||
* Copyright (C) 2006 Atmark Techno, Inc.
|
* Copyright (C) 2006 Atmark Techno, Inc.
|
||||||
*
|
*
|
||||||
@ -8,23 +9,15 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <asm/page.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
|
|
||||||
#include <asm/prom.h>
|
#include "../../drivers/irqchip/irqchip.h"
|
||||||
#include <asm/irq.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_SELFMOD_INTC
|
static void __iomem *intc_baseaddr;
|
||||||
#include <asm/selfmod.h>
|
|
||||||
#define INTC_BASE BARRIER_BASE_ADDR
|
|
||||||
#else
|
|
||||||
static unsigned int intc_baseaddr;
|
|
||||||
#define INTC_BASE intc_baseaddr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* No one else should require these constants, so define them locally here. */
|
/* No one else should require these constants, so define them locally here. */
|
||||||
#define ISR 0x00 /* Interrupt Status Register */
|
#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
|
* acks the irq before calling the interrupt handler
|
||||||
*/
|
*/
|
||||||
if (irqd_is_level_type(d))
|
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)
|
static void intc_disable_or_mask(struct irq_data *d)
|
||||||
{
|
{
|
||||||
pr_debug("disable: %ld\n", d->hwirq);
|
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)
|
static void intc_ack(struct irq_data *d)
|
||||||
{
|
{
|
||||||
pr_debug("ack: %ld\n", d->hwirq);
|
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)
|
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;
|
unsigned long mask = 1 << d->hwirq;
|
||||||
|
|
||||||
pr_debug("disable_and_ack: %ld\n", d->hwirq);
|
pr_debug("disable_and_ack: %ld\n", d->hwirq);
|
||||||
out_be32(INTC_BASE + CIE, mask);
|
out_be32(intc_baseaddr + CIE, mask);
|
||||||
out_be32(INTC_BASE + IAR, mask);
|
out_be32(intc_baseaddr + IAR, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip intc_dev = {
|
static struct irq_chip intc_dev = {
|
||||||
@ -90,7 +83,7 @@ unsigned int get_irq(void)
|
|||||||
{
|
{
|
||||||
unsigned int hwirq, irq = -1;
|
unsigned int hwirq, irq = -1;
|
||||||
|
|
||||||
hwirq = in_be32(INTC_BASE + IVR);
|
hwirq = in_be32(intc_baseaddr + IVR);
|
||||||
if (hwirq != -1U)
|
if (hwirq != -1U)
|
||||||
irq = irq_find_mapping(root_domain, hwirq);
|
irq = irq_find_mapping(root_domain, hwirq);
|
||||||
|
|
||||||
@ -120,40 +113,32 @@ static const struct irq_domain_ops xintc_irq_domain_ops = {
|
|||||||
.map = xintc_map,
|
.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;
|
u32 nr_irq, intr_mask;
|
||||||
struct device_node *intc = NULL;
|
int ret;
|
||||||
#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);
|
|
||||||
|
|
||||||
intc_baseaddr = be32_to_cpup(of_get_property(intc, "reg", NULL));
|
intc_baseaddr = of_iomap(intc, 0);
|
||||||
intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
|
BUG_ON(!intc_baseaddr);
|
||||||
nr_irq = be32_to_cpup(of_get_property(intc,
|
|
||||||
"xlnx,num-intr-inputs", NULL));
|
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))
|
if (intr_mask > (u32)((1ULL << nr_irq) - 1))
|
||||||
pr_info(" ERROR: Mismatch in kind-of-intr param\n");
|
pr_info(" ERROR: Mismatch in kind-of-intr param\n");
|
||||||
|
|
||||||
#ifdef CONFIG_SELFMOD_INTC
|
pr_info("%s: num_irq=%d, edge=0x%x\n",
|
||||||
selfmod_function((int *) arr_func, intc_baseaddr);
|
intc->full_name, nr_irq, intr_mask);
|
||||||
#endif
|
|
||||||
pr_info("%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
|
|
||||||
intc->name, intc_baseaddr, nr_irq, intr_mask);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable all external interrupts until they are
|
* Disable all external interrupts until they are
|
||||||
@ -174,4 +159,8 @@ void __init init_IRQ(void)
|
|||||||
(void *)intr_mask);
|
(void *)intr_mask);
|
||||||
|
|
||||||
irq_set_default_host(root_domain);
|
irq_set_default_host(root_domain);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/kernel_stat.h>
|
#include <linux/kernel_stat.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/irqchip.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/export.h>
|
|
||||||
|
|
||||||
#include <asm/prom.h>
|
|
||||||
|
|
||||||
static u32 concurrent_irq;
|
static u32 concurrent_irq;
|
||||||
|
|
||||||
@ -47,3 +45,9 @@ next_irq:
|
|||||||
set_irq_regs(old_regs);
|
set_irq_regs(old_regs);
|
||||||
trace_hardirqs_on();
|
trace_hardirqs_on();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init init_IRQ(void)
|
||||||
|
{
|
||||||
|
/* process the entire interrupt tree in one go */
|
||||||
|
irqchip_init();
|
||||||
|
}
|
||||||
|
@ -67,7 +67,11 @@ static void gpio_system_reset(void)
|
|||||||
pr_notice("Reset GPIO unavailable - halting!\n");
|
pr_notice("Reset GPIO unavailable - halting!\n");
|
||||||
}
|
}
|
||||||
#else
|
#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)
|
void of_platform_reset_gpio_probe(void)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -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 */
|
|
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/clocksource.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
@ -68,10 +69,6 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
|
|
||||||
xilinx_pci_init();
|
xilinx_pci_init();
|
||||||
|
|
||||||
#if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
|
|
||||||
pr_notice("Self modified code enable\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_VT
|
#ifdef CONFIG_VT
|
||||||
#if defined(CONFIG_XILINX_CONSOLE)
|
#if defined(CONFIG_XILINX_CONSOLE)
|
||||||
conswitchp = &xil_con;
|
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;
|
per_cpu(CURRENT_SAVE, 0) = (unsigned long)current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init time_init(void)
|
||||||
|
{
|
||||||
|
clocksource_of_init();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *of_debugfs_root;
|
struct dentry *of_debugfs_root;
|
||||||
|
|
||||||
|
@ -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) 2007-2009 PetaLogix
|
||||||
* Copyright (C) 2006 Atmark Techno, Inc.
|
* Copyright (C) 2006 Atmark Techno, Inc.
|
||||||
*
|
*
|
||||||
@ -8,34 +9,16 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/param.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/profile.h>
|
|
||||||
#include <linux/irq.h>
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/clocksource.h>
|
|
||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
#include <linux/io.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/bug.h>
|
|
||||||
#include <asm/cpuinfo.h>
|
#include <asm/cpuinfo.h>
|
||||||
#include <asm/setup.h>
|
|
||||||
#include <asm/prom.h>
|
|
||||||
#include <asm/irq.h>
|
|
||||||
#include <linux/cnt32_to_63.h>
|
#include <linux/cnt32_to_63.h>
|
||||||
|
|
||||||
#ifdef CONFIG_SELFMOD_TIMER
|
static void __iomem *timer_baseaddr;
|
||||||
#include <asm/selfmod.h>
|
|
||||||
#define TIMER_BASE BARRIER_BASE_ADDR
|
|
||||||
#else
|
|
||||||
static unsigned int timer_baseaddr;
|
|
||||||
#define TIMER_BASE timer_baseaddr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static unsigned int freq_div_hz;
|
static unsigned int freq_div_hz;
|
||||||
static unsigned int timer_clock_freq;
|
static unsigned int timer_clock_freq;
|
||||||
@ -59,19 +42,21 @@ static unsigned int timer_clock_freq;
|
|||||||
#define TCSR_PWMA (1<<9)
|
#define TCSR_PWMA (1<<9)
|
||||||
#define TCSR_ENALL (1<<10)
|
#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)
|
if (!load_val)
|
||||||
load_val = 1;
|
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 */
|
/* load the initial value */
|
||||||
out_be32(TIMER_BASE + TCSR0, TCSR_LOAD);
|
out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
|
||||||
|
|
||||||
/* see timer data sheet for detail
|
/* see timer data sheet for detail
|
||||||
* !ENALL - don't enable 'em all
|
* !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
|
* UDT - set the timer as down counter
|
||||||
* !MDT0 - generate mode
|
* !MDT0 - generate mode
|
||||||
*/
|
*/
|
||||||
out_be32(TIMER_BASE + TCSR0,
|
out_be32(timer_baseaddr + TCSR0,
|
||||||
TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
|
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)
|
if (!load_val)
|
||||||
load_val = 1;
|
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 */
|
/* 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);
|
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)
|
struct clock_event_device *dev)
|
||||||
{
|
{
|
||||||
pr_debug("%s: next event, delta %x\n", __func__, (u32)delta);
|
pr_debug("%s: next event, delta %x\n", __func__, (u32)delta);
|
||||||
microblaze_timer0_start_oneshot(delta);
|
xilinx_timer0_start_oneshot(delta);
|
||||||
return 0;
|
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)
|
struct clock_event_device *evt)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CLOCK_EVT_MODE_PERIODIC:
|
case CLOCK_EVT_MODE_PERIODIC:
|
||||||
pr_info("%s: periodic\n", __func__);
|
pr_info("%s: periodic\n", __func__);
|
||||||
microblaze_timer0_start_periodic(freq_div_hz);
|
xilinx_timer0_start_periodic(freq_div_hz);
|
||||||
break;
|
break;
|
||||||
case CLOCK_EVT_MODE_ONESHOT:
|
case CLOCK_EVT_MODE_ONESHOT:
|
||||||
pr_info("%s: oneshot\n", __func__);
|
pr_info("%s: oneshot\n", __func__);
|
||||||
@ -127,7 +113,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
|
|||||||
break;
|
break;
|
||||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||||
pr_info("%s: shutdown\n", __func__);
|
pr_info("%s: shutdown\n", __func__);
|
||||||
microblaze_timer0_stop();
|
xilinx_timer0_stop();
|
||||||
break;
|
break;
|
||||||
case CLOCK_EVT_MODE_RESUME:
|
case CLOCK_EVT_MODE_RESUME:
|
||||||
pr_info("%s: resume\n", __func__);
|
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 = {
|
static struct clock_event_device clockevent_xilinx_timer = {
|
||||||
.name = "microblaze_clockevent",
|
.name = "xilinx_clockevent",
|
||||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||||
.shift = 8,
|
.shift = 8,
|
||||||
.rating = 300,
|
.rating = 300,
|
||||||
.set_next_event = microblaze_timer_set_next_event,
|
.set_next_event = xilinx_timer_set_next_event,
|
||||||
.set_mode = microblaze_timer_set_mode,
|
.set_mode = xilinx_timer_set_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void timer_ack(void)
|
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)
|
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
|
#ifdef CONFIG_HEART_BEAT
|
||||||
heartbeat();
|
heartbeat();
|
||||||
#endif
|
#endif
|
||||||
@ -164,73 +150,74 @@ static struct irqaction timer_irqaction = {
|
|||||||
.handler = timer_interrupt,
|
.handler = timer_interrupt,
|
||||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||||
.name = "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,
|
div_sc(timer_clock_freq, NSEC_PER_SEC,
|
||||||
clockevent_microblaze_timer.shift);
|
clockevent_xilinx_timer.shift);
|
||||||
clockevent_microblaze_timer.max_delta_ns =
|
clockevent_xilinx_timer.max_delta_ns =
|
||||||
clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
|
clockevent_delta2ns((u32)~0, &clockevent_xilinx_timer);
|
||||||
clockevent_microblaze_timer.min_delta_ns =
|
clockevent_xilinx_timer.min_delta_ns =
|
||||||
clockevent_delta2ns(1, &clockevent_microblaze_timer);
|
clockevent_delta2ns(1, &clockevent_xilinx_timer);
|
||||||
clockevent_microblaze_timer.cpumask = cpumask_of(0);
|
clockevent_xilinx_timer.cpumask = cpumask_of(0);
|
||||||
clockevents_register_device(&clockevent_microblaze_timer);
|
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 */
|
/* 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,
|
.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 = {
|
static struct cyclecounter xilinx_cc = {
|
||||||
.read = microblaze_cc_read,
|
.read = xilinx_cc_read,
|
||||||
.mask = CLOCKSOURCE_MASK(32),
|
.mask = CLOCKSOURCE_MASK(32),
|
||||||
.shift = 8,
|
.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,
|
xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
|
||||||
microblaze_cc.shift);
|
xilinx_cc.shift);
|
||||||
|
|
||||||
timecounter_init(µblaze_tc, µblaze_cc, sched_clock());
|
timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct clocksource clocksource_microblaze = {
|
static struct clocksource clocksource_microblaze = {
|
||||||
.name = "microblaze_clocksource",
|
.name = "xilinx_clocksource",
|
||||||
.rating = 300,
|
.rating = 300,
|
||||||
.read = microblaze_read,
|
.read = xilinx_read,
|
||||||
.mask = CLOCKSOURCE_MASK(32),
|
.mask = CLOCKSOURCE_MASK(32),
|
||||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
.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))
|
if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq))
|
||||||
panic("failed to register clocksource");
|
panic("failed to register clocksource");
|
||||||
|
|
||||||
/* stop timer1 */
|
/* 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 */
|
/* 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 */
|
/* register timecounter - for ftrace support */
|
||||||
init_microblaze_timecounter();
|
init_xilinx_timecounter();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,55 +227,31 @@ static int __init microblaze_clocksource_init(void)
|
|||||||
*/
|
*/
|
||||||
static int timer_initialized;
|
static int timer_initialized;
|
||||||
|
|
||||||
void __init time_init(void)
|
static void __init xilinx_timer_init(struct device_node *timer)
|
||||||
{
|
{
|
||||||
u32 irq;
|
u32 irq;
|
||||||
u32 timer_num = 1;
|
u32 timer_num = 1;
|
||||||
struct device_node *timer = NULL;
|
int ret;
|
||||||
const void *prop;
|
|
||||||
#ifdef CONFIG_SELFMOD_TIMER
|
|
||||||
unsigned int timer_baseaddr = 0;
|
|
||||||
int arr_func[] = {
|
|
||||||
(int)µblaze_read,
|
|
||||||
(int)&timer_interrupt,
|
|
||||||
(int)µblaze_clocksource_init,
|
|
||||||
(int)µblaze_timer_set_mode,
|
|
||||||
(int)µblaze_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");
|
|
||||||
|
|
||||||
if (!timer)
|
timer_baseaddr = of_iomap(timer, 0);
|
||||||
timer = of_find_compatible_node(NULL, NULL,
|
if (!timer_baseaddr) {
|
||||||
"xlnx,xps-timer-1.00.a");
|
pr_err("ERROR: invalid timer base address\n");
|
||||||
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");
|
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SELFMOD_TIMER
|
irq = irq_of_parse_and_map(timer, 0);
|
||||||
selfmod_function((int *) arr_func, timer_baseaddr);
|
|
||||||
#endif
|
of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
|
||||||
pr_info("%s #0 at 0x%08x, irq=%d\n",
|
if (timer_num) {
|
||||||
timer->name, timer_baseaddr, irq);
|
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 */
|
/* If there is clock-frequency property than use it */
|
||||||
prop = of_get_property(timer, "clock-frequency", NULL);
|
ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq);
|
||||||
if (prop)
|
if (ret < 0)
|
||||||
timer_clock_freq = be32_to_cpup(prop);
|
|
||||||
else
|
|
||||||
timer_clock_freq = cpuinfo.cpu_clock_freq;
|
timer_clock_freq = cpuinfo.cpu_clock_freq;
|
||||||
|
|
||||||
freq_div_hz = timer_clock_freq / HZ;
|
freq_div_hz = timer_clock_freq / HZ;
|
||||||
@ -297,8 +260,8 @@ void __init time_init(void)
|
|||||||
#ifdef CONFIG_HEART_BEAT
|
#ifdef CONFIG_HEART_BEAT
|
||||||
setup_heartbeat();
|
setup_heartbeat();
|
||||||
#endif
|
#endif
|
||||||
microblaze_clocksource_init();
|
xilinx_clocksource_init();
|
||||||
microblaze_clockevent_init();
|
xilinx_clockevent_init();
|
||||||
timer_initialized = 1;
|
timer_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,3 +275,6 @@ unsigned long long notrace sched_clock(void)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a",
|
||||||
|
xilinx_timer_init);
|
||||||
|
@ -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,
|
void pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
||||||
struct device_node *dev, int primary)
|
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;
|
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;
|
unsigned long long isa_mb = 0;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
struct of_pci_range range;
|
||||||
|
struct of_pci_range_parser parser;
|
||||||
|
|
||||||
pr_info("PCI host bridge %s %s ranges:\n",
|
pr_info("PCI host bridge %s %s ranges:\n",
|
||||||
dev->full_name, primary ? "(primary)" : "");
|
dev->full_name, primary ? "(primary)" : "");
|
||||||
|
|
||||||
/* Get ranges property */
|
/* Check for ranges property */
|
||||||
ranges = of_get_property(dev, "ranges", &rlen);
|
if (of_pci_range_parser_init(&parser, dev))
|
||||||
if (ranges == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Parse it */
|
|
||||||
pr_debug("Parsing ranges property...\n");
|
pr_debug("Parsing ranges property...\n");
|
||||||
while ((rlen -= np * 4) >= 0) {
|
for_each_of_pci_range(&parser, &range) {
|
||||||
/* Read next ranges element */
|
/* 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 ",
|
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",
|
pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
|
||||||
cpu_addr, size);
|
range.cpu_addr, range.size);
|
||||||
|
|
||||||
ranges += np;
|
|
||||||
|
|
||||||
/* If we failed translation or got a zero-sized region
|
/* If we failed translation or got a zero-sized region
|
||||||
* (some FW try to feed us with non sensical zero sized regions
|
* (some FW try to feed us with non sensical zero sized regions
|
||||||
* such as power3 which look like some kind of attempt
|
* such as power3 which look like some kind of attempt
|
||||||
* at exposing the VGA memory hole)
|
* 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;
|
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 */
|
/* Act based on address space type */
|
||||||
res = NULL;
|
res = NULL;
|
||||||
switch ((pci_space >> 24) & 0x3) {
|
switch (range.flags & IORESOURCE_TYPE_BITS) {
|
||||||
case 1: /* PCI IO space */
|
case IORESOURCE_IO:
|
||||||
pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n",
|
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 */
|
/* We support only one IO range */
|
||||||
if (hose->pci_io_size) {
|
if (hose->pci_io_size) {
|
||||||
@ -725,11 +700,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* On 32 bits, limit I/O space to 16MB */
|
/* On 32 bits, limit I/O space to 16MB */
|
||||||
if (size > 0x01000000)
|
if (range.size > 0x01000000)
|
||||||
size = 0x01000000;
|
range.size = 0x01000000;
|
||||||
|
|
||||||
/* 32 bits needs to map IOs here */
|
/* 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 */
|
/* Expect trouble if pci_addr is not 0 */
|
||||||
if (primary)
|
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
|
/* pci_io_size and io_base_phys always represent IO
|
||||||
* space starting at 0 so we factor in pci_addr
|
* space starting at 0 so we factor in pci_addr
|
||||||
*/
|
*/
|
||||||
hose->pci_io_size = pci_addr + size;
|
hose->pci_io_size = range.pci_addr + range.size;
|
||||||
hose->io_base_phys = cpu_addr - pci_addr;
|
hose->io_base_phys = range.cpu_addr - range.pci_addr;
|
||||||
|
|
||||||
/* Build resource */
|
/* Build resource */
|
||||||
res = &hose->io_resource;
|
res = &hose->io_resource;
|
||||||
res->flags = IORESOURCE_IO;
|
range.cpu_addr = range.pci_addr;
|
||||||
res->start = pci_addr;
|
|
||||||
break;
|
break;
|
||||||
case 2: /* PCI Memory space */
|
case IORESOURCE_MEM:
|
||||||
case 3: /* PCI 64 bits Memory space */
|
|
||||||
pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
|
pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
|
||||||
cpu_addr, cpu_addr + size - 1, pci_addr,
|
range.cpu_addr, range.cpu_addr + range.size - 1,
|
||||||
(pci_space & 0x40000000) ? "Prefetch" : "");
|
range.pci_addr,
|
||||||
|
(range.pci_space & 0x40000000) ?
|
||||||
|
"Prefetch" : "");
|
||||||
|
|
||||||
/* We support only 3 memory ranges */
|
/* We support only 3 memory ranges */
|
||||||
if (memno >= 3) {
|
if (memno >= 3) {
|
||||||
@ -758,13 +735,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Handles ISA memory hole space here */
|
/* Handles ISA memory hole space here */
|
||||||
if (pci_addr == 0) {
|
if (range.pci_addr == 0) {
|
||||||
isa_mb = cpu_addr;
|
isa_mb = range.cpu_addr;
|
||||||
isa_hole = memno;
|
isa_hole = memno;
|
||||||
if (primary || isa_mem_base == 0)
|
if (primary || isa_mem_base == 0)
|
||||||
isa_mem_base = cpu_addr;
|
isa_mem_base = range.cpu_addr;
|
||||||
hose->isa_mem_phys = cpu_addr;
|
hose->isa_mem_phys = range.cpu_addr;
|
||||||
hose->isa_mem_size = size;
|
hose->isa_mem_size = range.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We get the PCI/Mem offset from the first range or
|
/* 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.
|
* hole. If they don't match, bugger.
|
||||||
*/
|
*/
|
||||||
if (memno == 0 ||
|
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 == isa_mb))
|
||||||
hose->pci_mem_offset = cpu_addr - pci_addr;
|
hose->pci_mem_offset = range.cpu_addr -
|
||||||
else if (pci_addr != 0 &&
|
range.pci_addr;
|
||||||
hose->pci_mem_offset != cpu_addr - pci_addr) {
|
else if (range.pci_addr != 0 &&
|
||||||
|
hose->pci_mem_offset != range.cpu_addr -
|
||||||
|
range.pci_addr) {
|
||||||
pr_info(" \\--> Skipped (offset mismatch) !\n");
|
pr_info(" \\--> Skipped (offset mismatch) !\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build resource */
|
/* Build resource */
|
||||||
res = &hose->mem_resources[memno++];
|
res = &hose->mem_resources[memno++];
|
||||||
res->flags = IORESOURCE_MEM;
|
|
||||||
if (pci_space & 0x40000000)
|
|
||||||
res->flags |= IORESOURCE_PREFETCH;
|
|
||||||
res->start = cpu_addr;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (res != NULL) {
|
if (res != NULL)
|
||||||
res->name = dev->full_name;
|
of_pci_range_to_resource(&range, dev, res);
|
||||||
res->end = res->start + size - 1;
|
|
||||||
res->parent = NULL;
|
|
||||||
res->sibling = NULL;
|
|
||||||
res->child = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's an ISA hole and the pci_mem_offset is -not- matching
|
/* If there's an ISA hole and the pci_mem_offset is -not- matching
|
||||||
|
@ -18,28 +18,6 @@ config PLATFORM_GENERIC
|
|||||||
|
|
||||||
endchoice
|
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
|
config OPT_LIB_FUNCTION
|
||||||
bool "Optimalized lib function"
|
bool "Optimalized lib function"
|
||||||
default y
|
default y
|
||||||
|
Loading…
Reference in New Issue
Block a user