Merge branches 'ftrace', 'gic', 'io', 'kexec', 'mod', 'sa11x0', 'sh' and 'versatile' into devel
This commit is contained in:
parent
3c0eee3fe6
ed60453fa8
ac61d143ff
28257f7fde
b230653132
50005a8deb
cf562b4a55
3d09fbcd26
8a9618f5df
commit
31edf274f9
@ -23,6 +23,7 @@ config ARM
|
||||
select PERF_USE_VMALLOC
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
|
||||
select HAVE_C_RECORDMCOUNT
|
||||
help
|
||||
The ARM series is a line of low-power-consumption RISC chip designs
|
||||
licensed by ARM Ltd and targeted at embedded applications and
|
||||
@ -1164,7 +1165,7 @@ config ISA_DMA_API
|
||||
bool
|
||||
|
||||
config PCI
|
||||
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
|
||||
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || SA1100_NANOENGINE
|
||||
help
|
||||
Find out whether you have a PCI motherboard. PCI is the name of a
|
||||
bus system, i.e. the way the CPU talks to the other stuff inside
|
||||
@ -1175,6 +1176,12 @@ config PCI_DOMAINS
|
||||
bool
|
||||
depends on PCI
|
||||
|
||||
config PCI_NANOENGINE
|
||||
bool "BSE nanoEngine PCI support"
|
||||
depends on SA1100_NANOENGINE
|
||||
help
|
||||
Enable PCI on the BSE nanoEngine board.
|
||||
|
||||
config PCI_SYSCALL
|
||||
def_bool PCI
|
||||
|
||||
@ -1650,6 +1657,19 @@ config ATAGS_PROC
|
||||
Should the atags used to boot the kernel be exported in an "atags"
|
||||
file in procfs. Useful with kexec.
|
||||
|
||||
config CRASH_DUMP
|
||||
bool "Build kdump crash kernel (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
Generate crash dump after being started by kexec. This should
|
||||
be normally only set in special crash dump kernels which are
|
||||
loaded in the main kernel with kexec-tools into a specially
|
||||
reserved region and then later executed after a crash by
|
||||
kdump/kexec. The crash dump kernel must be compiled to a
|
||||
memory address not used by the main kernel
|
||||
|
||||
For more details see Documentation/kdump/kdump.txt
|
||||
|
||||
config AUTO_ZRELADDR
|
||||
bool "Auto calculation of the decompressed kernel image address"
|
||||
depends on !ZBOOT_ROM && !ARCH_U300
|
||||
|
@ -45,6 +45,10 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_SHMOBILE),y)
|
||||
OBJS += head-shmobile.o
|
||||
endif
|
||||
|
||||
#
|
||||
# We now have a PIC decompressor implementation. Decompressors running
|
||||
# from RAM should not define ZTEXTADDR. Decompressors running directly
|
||||
|
53
arch/arm/boot/compressed/head-shmobile.S
Normal file
53
arch/arm/boot/compressed/head-shmobile.S
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* The head-file for SH-Mobile ARM platforms
|
||||
*
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
* Simon Horman <horms@verge.net.au>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ZBOOT_ROM
|
||||
|
||||
.section ".start", "ax"
|
||||
|
||||
/* load board-specific initialization code */
|
||||
#include <mach/zboot.h>
|
||||
|
||||
b 1f
|
||||
__atags:@ tag #1
|
||||
.long 12 @ tag->hdr.size = tag_size(tag_core);
|
||||
.long 0x54410001 @ tag->hdr.tag = ATAG_CORE;
|
||||
.long 0 @ tag->u.core.flags = 0;
|
||||
.long 0 @ tag->u.core.pagesize = 0;
|
||||
.long 0 @ tag->u.core.rootdev = 0;
|
||||
@ tag #2
|
||||
.long 8 @ tag->hdr.size = tag_size(tag_mem32);
|
||||
.long 0x54410002 @ tag->hdr.tag = ATAG_MEM;
|
||||
.long CONFIG_MEMORY_SIZE @ tag->u.mem.size = CONFIG_MEMORY_SIZE;
|
||||
.long CONFIG_MEMORY_START @ @ tag->u.mem.start = CONFIG_MEMORY_START;
|
||||
@ tag #3
|
||||
.long 0 @ tag->hdr.size = 0
|
||||
.long 0 @ tag->hdr.tag = ATAG_NONE;
|
||||
1:
|
||||
|
||||
/* Set board ID necessary for boot */
|
||||
ldr r7, 1f @ Set machine type register
|
||||
adr r8, __atags @ Set atag register
|
||||
b 2f
|
||||
|
||||
1 : .long MACH_TYPE
|
||||
2 :
|
||||
|
||||
#endif /* CONFIG_ZBOOT_ROM */
|
@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_IXP2000) += uengine.o
|
||||
obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
|
||||
obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
|
||||
obj-$(CONFIG_COMMON_CLKDEV) += clkdev.o
|
||||
obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
|
||||
|
@ -35,6 +35,9 @@
|
||||
|
||||
static DEFINE_SPINLOCK(irq_controller_lock);
|
||||
|
||||
/* Address of GIC 0 CPU interface */
|
||||
void __iomem *gic_cpu_base_addr __read_mostly;
|
||||
|
||||
struct gic_chip_data {
|
||||
unsigned int irq_offset;
|
||||
void __iomem *dist_base;
|
||||
@ -45,7 +48,7 @@ struct gic_chip_data {
|
||||
#define MAX_GIC_NR 1
|
||||
#endif
|
||||
|
||||
static struct gic_chip_data gic_data[MAX_GIC_NR];
|
||||
static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
|
||||
|
||||
static inline void __iomem *gic_dist_base(unsigned int irq)
|
||||
{
|
||||
@ -213,21 +216,16 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
|
||||
set_irq_chained_handler(irq, gic_handle_cascade_irq);
|
||||
}
|
||||
|
||||
void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
|
||||
unsigned int irq_start)
|
||||
static void __init gic_dist_init(struct gic_chip_data *gic,
|
||||
unsigned int irq_start)
|
||||
{
|
||||
unsigned int gic_irqs, irq_limit, i;
|
||||
void __iomem *base = gic->dist_base;
|
||||
u32 cpumask = 1 << smp_processor_id();
|
||||
|
||||
if (gic_nr >= MAX_GIC_NR)
|
||||
BUG();
|
||||
|
||||
cpumask |= cpumask << 8;
|
||||
cpumask |= cpumask << 16;
|
||||
|
||||
gic_data[gic_nr].dist_base = base;
|
||||
gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
|
||||
|
||||
writel(0, base + GIC_DIST_CTRL);
|
||||
|
||||
/*
|
||||
@ -267,7 +265,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
|
||||
/*
|
||||
* Limit number of interrupts registered to the platform maximum
|
||||
*/
|
||||
irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
|
||||
irq_limit = gic->irq_offset + gic_irqs;
|
||||
if (WARN_ON(irq_limit > NR_IRQS))
|
||||
irq_limit = NR_IRQS;
|
||||
|
||||
@ -276,7 +274,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
|
||||
*/
|
||||
for (i = irq_start; i < irq_limit; i++) {
|
||||
set_irq_chip(i, &gic_chip);
|
||||
set_irq_chip_data(i, &gic_data[gic_nr]);
|
||||
set_irq_chip_data(i, gic);
|
||||
set_irq_handler(i, handle_level_irq);
|
||||
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
@ -284,19 +282,12 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
|
||||
writel(1, base + GIC_DIST_CTRL);
|
||||
}
|
||||
|
||||
void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
|
||||
static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
|
||||
{
|
||||
void __iomem *dist_base;
|
||||
void __iomem *dist_base = gic->dist_base;
|
||||
void __iomem *base = gic->cpu_base;
|
||||
int i;
|
||||
|
||||
if (gic_nr >= MAX_GIC_NR)
|
||||
BUG();
|
||||
|
||||
dist_base = gic_data[gic_nr].dist_base;
|
||||
BUG_ON(!dist_base);
|
||||
|
||||
gic_data[gic_nr].cpu_base = base;
|
||||
|
||||
/*
|
||||
* Deal with the banked PPI and SGI interrupts - disable all
|
||||
* PPI interrupts, ensure all SGI interrupts are enabled.
|
||||
@ -314,6 +305,42 @@ void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
|
||||
writel(1, base + GIC_CPU_CTRL);
|
||||
}
|
||||
|
||||
void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
|
||||
void __iomem *dist_base, void __iomem *cpu_base)
|
||||
{
|
||||
struct gic_chip_data *gic;
|
||||
|
||||
BUG_ON(gic_nr >= MAX_GIC_NR);
|
||||
|
||||
gic = &gic_data[gic_nr];
|
||||
gic->dist_base = dist_base;
|
||||
gic->cpu_base = cpu_base;
|
||||
gic->irq_offset = (irq_start - 1) & ~31;
|
||||
|
||||
if (gic_nr == 0)
|
||||
gic_cpu_base_addr = cpu_base;
|
||||
|
||||
gic_dist_init(gic, irq_start);
|
||||
gic_cpu_init(gic);
|
||||
}
|
||||
|
||||
void __cpuinit gic_secondary_init(unsigned int gic_nr)
|
||||
{
|
||||
BUG_ON(gic_nr >= MAX_GIC_NR);
|
||||
|
||||
gic_cpu_init(&gic_data[gic_nr]);
|
||||
}
|
||||
|
||||
void __cpuinit gic_enable_ppi(unsigned int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
irq_to_desc(irq)->status |= IRQ_NOPROBE;
|
||||
gic_unmask_irq(irq);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* linux/arch/arm/plat-versatile/timer-sp.c
|
||||
* linux/arch/arm/common/timer-sp.c
|
||||
*
|
||||
* Copyright (C) 1999 - 2003 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
@ -26,8 +26,6 @@
|
||||
|
||||
#include <asm/hardware/arm_timer.h>
|
||||
|
||||
#include <plat/timer-sp.h>
|
||||
|
||||
/*
|
||||
* These timers are currently always setup to be clocked at 1MHz.
|
||||
*/
|
@ -99,6 +99,8 @@ struct elf32_hdr;
|
||||
extern int elf_check_arch(const struct elf32_hdr *);
|
||||
#define elf_check_arch elf_check_arch
|
||||
|
||||
#define vmcore_elf64_check_arch(x) (0)
|
||||
|
||||
extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
|
||||
#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
|
||||
|
||||
|
75
arch/arm/include/asm/hardware/entry-macro-gic.S
Normal file
75
arch/arm/include/asm/hardware/entry-macro-gic.S
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* arch/arm/include/asm/hardware/entry-macro-gic.S
|
||||
*
|
||||
* Low-level IRQ helper macros for GIC
|
||||
*
|
||||
* 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 <asm/hardware/gic.h>
|
||||
|
||||
#ifndef HAVE_GET_IRQNR_PREAMBLE
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =gic_cpu_base_addr
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an interrupt if it's
|
||||
* between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
|
||||
*
|
||||
* A simple read from the controller will tell us the number of the highest
|
||||
* priority enabled interrupt. We then just need to check whether it is in the
|
||||
* valid range for an IRQ (30-1020 inclusive).
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK]
|
||||
/* bits 12-10 = src CPU, 9-0 = int # */
|
||||
|
||||
ldr \tmp, =1021
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt on the
|
||||
* controller, since this requires the original irqstat value which
|
||||
* we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved.. */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
@ -33,10 +33,13 @@
|
||||
#define GIC_DIST_SOFTINT 0xf00
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
|
||||
void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
|
||||
void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
|
||||
void gic_secondary_init(unsigned int);
|
||||
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
|
||||
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
|
||||
void gic_enable_ppi(unsigned int);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -241,18 +241,15 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
|
||||
*
|
||||
*/
|
||||
#ifndef __arch_ioremap
|
||||
#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
|
||||
#define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
|
||||
#define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
|
||||
#define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC)
|
||||
#define iounmap(cookie) __iounmap(cookie)
|
||||
#else
|
||||
#define __arch_ioremap __arm_ioremap
|
||||
#define __arch_iounmap __iounmap
|
||||
#endif
|
||||
|
||||
#define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
|
||||
#define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
|
||||
#define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
|
||||
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
|
||||
#define iounmap(cookie) __arch_iounmap(cookie)
|
||||
#endif
|
||||
#define iounmap __arch_iounmap
|
||||
|
||||
/*
|
||||
* io{read,write}{8,16,32} macros
|
||||
|
@ -33,10 +33,20 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
|
||||
if (oldregs) {
|
||||
memcpy(newregs, oldregs, sizeof(*newregs));
|
||||
} else {
|
||||
__asm__ __volatile__ ("stmia %0, {r0 - r15}"
|
||||
: : "r" (&newregs->ARM_r0));
|
||||
__asm__ __volatile__ ("mrs %0, cpsr"
|
||||
: "=r" (newregs->ARM_cpsr));
|
||||
__asm__ __volatile__ (
|
||||
"stmia %[regs_base], {r0-r12}\n\t"
|
||||
"mov %[_ARM_sp], sp\n\t"
|
||||
"str lr, %[_ARM_lr]\n\t"
|
||||
"adr %[_ARM_pc], 1f\n\t"
|
||||
"mrs %[_ARM_cpsr], cpsr\n\t"
|
||||
"1:"
|
||||
: [_ARM_pc] "=r" (newregs->ARM_pc),
|
||||
[_ARM_cpsr] "=r" (newregs->ARM_cpsr),
|
||||
[_ARM_sp] "=r" (newregs->ARM_sp),
|
||||
[_ARM_lr] "=o" (newregs->ARM_lr)
|
||||
: [regs_base] "r" (&newregs->ARM_r0)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,6 @@
|
||||
struct unwind_table;
|
||||
|
||||
#ifdef CONFIG_ARM_UNWIND
|
||||
struct arm_unwind_mapping {
|
||||
Elf_Shdr *unw_sec;
|
||||
Elf_Shdr *sec_text;
|
||||
struct unwind_table *unwind;
|
||||
};
|
||||
enum {
|
||||
ARM_SEC_INIT,
|
||||
ARM_SEC_DEVINIT,
|
||||
@ -21,14 +16,14 @@ enum {
|
||||
ARM_SEC_DEVEXIT,
|
||||
ARM_SEC_MAX,
|
||||
};
|
||||
struct mod_arch_specific {
|
||||
struct arm_unwind_mapping map[ARM_SEC_MAX];
|
||||
};
|
||||
#else
|
||||
struct mod_arch_specific {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mod_arch_specific {
|
||||
#ifdef CONFIG_ARM_UNWIND
|
||||
struct unwind_table *unwind[ARM_SEC_MAX];
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Include the ARM architecture version.
|
||||
*/
|
||||
|
@ -23,6 +23,8 @@ extern unsigned long kexec_indirection_page;
|
||||
extern unsigned long kexec_mach_type;
|
||||
extern unsigned long kexec_boot_atags;
|
||||
|
||||
static atomic_t waiting_for_crash_ipi;
|
||||
|
||||
/*
|
||||
* Provide a dummy crash_notes definition while crash dump arrives to arm.
|
||||
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
|
||||
@ -37,9 +39,37 @@ void machine_kexec_cleanup(struct kimage *image)
|
||||
{
|
||||
}
|
||||
|
||||
void machine_crash_nonpanic_core(void *unused)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
crash_setup_regs(®s, NULL);
|
||||
printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
|
||||
smp_processor_id());
|
||||
crash_save_cpu(®s, smp_processor_id());
|
||||
flush_cache_all();
|
||||
|
||||
atomic_dec(&waiting_for_crash_ipi);
|
||||
while (1)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
void machine_crash_shutdown(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long msecs;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
|
||||
smp_call_function(machine_crash_nonpanic_core, NULL, false);
|
||||
msecs = 1000; /* Wait at most a second for the other cpus to stop */
|
||||
while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
|
||||
mdelay(1);
|
||||
msecs--;
|
||||
}
|
||||
if (atomic_read(&waiting_for_crash_ipi) > 0)
|
||||
printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
|
||||
|
||||
crash_save_cpu(regs, smp_processor_id());
|
||||
|
||||
printk(KERN_INFO "Loading crashdump kernel...\n");
|
||||
|
@ -67,35 +67,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
|
||||
char *secstrings,
|
||||
struct module *mod)
|
||||
{
|
||||
#ifdef CONFIG_ARM_UNWIND
|
||||
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
||||
struct arm_unwind_mapping *maps = mod->arch.map;
|
||||
|
||||
for (s = sechdrs; s < sechdrs_end; s++) {
|
||||
char const *secname = secstrings + s->sh_name;
|
||||
|
||||
if (strcmp(".ARM.exidx.init.text", secname) == 0)
|
||||
maps[ARM_SEC_INIT].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVINIT].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx", secname) == 0)
|
||||
maps[ARM_SEC_CORE].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
|
||||
maps[ARM_SEC_EXIT].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVEXIT].unw_sec = s;
|
||||
else if (strcmp(".init.text", secname) == 0)
|
||||
maps[ARM_SEC_INIT].sec_text = s;
|
||||
else if (strcmp(".devinit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVINIT].sec_text = s;
|
||||
else if (strcmp(".text", secname) == 0)
|
||||
maps[ARM_SEC_CORE].sec_text = s;
|
||||
else if (strcmp(".exit.text", secname) == 0)
|
||||
maps[ARM_SEC_EXIT].sec_text = s;
|
||||
else if (strcmp(".devexit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVEXIT].sec_text = s;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -300,41 +271,69 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
struct mod_unwind_map {
|
||||
const Elf_Shdr *unw_sec;
|
||||
const Elf_Shdr *txt_sec;
|
||||
};
|
||||
|
||||
int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
||||
struct module *mod)
|
||||
{
|
||||
#ifdef CONFIG_ARM_UNWIND
|
||||
static void register_unwind_tables(struct module *mod)
|
||||
{
|
||||
const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
|
||||
const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
||||
struct mod_unwind_map maps[ARM_SEC_MAX];
|
||||
int i;
|
||||
for (i = 0; i < ARM_SEC_MAX; ++i) {
|
||||
struct arm_unwind_mapping *map = &mod->arch.map[i];
|
||||
if (map->unw_sec && map->sec_text)
|
||||
map->unwind = unwind_table_add(map->unw_sec->sh_addr,
|
||||
map->unw_sec->sh_size,
|
||||
map->sec_text->sh_addr,
|
||||
map->sec_text->sh_size);
|
||||
|
||||
memset(maps, 0, sizeof(maps));
|
||||
|
||||
for (s = sechdrs; s < sechdrs_end; s++) {
|
||||
const char *secname = secstrs + s->sh_name;
|
||||
|
||||
if (!(s->sh_flags & SHF_ALLOC))
|
||||
continue;
|
||||
|
||||
if (strcmp(".ARM.exidx.init.text", secname) == 0)
|
||||
maps[ARM_SEC_INIT].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVINIT].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx", secname) == 0)
|
||||
maps[ARM_SEC_CORE].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
|
||||
maps[ARM_SEC_EXIT].unw_sec = s;
|
||||
else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVEXIT].unw_sec = s;
|
||||
else if (strcmp(".init.text", secname) == 0)
|
||||
maps[ARM_SEC_INIT].txt_sec = s;
|
||||
else if (strcmp(".devinit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVINIT].txt_sec = s;
|
||||
else if (strcmp(".text", secname) == 0)
|
||||
maps[ARM_SEC_CORE].txt_sec = s;
|
||||
else if (strcmp(".exit.text", secname) == 0)
|
||||
maps[ARM_SEC_EXIT].txt_sec = s;
|
||||
else if (strcmp(".devexit.text", secname) == 0)
|
||||
maps[ARM_SEC_DEVEXIT].txt_sec = s;
|
||||
}
|
||||
}
|
||||
|
||||
static void unregister_unwind_tables(struct module *mod)
|
||||
{
|
||||
int i = ARM_SEC_MAX;
|
||||
while (--i >= 0)
|
||||
unwind_table_del(mod->arch.map[i].unwind);
|
||||
}
|
||||
#else
|
||||
static inline void register_unwind_tables(struct module *mod) { }
|
||||
static inline void unregister_unwind_tables(struct module *mod) { }
|
||||
for (i = 0; i < ARM_SEC_MAX; i++)
|
||||
if (maps[i].unw_sec && maps[i].txt_sec)
|
||||
mod->arch.unwind[i] =
|
||||
unwind_table_add(maps[i].unw_sec->sh_addr,
|
||||
maps[i].unw_sec->sh_size,
|
||||
maps[i].txt_sec->sh_addr,
|
||||
maps[i].txt_sec->sh_size);
|
||||
#endif
|
||||
|
||||
int
|
||||
module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
||||
struct module *module)
|
||||
{
|
||||
register_unwind_tables(module);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
unregister_unwind_tables(mod);
|
||||
#ifdef CONFIG_ARM_UNWIND
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARM_SEC_MAX; i++)
|
||||
if (mod->arch.unwind[i])
|
||||
unwind_table_del(mod->arch.unwind[i]);
|
||||
#endif
|
||||
}
|
||||
|
@ -127,8 +127,6 @@ static void __cpuinit twd_calibrate_rate(void)
|
||||
*/
|
||||
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
twd_calibrate_rate();
|
||||
|
||||
clk->name = "local_timer";
|
||||
@ -143,10 +141,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
|
||||
|
||||
/* Make sure our local interrupt controller has this enabled */
|
||||
local_irq_save(flags);
|
||||
irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
|
||||
get_irq_chip(clk->irq)->unmask(clk->irq);
|
||||
local_irq_restore(flags);
|
||||
gic_enable_ppi(clk->irq);
|
||||
|
||||
clockevents_register_device(clk);
|
||||
}
|
||||
|
@ -69,13 +69,10 @@ void __init cns3xxx_map_io(void)
|
||||
}
|
||||
|
||||
/* used by entry-macro.S */
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
void __init cns3xxx_init_irq(void)
|
||||
{
|
||||
gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
|
||||
gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
|
||||
__io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
|
||||
}
|
||||
|
||||
void cns3xxx_power_off(void)
|
||||
|
@ -11,7 +11,6 @@
|
||||
#ifndef __CNS3XXX_CORE_H
|
||||
#define __CNS3XXX_CORE_H
|
||||
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
extern struct sys_timer cns3xxx_timer;
|
||||
|
||||
void __init cns3xxx_map_io(void);
|
||||
|
@ -9,74 +9,10 @@
|
||||
*/
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =gic_cpu_base_addr
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an interrupt if it's
|
||||
* between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
|
||||
*
|
||||
* A simple read from the controller will tell us the number of the highest
|
||||
* priority enabled interrupt. We then just need to check whether it is in the
|
||||
* valid range for an IRQ (30-1020 inclusive).
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
|
||||
|
||||
ldr \tmp, =1021
|
||||
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt on the
|
||||
* controller, since this requires the original irqstat value which
|
||||
* we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved.. */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
|
@ -22,8 +22,8 @@
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t)
|
||||
#define __arch_iounmap(v) davinci_iounmap(v)
|
||||
#define __arch_ioremap davinci_ioremap
|
||||
#define __arch_iounmap davinci_iounmap
|
||||
|
||||
void __iomem *davinci_ioremap(unsigned long phys, size_t size,
|
||||
unsigned int type);
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include <plat/timer-sp.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
@ -35,7 +35,7 @@ extern u32 iop13xx_atux_mem_base;
|
||||
extern size_t iop13xx_atue_mem_size;
|
||||
extern size_t iop13xx_atux_mem_size;
|
||||
|
||||
#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
|
||||
#define __arch_iounmap(a) __iop13xx_iounmap(a)
|
||||
#define __arch_ioremap __iop13xx_ioremap
|
||||
#define __arch_iounmap __iop13xx_iounmap
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr);
|
||||
#define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
|
||||
#define __arch_iounmap(a) __iop3xx_iounmap(a)
|
||||
#define __arch_ioremap __iop3xx_ioremap
|
||||
#define __arch_iounmap __iop3xx_iounmap
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr);
|
||||
#define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
|
||||
#define __arch_iounmap(a) __iop3xx_iounmap(a)
|
||||
#define __arch_ioremap __iop3xx_ioremap
|
||||
#define __arch_iounmap __iop3xx_iounmap
|
||||
|
||||
#endif
|
||||
|
@ -45,8 +45,8 @@ ixp23xx_iounmap(void __iomem *addr)
|
||||
__iounmap(addr);
|
||||
}
|
||||
|
||||
#define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f)
|
||||
#define __arch_iounmap(a) ixp23xx_iounmap(a)
|
||||
#define __arch_ioremap ixp23xx_ioremap
|
||||
#define __arch_iounmap ixp23xx_iounmap
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -74,8 +74,8 @@ static inline void __indirect_iounmap(void __iomem *addr)
|
||||
__iounmap(addr);
|
||||
}
|
||||
|
||||
#define __arch_ioremap(a, s, f) __indirect_ioremap(a, s, f)
|
||||
#define __arch_iounmap(a) __indirect_iounmap(a)
|
||||
#define __arch_ioremap __indirect_ioremap
|
||||
#define __arch_iounmap __indirect_iounmap
|
||||
|
||||
#define writeb(v, p) __indirect_writeb(v, p)
|
||||
#define writew(v, p) __indirect_writew(v, p)
|
||||
|
@ -42,8 +42,8 @@ __arch_iounmap(void __iomem *addr)
|
||||
__iounmap(addr);
|
||||
}
|
||||
|
||||
#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m)
|
||||
#define __arch_iounmap(a) __arch_iounmap(a)
|
||||
#define __arch_ioremap __arch_ioremap
|
||||
#define __arch_iounmap __arch_iounmap
|
||||
#define __io(a) __io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include <mach/board.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
unsigned long clk_get_max_axi_khz(void)
|
||||
{
|
||||
return 0;
|
||||
@ -44,9 +42,8 @@ static void __init msm8x60_init_irq(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
|
||||
gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
|
||||
gic_cpu_init(0, MSM_QGIC_CPU_BASE);
|
||||
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
|
||||
(void *)MSM_QGIC_CPU_BASE);
|
||||
|
||||
/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
|
||||
writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
|
||||
|
@ -105,6 +105,35 @@ omap_irq_base: .word 0
|
||||
9999:
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt
|
||||
* on the controller, since this requires the original irqstat
|
||||
* value which we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
it cc
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
it cs
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
itt eq
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#else /* MULTI_OMAP2 */
|
||||
|
||||
@ -141,74 +170,16 @@ omap_irq_base: .word 0
|
||||
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP4
|
||||
#define HAVE_GET_IRQNR_PREAMBLE
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =OMAP4_IRQ_BASE
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an
|
||||
* interrupt if it's between 30 and 1020. The test_for_ipi
|
||||
* routine below will pick up on IPIs.
|
||||
* A simple read from the controller will tell us the number
|
||||
* of the highest priority enabled interrupt.
|
||||
* We then just need to check whether it is in the
|
||||
* valid range for an IRQ (30-1020 inclusive).
|
||||
*/
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK]
|
||||
|
||||
ldr \tmp, =1021
|
||||
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
#endif
|
||||
|
||||
#endif /* MULTI_OMAP2 */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt
|
||||
* on the controller, since this requires the original irqstat
|
||||
* value which we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
it cc
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
it cs
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
itt eq
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
.macro irq_prio_table
|
||||
.endm
|
||||
|
@ -24,7 +24,6 @@
|
||||
extern void __iomem *l2cache_base;
|
||||
#endif
|
||||
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
extern void __iomem *gic_dist_base_addr;
|
||||
|
||||
extern void __init gic_init_irq(void);
|
||||
|
@ -50,7 +50,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_secondary_init(0);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
|
@ -26,21 +26,22 @@
|
||||
void __iomem *l2cache_base;
|
||||
#endif
|
||||
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
void __iomem *gic_dist_base_addr;
|
||||
|
||||
|
||||
void __init gic_init_irq(void)
|
||||
{
|
||||
void __iomem *gic_cpu_base;
|
||||
|
||||
/* Static mapping, never released */
|
||||
gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
|
||||
BUG_ON(!gic_dist_base_addr);
|
||||
gic_dist_init(0, gic_dist_base_addr, 29);
|
||||
|
||||
/* Static mapping, never released */
|
||||
gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
|
||||
BUG_ON(!gic_cpu_base_addr);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
|
||||
BUG_ON(!gic_cpu_base);
|
||||
|
||||
gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
|
@ -38,8 +38,8 @@ __arch_iounmap(void __iomem *addr)
|
||||
__iounmap(addr);
|
||||
}
|
||||
|
||||
#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m)
|
||||
#define __arch_iounmap(a) __arch_iounmap(a)
|
||||
#define __arch_ioremap __arch_ioremap
|
||||
#define __arch_iounmap __arch_iounmap
|
||||
#define __io(a) __typesafe_io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
|
@ -50,13 +50,10 @@
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/platform.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <plat/timer-sp.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/* used by entry-macro.S and platsmp.c */
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
#ifdef CONFIG_ZONE_DMA
|
||||
/*
|
||||
* Adjust the zones if there are restrictions for DMA access.
|
||||
|
@ -53,7 +53,6 @@ extern struct platform_device realview_i2c_device;
|
||||
extern struct mmci_platform_data realview_mmc0_plat_data;
|
||||
extern struct mmci_platform_data realview_mmc1_plat_data;
|
||||
extern struct clcd_board clcd_plat_data;
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
extern void __iomem *timer0_va_base;
|
||||
extern void __iomem *timer1_va_base;
|
||||
extern void __iomem *timer2_va_base;
|
||||
|
@ -8,74 +8,11 @@
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =gic_cpu_base_addr
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an interrupt if it's
|
||||
* between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
|
||||
*
|
||||
* A simple read from the controller will tell us the number of the highest
|
||||
* priority enabled interrupt. We then just need to check whether it is in the
|
||||
* valid range for an IRQ (30-1020 inclusive).
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
|
||||
|
||||
ldr \tmp, =1021
|
||||
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt on the
|
||||
* controller, since this requires the original irqstat value which
|
||||
* we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved.. */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
|
@ -69,7 +69,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_secondary_init(0);
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
|
@ -364,21 +364,19 @@ static void __init gic_init_irq(void)
|
||||
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
|
||||
|
||||
/* core tile GIC, primary */
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
|
||||
|
||||
#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
|
||||
/* board GIC, secondary */
|
||||
gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
|
||||
gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
|
||||
gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_EB_GIC_CPU_BASE));
|
||||
gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
|
||||
#endif
|
||||
} else {
|
||||
/* board GIC, primary */
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_EB_GIC_CPU_BASE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,13 +304,14 @@ static struct platform_device char_lcd_device = {
|
||||
static void __init gic_init_irq(void)
|
||||
{
|
||||
/* ARM1176 DevChip GIC, primary */
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_init(0, IRQ_DC1176_GIC_START,
|
||||
__io_address(REALVIEW_DC1176_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_DC1176_GIC_CPU_BASE));
|
||||
|
||||
/* board GIC, secondary */
|
||||
gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
|
||||
gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
|
||||
gic_init(1, IRQ_PB1176_GIC_START,
|
||||
__io_address(REALVIEW_PB1176_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_PB1176_GIC_CPU_BASE));
|
||||
gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
|
||||
}
|
||||
|
||||
|
@ -309,13 +309,13 @@ static void __init gic_init_irq(void)
|
||||
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
|
||||
|
||||
/* ARM11MPCore test chip GIC, primary */
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
|
||||
|
||||
/* board GIC, secondary */
|
||||
gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
|
||||
gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
|
||||
gic_init(1, IRQ_PB11MP_GIC_START,
|
||||
__io_address(REALVIEW_PB11MP_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
|
||||
gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
|
||||
}
|
||||
|
||||
|
@ -273,9 +273,9 @@ static struct platform_device pmu_device = {
|
||||
static void __init gic_init_irq(void)
|
||||
{
|
||||
/* ARM PB-A8 on-board GIC */
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START);
|
||||
gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
|
||||
gic_init(0, IRQ_PBA8_GIC_START,
|
||||
__io_address(REALVIEW_PBA8_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_PBA8_GIC_CPU_BASE));
|
||||
}
|
||||
|
||||
static void __init realview_pba8_timer_init(void)
|
||||
|
@ -313,15 +313,12 @@ static void __init gic_init_irq(void)
|
||||
{
|
||||
/* ARM PBX on-board GIC */
|
||||
if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
|
||||
29);
|
||||
gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
|
||||
gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
|
||||
} else {
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
|
||||
IRQ_PBX_GIC_START);
|
||||
gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
|
||||
gic_init(0, IRQ_PBX_GIC_START,
|
||||
__io_address(REALVIEW_PBX_GIC_DIST_BASE),
|
||||
__io_address(REALVIEW_PBX_GIC_CPU_BASE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,6 @@
|
||||
|
||||
#include <mach/regs-irq.h>
|
||||
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
|
||||
unsigned int irq_start);
|
||||
extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
|
||||
@ -122,9 +120,7 @@ void __init s5pv310_init_irq(void)
|
||||
{
|
||||
int irq;
|
||||
|
||||
gic_cpu_base_addr = S5P_VA_GIC_CPU;
|
||||
gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
|
||||
gic_cpu_init(0, S5P_VA_GIC_CPU);
|
||||
gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
|
||||
|
||||
for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
|
||||
combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
|
||||
|
@ -9,8 +9,6 @@
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_mpidr.h>
|
||||
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
|
||||
/*
|
||||
* We use IRQ1 as the IPI
|
||||
*/
|
||||
|
@ -54,7 +54,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_secondary_init(0);
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
|
@ -118,6 +118,16 @@ config SA1100_LART
|
||||
(also known as the LART). See <http://www.lartmaker.nl/> for
|
||||
information on the LART.
|
||||
|
||||
config SA1100_NANOENGINE
|
||||
bool "nanoEngine"
|
||||
select CPU_FREQ_SA1110
|
||||
select PCI
|
||||
select PCI_NANOENGINE
|
||||
help
|
||||
Say Y here if you are using the Bright Star Engineering nanoEngine.
|
||||
See <http://www.brightstareng.com/arm/nanoeng.htm> for information
|
||||
on the BSE nanoEngine.
|
||||
|
||||
config SA1100_PLEB
|
||||
bool "PLEB"
|
||||
select CPU_FREQ_SA1100
|
||||
|
@ -37,6 +37,9 @@ obj-$(CONFIG_SA1100_JORNADA720_SSP) += jornada720_ssp.o
|
||||
obj-$(CONFIG_SA1100_LART) += lart.o
|
||||
led-$(CONFIG_SA1100_LART) += leds-lart.o
|
||||
|
||||
obj-$(CONFIG_SA1100_NANOENGINE) += nanoengine.o
|
||||
obj-$(CONFIG_PCI_NANOENGINE) += pci-nanoengine.o
|
||||
|
||||
obj-$(CONFIG_SA1100_PLEB) += pleb.o
|
||||
|
||||
obj-$(CONFIG_SA1100_SHANNON) += shannon.o
|
||||
|
@ -94,48 +94,47 @@
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
typedef struct {
|
||||
struct sa1100_dram_regs {
|
||||
int speed;
|
||||
u32 mdcnfg;
|
||||
u32 mdcas0;
|
||||
u32 mdcas1;
|
||||
u32 mdcas2;
|
||||
} sa1100_dram_regs_t;
|
||||
};
|
||||
|
||||
|
||||
static struct cpufreq_driver sa1100_driver;
|
||||
|
||||
static sa1100_dram_regs_t sa1100_dram_settings[] =
|
||||
{
|
||||
/* speed, mdcnfg, mdcas0, mdcas1, mdcas2 clock frequency */
|
||||
{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 59.0 MHz */
|
||||
{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 73.7 MHz */
|
||||
{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 88.5 MHz */
|
||||
{ 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */
|
||||
{ 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */
|
||||
{ 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */
|
||||
{ 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */
|
||||
{ 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */
|
||||
{ 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */
|
||||
{ 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */
|
||||
{ 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */
|
||||
{ 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */
|
||||
{ 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */
|
||||
{ 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */
|
||||
{ 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */
|
||||
{ 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */
|
||||
static struct sa1100_dram_regs sa1100_dram_settings[] = {
|
||||
/*speed, mdcnfg, mdcas0, mdcas1, mdcas2, clock freq */
|
||||
{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 59.0 MHz */
|
||||
{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 73.7 MHz */
|
||||
{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 88.5 MHz */
|
||||
{103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
|
||||
{118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
|
||||
{132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
|
||||
{147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
|
||||
{162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
|
||||
{176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
|
||||
{191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
|
||||
{206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
|
||||
{221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
|
||||
{235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
|
||||
{250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
|
||||
{265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
|
||||
{280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
|
||||
{ 0, 0, 0, 0, 0 } /* last entry */
|
||||
};
|
||||
|
||||
static void sa1100_update_dram_timings(int current_speed, int new_speed)
|
||||
{
|
||||
sa1100_dram_regs_t *settings = sa1100_dram_settings;
|
||||
struct sa1100_dram_regs *settings = sa1100_dram_settings;
|
||||
|
||||
/* find speed */
|
||||
while (settings->speed != 0) {
|
||||
if(new_speed == settings->speed)
|
||||
if (new_speed == settings->speed)
|
||||
break;
|
||||
|
||||
|
||||
settings++;
|
||||
}
|
||||
|
||||
@ -149,7 +148,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
|
||||
/* We're going FASTER, so first relax the memory
|
||||
* timings before changing the core frequency
|
||||
*/
|
||||
|
||||
|
||||
/* Half the memory access clock */
|
||||
MDCNFG |= MDCNFG_CDB2;
|
||||
|
||||
@ -187,7 +186,7 @@ static int sa1100_target(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
new_ppcr = sa11x0_freq_to_ppcr(target_freq);
|
||||
switch(relation){
|
||||
switch (relation) {
|
||||
case CPUFREQ_RELATION_L:
|
||||
if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
|
||||
new_ppcr--;
|
||||
|
@ -16,28 +16,24 @@
|
||||
*
|
||||
* The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
|
||||
*/
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
static struct cpufreq_driver sa1110_driver;
|
||||
|
||||
struct sdram_params {
|
||||
const char name[16];
|
||||
const char name[20];
|
||||
u_char rows; /* bits */
|
||||
u_char cas_latency; /* cycles */
|
||||
u_char tck; /* clock cycle time (ns) */
|
||||
@ -107,6 +103,15 @@ static struct sdram_params sdram_tbl[] __initdata = {
|
||||
.twr = 8,
|
||||
.refresh = 64000,
|
||||
.cas_latency = 3,
|
||||
}, { /* Micron MT48LC8M16A2TG-75 */
|
||||
.name = "MT48LC8M16A2TG-75",
|
||||
.rows = 12,
|
||||
.tck = 8,
|
||||
.trcd = 20,
|
||||
.trp = 20,
|
||||
.twr = 8,
|
||||
.refresh = 64000,
|
||||
.cas_latency = 3,
|
||||
},
|
||||
};
|
||||
|
||||
@ -180,11 +185,13 @@ sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
|
||||
sd->mdrefr |= MDREFR_K1DB2;
|
||||
|
||||
/* initial number of '1's in MDCAS + 1 */
|
||||
set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
|
||||
set_mdcas(sd->mdcas, sd_khz >= 62000,
|
||||
ns_to_cycles(sdram->trcd, mem_khz));
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
|
||||
sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
|
||||
printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
|
||||
sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
|
||||
sd->mdcas[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -213,7 +220,7 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
|
||||
|
||||
#ifdef DEBUG
|
||||
mdelay(250);
|
||||
printk("new dri value = %d\n", dri);
|
||||
printk(KERN_DEBUG "new dri value = %d\n", dri);
|
||||
#endif
|
||||
|
||||
sdram_set_refresh(dri);
|
||||
@ -232,7 +239,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
|
||||
unsigned long flags;
|
||||
unsigned int ppcr, unused;
|
||||
|
||||
switch(relation){
|
||||
switch (relation) {
|
||||
case CPUFREQ_RELATION_L:
|
||||
ppcr = sa11x0_freq_to_ppcr(target_freq);
|
||||
if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
|
||||
@ -280,11 +287,10 @@ static int sa1110_target(struct cpufreq_policy *policy,
|
||||
* We wait 20ms to be safe.
|
||||
*/
|
||||
sdram_set_refresh(2);
|
||||
if (!irqs_disabled()) {
|
||||
if (!irqs_disabled())
|
||||
msleep(20);
|
||||
} else {
|
||||
else
|
||||
mdelay(20);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reprogram the DRAM timings with interrupts disabled, and
|
||||
@ -295,7 +301,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
|
||||
local_irq_save(flags);
|
||||
asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
|
||||
udelay(10);
|
||||
__asm__ __volatile__(" \n\
|
||||
__asm__ __volatile__("\n\
|
||||
b 2f \n\
|
||||
.align 5 \n\
|
||||
1: str %3, [%1, #0] @ MDCNFG \n\
|
||||
@ -336,7 +342,9 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cpufreq_driver sa1110_driver = {
|
||||
/* sa1110_driver needs __refdata because it must remain after init registers
|
||||
* it with cpufreq_register_driver() */
|
||||
static struct cpufreq_driver sa1110_driver __refdata = {
|
||||
.flags = CPUFREQ_STICKY,
|
||||
.verify = sa11x0_verify_speed,
|
||||
.target = sa1110_target,
|
||||
@ -349,7 +357,8 @@ static struct sdram_params *sa1110_find_sdram(const char *name)
|
||||
{
|
||||
struct sdram_params *sdram;
|
||||
|
||||
for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++)
|
||||
for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
|
||||
sdram++)
|
||||
if (strcmp(name, sdram->name) == 0)
|
||||
return sdram;
|
||||
|
||||
@ -369,14 +378,14 @@ static int __init sa1110_clk_init(void)
|
||||
if (!name[0]) {
|
||||
if (machine_is_assabet())
|
||||
name = "TC59SM716-CL3";
|
||||
|
||||
if (machine_is_pt_system3())
|
||||
name = "K4S641632D";
|
||||
|
||||
if (machine_is_h3100())
|
||||
name = "KM416S4030CT";
|
||||
if (machine_is_jornada720())
|
||||
name = "K4S281632B-1H";
|
||||
name = "K4S281632B-1H";
|
||||
if (machine_is_nanoengine())
|
||||
name = "MT48LC8M16A2TG-75";
|
||||
}
|
||||
|
||||
sdram = sa1110_find_sdram(name);
|
||||
|
@ -163,10 +163,15 @@ static void sa11x0_register_device(struct platform_device *dev, void *data)
|
||||
|
||||
static struct resource sa11x0udc_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80000000,
|
||||
.end = 0x8000ffff,
|
||||
.start = __PREG(Ser0UDCCR),
|
||||
.end = __PREG(Ser0UDCCR) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser0UDC,
|
||||
.end = IRQ_Ser0UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 sa11x0udc_dma_mask = 0xffffffffUL;
|
||||
@ -184,10 +189,15 @@ static struct platform_device sa11x0udc_device = {
|
||||
|
||||
static struct resource sa11x0uart1_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80010000,
|
||||
.end = 0x8001ffff,
|
||||
.start = __PREG(Ser1UTCR0),
|
||||
.end = __PREG(Ser1UTCR0) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser1UART,
|
||||
.end = IRQ_Ser1UART,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sa11x0uart1_device = {
|
||||
@ -199,10 +209,15 @@ static struct platform_device sa11x0uart1_device = {
|
||||
|
||||
static struct resource sa11x0uart3_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80050000,
|
||||
.end = 0x8005ffff,
|
||||
.start = __PREG(Ser3UTCR0),
|
||||
.end = __PREG(Ser3UTCR0) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser3UART,
|
||||
.end = IRQ_Ser3UART,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sa11x0uart3_device = {
|
||||
@ -214,10 +229,15 @@ static struct platform_device sa11x0uart3_device = {
|
||||
|
||||
static struct resource sa11x0mcp_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80060000,
|
||||
.end = 0x8006ffff,
|
||||
.start = __PREG(Ser4MCCR0),
|
||||
.end = __PREG(Ser4MCCR0) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser4MCP,
|
||||
.end = IRQ_Ser4MCP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
|
||||
@ -244,6 +264,11 @@ static struct resource sa11x0ssp_resources[] = {
|
||||
.end = 0x8007ffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser4SSP,
|
||||
.end = IRQ_Ser4SSP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
|
||||
|
@ -76,4 +76,12 @@ static inline unsigned long get_clock_tick_rate(void)
|
||||
#include "SA-1101.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
|
||||
#define PCIBIOS_MIN_IO 0
|
||||
#define PCIBIOS_MIN_MEM 0
|
||||
#define pcibios_assign_all_busses() 1
|
||||
#define HAVE_ARCH_PCI_SET_DMA_MASK 1
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _ASM_ARCH_HARDWARE_H */
|
||||
|
52
arch/arm/mach-sa1100/include/mach/nanoengine.h
Normal file
52
arch/arm/mach-sa1100/include/mach/nanoengine.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/nanoengine.h
|
||||
*
|
||||
* This file contains the hardware specific definitions for nanoEngine.
|
||||
* Only include this file from SA1100-specific files.
|
||||
*
|
||||
* Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
#ifndef __ASM_ARCH_NANOENGINE_H
|
||||
#define __ASM_ARCH_NANOENGINE_H
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#define GPIO_PC_READY0 GPIO_GPIO(11) /* ready for socket 0 (active high)*/
|
||||
#define GPIO_PC_READY1 GPIO_GPIO(12) /* ready for socket 1 (active high) */
|
||||
#define GPIO_PC_CD0 GPIO_GPIO(13) /* detect for socket 0 (active low) */
|
||||
#define GPIO_PC_CD1 GPIO_GPIO(14) /* detect for socket 1 (active low) */
|
||||
#define GPIO_PC_RESET0 GPIO_GPIO(15) /* reset socket 0 */
|
||||
#define GPIO_PC_RESET1 GPIO_GPIO(16) /* reset socket 1 */
|
||||
|
||||
#define NANOENGINE_IRQ_GPIO_PCI IRQ_GPIO0
|
||||
#define NANOENGINE_IRQ_GPIO_PC_READY0 IRQ_GPIO11
|
||||
#define NANOENGINE_IRQ_GPIO_PC_READY1 IRQ_GPIO12
|
||||
#define NANOENGINE_IRQ_GPIO_PC_CD0 IRQ_GPIO13
|
||||
#define NANOENGINE_IRQ_GPIO_PC_CD1 IRQ_GPIO14
|
||||
|
||||
/*
|
||||
* nanoEngine Memory Map:
|
||||
*
|
||||
* 0000.0000 - 003F.0000 - 4 MB Flash
|
||||
* C000.0000 - C1FF.FFFF - 32 MB SDRAM
|
||||
* 1860.0000 - 186F.FFFF - 1 MB Internal PCI Memory Read/Write
|
||||
* 18A1.0000 - 18A1.FFFF - 64 KB Internal PCI Config Space
|
||||
* 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode
|
||||
* 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode
|
||||
*
|
||||
*/
|
||||
|
||||
#define NANO_PCI_MEM_RW_PHYS 0x18600000
|
||||
#define NANO_PCI_MEM_RW_VIRT 0xf1000000
|
||||
#define NANO_PCI_MEM_RW_SIZE SZ_1M
|
||||
#define NANO_PCI_CONFIG_SPACE_PHYS 0x18A10000
|
||||
#define NANO_PCI_CONFIG_SPACE_VIRT 0xf2000000
|
||||
#define NANO_PCI_CONFIG_SPACE_SIZE SZ_64K
|
||||
|
||||
#endif
|
||||
|
119
arch/arm/mach-sa1100/nanoengine.c
Normal file
119
arch/arm/mach-sa1100/nanoengine.c
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-sa1100/nanoengine.c
|
||||
*
|
||||
* Bright Star Engineering's nanoEngine board init code.
|
||||
*
|
||||
* Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/root_dev.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/nanoengine.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
/* Flash bank 0 */
|
||||
static struct mtd_partition nanoengine_partitions[] = {
|
||||
{
|
||||
.name = "nanoEngine boot firmware and parameter table",
|
||||
.size = 0x00010000, /* 32K */
|
||||
.offset = 0,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
}, {
|
||||
.name = "kernel/initrd reserved",
|
||||
.size = 0x002f0000,
|
||||
.offset = 0x00010000,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
}, {
|
||||
.name = "experimental filesystem allocation",
|
||||
.size = 0x00100000,
|
||||
.offset = 0x00300000,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static struct flash_platform_data nanoengine_flash_data = {
|
||||
.map_name = "jedec_probe",
|
||||
.parts = nanoengine_partitions,
|
||||
.nr_parts = ARRAY_SIZE(nanoengine_partitions),
|
||||
};
|
||||
|
||||
static struct resource nanoengine_flash_resources[] = {
|
||||
{
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = SA1100_CS1_PHYS,
|
||||
.end = SA1100_CS1_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct map_desc nanoengine_io_desc[] __initdata = {
|
||||
{
|
||||
/* System Registers */
|
||||
.virtual = 0xf0000000,
|
||||
.pfn = __phys_to_pfn(0x10000000),
|
||||
.length = 0x00100000,
|
||||
.type = MT_DEVICE
|
||||
}, {
|
||||
/* Internal PCI Memory Read/Write */
|
||||
.virtual = NANO_PCI_MEM_RW_VIRT,
|
||||
.pfn = __phys_to_pfn(NANO_PCI_MEM_RW_PHYS),
|
||||
.length = NANO_PCI_MEM_RW_SIZE,
|
||||
.type = MT_DEVICE
|
||||
}, {
|
||||
/* Internal PCI Config Space */
|
||||
.virtual = NANO_PCI_CONFIG_SPACE_VIRT,
|
||||
.pfn = __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS),
|
||||
.length = NANO_PCI_CONFIG_SPACE_SIZE,
|
||||
.type = MT_DEVICE
|
||||
}
|
||||
};
|
||||
|
||||
static void __init nanoengine_map_io(void)
|
||||
{
|
||||
sa1100_map_io();
|
||||
iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc));
|
||||
|
||||
sa1100_register_uart(0, 1);
|
||||
sa1100_register_uart(1, 2);
|
||||
sa1100_register_uart(2, 3);
|
||||
Ser1SDCR0 |= SDCR0_UART;
|
||||
/* disable IRDA -- UART2 is used as a normal serial port */
|
||||
Ser2UTCR4 = 0;
|
||||
Ser2HSCR0 = 0;
|
||||
}
|
||||
|
||||
static void __init nanoengine_init(void)
|
||||
{
|
||||
sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources,
|
||||
ARRAY_SIZE(nanoengine_flash_resources));
|
||||
}
|
||||
|
||||
MACHINE_START(NANOENGINE, "BSE nanoEngine")
|
||||
.boot_params = 0xc0000000,
|
||||
.map_io = nanoengine_map_io,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = nanoengine_init,
|
||||
MACHINE_END
|
284
arch/arm/mach-sa1100/pci-nanoengine.c
Normal file
284
arch/arm/mach-sa1100/pci-nanoengine.c
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-sa1100/pci-nanoengine.c
|
||||
*
|
||||
* PCI functions for BSE nanoEngine PCI
|
||||
*
|
||||
* Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <mach/nanoengine.h>
|
||||
|
||||
static DEFINE_SPINLOCK(nano_lock);
|
||||
|
||||
static int nanoengine_get_pci_address(struct pci_bus *bus,
|
||||
unsigned int devfn, int where, unsigned long *address)
|
||||
{
|
||||
int ret = PCIBIOS_DEVICE_NOT_FOUND;
|
||||
unsigned int busnr = bus->number;
|
||||
|
||||
*address = NANO_PCI_CONFIG_SPACE_VIRT +
|
||||
((bus->number << 16) | (devfn << 8) | (where & ~3));
|
||||
|
||||
ret = (busnr > 255 || devfn > 255 || where > 255) ?
|
||||
PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned long address;
|
||||
unsigned long flags;
|
||||
u32 v;
|
||||
|
||||
/* nanoEngine PCI bridge does not return -1 for a non-existing
|
||||
* device. We must fake the answer. We know that the only valid
|
||||
* device is device zero at bus 0, which is the network chip. */
|
||||
if (bus->number != 0 || (devfn >> 3) != 0) {
|
||||
v = -1;
|
||||
nanoengine_get_pci_address(bus, devfn, where, &address);
|
||||
goto exit_function;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&nano_lock, flags);
|
||||
|
||||
ret = nanoengine_get_pci_address(bus, devfn, where, &address);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return ret;
|
||||
v = __raw_readl(address);
|
||||
|
||||
spin_unlock_irqrestore(&nano_lock, flags);
|
||||
|
||||
v >>= ((where & 3) * 8);
|
||||
v &= (unsigned long)(-1) >> ((4 - size) * 8);
|
||||
|
||||
exit_function:
|
||||
*val = v;
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 val)
|
||||
{
|
||||
int ret;
|
||||
unsigned long address;
|
||||
unsigned long flags;
|
||||
unsigned shift;
|
||||
u32 v;
|
||||
|
||||
shift = (where & 3) * 8;
|
||||
|
||||
spin_lock_irqsave(&nano_lock, flags);
|
||||
|
||||
ret = nanoengine_get_pci_address(bus, devfn, where, &address);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return ret;
|
||||
v = __raw_readl(address);
|
||||
switch (size) {
|
||||
case 1:
|
||||
v &= ~(0xFF << shift);
|
||||
v |= val << shift;
|
||||
break;
|
||||
case 2:
|
||||
v &= ~(0xFFFF << shift);
|
||||
v |= val << shift;
|
||||
break;
|
||||
case 4:
|
||||
v = val;
|
||||
break;
|
||||
}
|
||||
__raw_writel(v, address);
|
||||
|
||||
spin_unlock_irqrestore(&nano_lock, flags);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops pci_nano_ops = {
|
||||
.read = nanoengine_read_config,
|
||||
.write = nanoengine_write_config,
|
||||
};
|
||||
|
||||
static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
return NANOENGINE_IRQ_GPIO_PCI;
|
||||
}
|
||||
|
||||
struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
return pci_scan_bus(sys->busnr, &pci_nano_ops, sys);
|
||||
}
|
||||
|
||||
static struct resource pci_io_ports = {
|
||||
.name = "PCI IO",
|
||||
.start = 0x400,
|
||||
.end = 0x7FF,
|
||||
.flags = IORESOURCE_IO,
|
||||
};
|
||||
|
||||
static struct resource pci_non_prefetchable_memory = {
|
||||
.name = "PCI non-prefetchable",
|
||||
.start = NANO_PCI_MEM_RW_PHYS,
|
||||
/* nanoEngine documentation says there is a 1 Megabyte window here,
|
||||
* but PCI reports just 128 + 8 kbytes. */
|
||||
.end = NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
|
||||
/* .end = NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
/*
|
||||
* nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
|
||||
* overlaps with previously defined memory.
|
||||
*
|
||||
* Here is what happens:
|
||||
*
|
||||
# dmesg
|
||||
...
|
||||
pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
|
||||
pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
|
||||
pci 0000:00:00.0: reg 14: [io 0x0000-0x003f]
|
||||
pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
|
||||
pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
|
||||
pci 0000:00:00.0: supports D1 D2
|
||||
pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
|
||||
pci 0000:00:00.0: PME# disabled
|
||||
PCI: bus0: Fast back to back transfers enabled
|
||||
pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
|
||||
pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
|
||||
pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
|
||||
pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
|
||||
pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
|
||||
pci 0000:00:00.0: BAR 1: assigned [io 0x0400-0x043f]
|
||||
pci 0000:00:00.0: BAR 1: set to [io 0x0400-0x043f] (PCI address [0x0-0x3f])
|
||||
*
|
||||
* On the other hand, if we do not request the prefetchable memory resource,
|
||||
* linux will alloc it first and the two non-prefetchable memory areas that
|
||||
* are our real interest will not be mapped. So we choose to map it to an
|
||||
* unused area. It gets recognized as expansion ROM, but becomes disabled.
|
||||
*
|
||||
* Here is what happens then:
|
||||
*
|
||||
# dmesg
|
||||
...
|
||||
pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
|
||||
pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
|
||||
pci 0000:00:00.0: reg 14: [io 0x0000-0x003f]
|
||||
pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
|
||||
pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
|
||||
pci 0000:00:00.0: supports D1 D2
|
||||
pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
|
||||
pci 0000:00:00.0: PME# disabled
|
||||
PCI: bus0: Fast back to back transfers enabled
|
||||
pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
|
||||
pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
|
||||
pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
|
||||
pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
|
||||
pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
|
||||
pci 0000:00:00.0: BAR 1: assigned [io 0x0400-0x043f]
|
||||
pci 0000:00:00.0: BAR 1: set to [io 0x0400-0x043f] (PCI address [0x0-0x3f])
|
||||
|
||||
# lspci -vv -s 0000:00:00.0
|
||||
00:00.0 Class 0200: Device 8086:1209 (rev 09)
|
||||
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
|
||||
Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
|
||||
Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
|
||||
Interrupt: pin A routed to IRQ 0
|
||||
Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
|
||||
Region 1: I/O ports at 0400 [size=64]
|
||||
Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
|
||||
[virtual] Expansion ROM at 78000000 [disabled] [size=1M]
|
||||
Capabilities: [dc] Power Management version 2
|
||||
Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
|
||||
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
|
||||
Kernel driver in use: e100
|
||||
Kernel modules: e100
|
||||
*
|
||||
*/
|
||||
static struct resource pci_prefetchable_memory = {
|
||||
.name = "PCI prefetchable",
|
||||
.start = 0x78000000,
|
||||
.end = 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
|
||||
};
|
||||
|
||||
static int __init pci_nanoengine_setup_resources(struct resource **resource)
|
||||
{
|
||||
if (request_resource(&ioport_resource, &pci_io_ports)) {
|
||||
printk(KERN_ERR "PCI: unable to allocate io port region\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
|
||||
release_resource(&pci_io_ports);
|
||||
printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
|
||||
release_resource(&pci_io_ports);
|
||||
release_resource(&pci_non_prefetchable_memory);
|
||||
printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
resource[0] = &pci_io_ports;
|
||||
resource[1] = &pci_non_prefetchable_memory;
|
||||
resource[2] = &pci_prefetchable_memory;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (nr == 0) {
|
||||
sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
|
||||
sys->io_offset = 0x400;
|
||||
ret = pci_nanoengine_setup_resources(sys->resource);
|
||||
/* Enable alternate memory bus master mode, see
|
||||
* "Intel StrongARM SA1110 Developer's Manual",
|
||||
* section 10.8, "Alternate Memory Bus Master Mode". */
|
||||
GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
|
||||
GAFR |= GPIO_MBGNT | GPIO_MBREQ;
|
||||
TUCR |= TUCR_MBGPIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct hw_pci nanoengine_pci __initdata = {
|
||||
.map_irq = pci_nanoengine_map_irq,
|
||||
.nr_controllers = 1,
|
||||
.scan = pci_nanoengine_scan_bus,
|
||||
.setup = pci_nanoengine_setup,
|
||||
};
|
||||
|
||||
static int __init nanoengine_pci_init(void)
|
||||
{
|
||||
if (machine_is_nanoengine())
|
||||
pci_common_init(&nanoengine_pci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(nanoengine_pci_init);
|
@ -166,9 +166,6 @@ static void __init simpad_map_io(void)
|
||||
PCFR = 0;
|
||||
PSDR = 0;
|
||||
|
||||
sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
|
||||
ARRAY_SIZE(simpad_flash_resources));
|
||||
sa11x0_register_mcp(&simpad_mcp_data);
|
||||
}
|
||||
|
||||
static void simpad_power_off(void)
|
||||
@ -216,6 +213,10 @@ static int __init simpad_init(void)
|
||||
|
||||
pm_power_off = simpad_power_off;
|
||||
|
||||
sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
|
||||
ARRAY_SIZE(simpad_flash_resources));
|
||||
sa11x0_register_mcp(&simpad_mcp_data);
|
||||
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
if(ret)
|
||||
printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
/*
|
||||
* Address Interface BusWidth note
|
||||
|
87
arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
Normal file
87
arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
Normal file
@ -0,0 +1,87 @@
|
||||
LIST "partner-jet-setup.txt"
|
||||
LIST "(C) Copyright 2010 Renesas Solutions Corp"
|
||||
LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
|
||||
|
||||
LIST "RWT Setting"
|
||||
EW 0xE6020004, 0xA500
|
||||
EW 0xE6030004, 0xA500
|
||||
|
||||
DD 0x01001000, 0x01001000
|
||||
|
||||
LIST "GPIO Setting"
|
||||
EB 0xE6051013, 0xA2
|
||||
|
||||
LIST "CPG"
|
||||
ED 0xE6150080, 0x00000180
|
||||
ED 0xE61500C0, 0x00000002
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
LIST "FRQCR"
|
||||
ED 0xE6150000, 0x2D1305C3
|
||||
ED 0xE61500E0, 0x9E40358E
|
||||
ED 0xE6150004, 0x80331050
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
ED 0xE61500E4, 0x00002000
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
LIST "PLL"
|
||||
ED 0xE6150028, 0x00004000
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
ED 0xE615002C, 0x93000040
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
LIST "BSC"
|
||||
ED 0xFEC10000, 0x00E0001B
|
||||
|
||||
LIST "SBSC1"
|
||||
ED 0xFE400354, 0x01AD8000
|
||||
ED 0xFE400354, 0x01AD8001
|
||||
|
||||
WAIT 5, 0xFE40009C
|
||||
|
||||
ED 0xFE400008, 0xBCC90151
|
||||
ED 0xFE400040, 0x41774113
|
||||
ED 0xFE400044, 0x2712E229
|
||||
ED 0xFE400048, 0x20C18505
|
||||
ED 0xFE40004C, 0x00110209
|
||||
ED 0xFE400010, 0x00000087
|
||||
|
||||
WAIT 10, 0xFE40009C
|
||||
|
||||
ED 0xFE400084, 0x0000003F
|
||||
EB 0xFE500000, 0x00
|
||||
|
||||
WAIT 5, 0xFE40009C
|
||||
|
||||
ED 0xFE400084, 0x0000FF0A
|
||||
EB 0xFE500000, 0x00
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
ED 0xFE400084, 0x00002201
|
||||
EB 0xFE500000, 0x00
|
||||
ED 0xFE400084, 0x00000302
|
||||
EB 0xFE500000, 0x00
|
||||
EB 0xFE5C0000, 0x00
|
||||
ED 0xFE400008, 0xBCC90159
|
||||
ED 0xFE40008C, 0x88800004
|
||||
ED 0xFE400094, 0x00000004
|
||||
ED 0xFE400028, 0xA55A0032
|
||||
ED 0xFE40002C, 0xA55A000C
|
||||
ED 0xFE400020, 0xA55A2048
|
||||
ED 0xFE400008, 0xBCC90959
|
||||
|
||||
LIST "Change CPGA setting"
|
||||
ED 0xE61500E0, 0x9E40352E
|
||||
ED 0xE6150004, 0x80331050
|
||||
|
||||
WAIT 1, 0xFE40009C
|
||||
|
||||
ED 0xE6150354, 0x00000002
|
20
arch/arm/mach-shmobile/include/mach/zboot.h
Normal file
20
arch/arm/mach-shmobile/include/mach/zboot.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef ZBOOT_H
|
||||
#define ZBOOT_H
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/zboot_macros.h>
|
||||
|
||||
/**************************************************
|
||||
*
|
||||
* board specific settings
|
||||
*
|
||||
**************************************************/
|
||||
|
||||
#ifdef CONFIG_MACH_AP4EVB
|
||||
#define MACH_TYPE MACH_TYPE_AP4EVB
|
||||
#include "mach/head-ap4evb.txt"
|
||||
#else
|
||||
#error "unsupported board."
|
||||
#endif
|
||||
|
||||
#endif /* ZBOOT_H */
|
65
arch/arm/mach-shmobile/include/mach/zboot_macros.h
Normal file
65
arch/arm/mach-shmobile/include/mach/zboot_macros.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef __ZBOOT_MACRO_H
|
||||
#define __ZBOOT_MACRO_H
|
||||
|
||||
/* The LIST command is used to include comments in the script */
|
||||
.macro LIST comment
|
||||
.endm
|
||||
|
||||
/* The ED command is used to write a 32-bit word */
|
||||
.macro ED, addr, data
|
||||
LDR r0, 1f
|
||||
LDR r1, 2f
|
||||
STR r1, [r0]
|
||||
B 3f
|
||||
1 : .long \addr
|
||||
2 : .long \data
|
||||
3 :
|
||||
.endm
|
||||
|
||||
/* The EW command is used to write a 16-bit word */
|
||||
.macro EW, addr, data
|
||||
LDR r0, 1f
|
||||
LDR r1, 2f
|
||||
STRH r1, [r0]
|
||||
B 3f
|
||||
1 : .long \addr
|
||||
2 : .long \data
|
||||
3 :
|
||||
.endm
|
||||
|
||||
/* The EB command is used to write an 8-bit word */
|
||||
.macro EB, addr, data
|
||||
LDR r0, 1f
|
||||
LDR r1, 2f
|
||||
STRB r1, [r0]
|
||||
B 3f
|
||||
1 : .long \addr
|
||||
2 : .long \data
|
||||
3 :
|
||||
.endm
|
||||
|
||||
/* The WAIT command is used to delay the execution */
|
||||
.macro WAIT, time, reg
|
||||
LDR r1, 1f
|
||||
LDR r0, 2f
|
||||
STR r0, [r1]
|
||||
10 :
|
||||
LDR r0, [r1]
|
||||
CMP r0, #0x00000000
|
||||
BNE 10b
|
||||
NOP
|
||||
B 3f
|
||||
1 : .long \reg
|
||||
2 : .long \time * 100
|
||||
3 :
|
||||
.endm
|
||||
|
||||
/* The DD command is used to read a 32-bit word */
|
||||
.macro DD, start, end
|
||||
LDR r1, 1f
|
||||
B 2f
|
||||
1 : .long \start
|
||||
2 :
|
||||
.endm
|
||||
|
||||
#endif /* __ZBOOT_MACRO_H */
|
@ -16,8 +16,8 @@
|
||||
#include <mach/io.h>
|
||||
|
||||
#if defined(CONFIG_ARM_GIC)
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#define HAVE_GET_IRQNR_PREAMBLE
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
/* Uses the GIC interrupt controller built into the cpu */
|
||||
#define ICTRL_BASE (IO_CPU_VIRT + 0x100)
|
||||
@ -32,68 +32,6 @@
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an interrupt
|
||||
* if it's between 30 and 1020. The test_for_ipi routine below will
|
||||
* pick up on IPIs.
|
||||
*
|
||||
* A simple read from the controller will tell us the number of the
|
||||
* highest priority enabled interrupt. We then just need to check
|
||||
* whether it is in the valid range for an IRQ (30-1020 inclusive).
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
|
||||
/* bits 12-10 = src CPU, 9-0 = int # */
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK]
|
||||
|
||||
ldr \tmp, =1021
|
||||
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt on the
|
||||
* controller, since this requires the original irqstat value which
|
||||
* we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved.. */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
|
||||
#else
|
||||
/* legacy interrupt controller for AP16 */
|
||||
.macro disable_fiq
|
||||
|
@ -65,8 +65,8 @@
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#define __arch_ioremap(p, s, t) tegra_ioremap(p, s, t)
|
||||
#define __arch_iounmap(v) tegra_iounmap(v)
|
||||
#define __arch_ioremap tegra_ioremap
|
||||
#define __arch_iounmap tegra_iounmap
|
||||
|
||||
void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
|
||||
void tegra_iounmap(volatile void __iomem *addr);
|
||||
|
@ -94,8 +94,8 @@ void __init tegra_init_irq(void)
|
||||
writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
|
||||
}
|
||||
|
||||
gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
|
||||
gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
|
||||
gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
|
||||
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
|
||||
|
||||
gic = get_irq_chip(29);
|
||||
gic_unmask_irq = gic->unmask;
|
||||
|
@ -48,7 +48,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
|
||||
gic_secondary_init(0);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
|
@ -61,8 +61,8 @@ void __init ux500_init_devices(void)
|
||||
|
||||
void __init ux500_init_irq(void)
|
||||
{
|
||||
gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
|
||||
gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
|
||||
gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE),
|
||||
__io_address(UX500_GIC_CPU_BASE));
|
||||
|
||||
/*
|
||||
* Init clocks here so that they are available for system timer
|
||||
|
@ -11,7 +11,8 @@
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#define HAVE_GET_IRQNR_PREAMBLE
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
@ -22,68 +23,3 @@
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an
|
||||
* interrupt if it's between 30 and 1020. The test_for_ipi
|
||||
* routine below will pick up on IPIs.
|
||||
*
|
||||
* A simple read from the controller will tell us the number
|
||||
* of the highest priority enabled interrupt. We then just
|
||||
* need to check whether it is in the valid range for an
|
||||
* IRQ (30-1020 inclusive).
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
|
||||
/* bits 12-10 = src CPU, 9-0 = int # */
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK]
|
||||
|
||||
ldr \tmp, =1021
|
||||
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ
|
||||
* acknowledge register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of
|
||||
* interrupt on the controller, since this requires the
|
||||
* original irqstat value which we won't easily be able
|
||||
* to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base
|
||||
* are preserved..
|
||||
*/
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
|
@ -44,7 +44,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
|
||||
gic_secondary_init(0);
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
|
@ -49,7 +49,7 @@
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.h>
|
||||
#include <plat/timer-sp.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
|
@ -22,5 +22,3 @@ struct map_desc;
|
||||
|
||||
void v2m_map_io(struct map_desc *tile, size_t num);
|
||||
extern struct sys_timer v2m_timer;
|
||||
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/ct-ca9x4.h>
|
||||
|
||||
#include <plat/timer-sp.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
@ -60,13 +60,10 @@ static void __init ct_ca9x4_map_io(void)
|
||||
v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
|
||||
}
|
||||
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
static void __init ct_ca9x4_init_irq(void)
|
||||
{
|
||||
gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU);
|
||||
gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
|
||||
MMIO_P2V(A9_MPCORE_GIC_CPU));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -1,67 +1,7 @@
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =gic_cpu_base_addr
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-28 are reserved
|
||||
* 29-31 are local. We allow 30 to be used for the watchdog.
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* For now, we ignore all local interrupts so only return an interrupt if it's
|
||||
* between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
|
||||
*
|
||||
* A simple read from the controller will tell us the number of the highest
|
||||
* priority enabled interrupt. We then just need to check whether it is in the
|
||||
* valid range for an IRQ (30-1020 inclusive).
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
|
||||
ldr \tmp, =1021
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #29
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt on the
|
||||
* controller, since this requires the original irqstat value which
|
||||
* we won't easily be able to recreate later.
|
||||
*/
|
||||
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved.. */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #29
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
||||
|
||||
|
@ -51,7 +51,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
gic_secondary_init(0);
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/motherboard.h>
|
||||
|
||||
#include <plat/timer-sp.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
|
@ -294,8 +294,8 @@ static inline void omap44xx_map_common_io(void)
|
||||
extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
|
||||
struct omap_sdrc_params *sdrc_cs1);
|
||||
|
||||
#define __arch_ioremap(p,s,t) omap_ioremap(p,s,t)
|
||||
#define __arch_iounmap(v) omap_iounmap(v)
|
||||
#define __arch_ioremap omap_ioremap
|
||||
#define __arch_iounmap omap_iounmap
|
||||
|
||||
void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
|
||||
void omap_iounmap(volatile void __iomem *addr);
|
||||
|
@ -1,5 +1,4 @@
|
||||
obj-y := clock.o
|
||||
obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
|
||||
obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o
|
||||
obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o
|
||||
ifeq ($(CONFIG_LEDS_CLASS),y)
|
||||
|
@ -50,8 +50,9 @@ sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
|
||||
sa1100_cs-y += sa1100_generic.o
|
||||
sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
|
||||
sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
|
||||
sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
|
||||
sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
|
||||
sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
|
||||
sa1100_cs-$(CONFIG_SA1100_NANOENGINE) += sa1100_nanoengine.o
|
||||
sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
|
||||
sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
|
||||
|
||||
|
@ -53,6 +53,9 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
|
||||
#if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
|
||||
pcmcia_h3600_init,
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_NANOENGINE
|
||||
pcmcia_nanoengine_init,
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_SHANNON
|
||||
pcmcia_shannon_init,
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@ extern int pcmcia_freebird_init(struct device *);
|
||||
extern int pcmcia_gcplus_init(struct device *);
|
||||
extern int pcmcia_graphicsmaster_init(struct device *);
|
||||
extern int pcmcia_h3600_init(struct device *);
|
||||
extern int pcmcia_nanoengine_init(struct device *);
|
||||
extern int pcmcia_pangolin_init(struct device *);
|
||||
extern int pcmcia_pfs168_init(struct device *);
|
||||
extern int pcmcia_shannon_init(struct device *);
|
||||
|
219
drivers/pcmcia/sa1100_nanoengine.c
Normal file
219
drivers/pcmcia/sa1100_nanoengine.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* drivers/pcmcia/sa1100_nanoengine.c
|
||||
*
|
||||
* PCMCIA implementation routines for BSI nanoEngine.
|
||||
*
|
||||
* In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
|
||||
* board you should carefully read this:
|
||||
* http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
|
||||
*
|
||||
* Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
|
||||
*
|
||||
* Based on original work for kernel 2.4 by
|
||||
* Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/nanoengine.h>
|
||||
|
||||
#include "sa1100_generic.h"
|
||||
|
||||
static struct pcmcia_irqs irqs_skt0[] = {
|
||||
/* socket, IRQ, name */
|
||||
{ 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" },
|
||||
};
|
||||
|
||||
static struct pcmcia_irqs irqs_skt1[] = {
|
||||
/* socket, IRQ, name */
|
||||
{ 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" },
|
||||
};
|
||||
|
||||
struct nanoengine_pins {
|
||||
unsigned input_pins;
|
||||
unsigned output_pins;
|
||||
unsigned clear_outputs;
|
||||
unsigned transition_pins;
|
||||
unsigned pci_irq;
|
||||
struct pcmcia_irqs *pcmcia_irqs;
|
||||
unsigned pcmcia_irqs_size;
|
||||
};
|
||||
|
||||
static struct nanoengine_pins nano_skts[] = {
|
||||
{
|
||||
.input_pins = GPIO_PC_READY0 | GPIO_PC_CD0,
|
||||
.output_pins = GPIO_PC_RESET0,
|
||||
.clear_outputs = GPIO_PC_RESET0,
|
||||
.transition_pins = NANOENGINE_IRQ_GPIO_PC_CD0,
|
||||
.pci_irq = NANOENGINE_IRQ_GPIO_PC_READY0,
|
||||
.pcmcia_irqs = irqs_skt0,
|
||||
.pcmcia_irqs_size = ARRAY_SIZE(irqs_skt0)
|
||||
}, {
|
||||
.input_pins = GPIO_PC_READY1 | GPIO_PC_CD1,
|
||||
.output_pins = GPIO_PC_RESET1,
|
||||
.clear_outputs = GPIO_PC_RESET1,
|
||||
.transition_pins = NANOENGINE_IRQ_GPIO_PC_CD1,
|
||||
.pci_irq = NANOENGINE_IRQ_GPIO_PC_READY1,
|
||||
.pcmcia_irqs = irqs_skt1,
|
||||
.pcmcia_irqs_size = ARRAY_SIZE(irqs_skt1)
|
||||
}
|
||||
};
|
||||
|
||||
unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
|
||||
|
||||
static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
unsigned i = skt->nr;
|
||||
|
||||
if (i >= num_nano_pcmcia_sockets)
|
||||
return -ENXIO;
|
||||
|
||||
GPDR &= ~nano_skts[i].input_pins;
|
||||
GPDR |= nano_skts[i].output_pins;
|
||||
GPCR = nano_skts[i].clear_outputs;
|
||||
set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
|
||||
skt->socket.pci_irq = nano_skts[i].pci_irq;
|
||||
|
||||
return soc_pcmcia_request_irqs(skt,
|
||||
nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release all resources.
|
||||
*/
|
||||
static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
unsigned i = skt->nr;
|
||||
|
||||
if (i >= num_nano_pcmcia_sockets)
|
||||
return;
|
||||
|
||||
soc_pcmcia_free_irqs(skt,
|
||||
nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
|
||||
}
|
||||
|
||||
static int nanoengine_pcmcia_configure_socket(
|
||||
struct soc_pcmcia_socket *skt, const socket_state_t *state)
|
||||
{
|
||||
unsigned reset;
|
||||
unsigned i = skt->nr;
|
||||
|
||||
if (i >= num_nano_pcmcia_sockets)
|
||||
return -ENXIO;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
reset = GPIO_PC_RESET0;
|
||||
break;
|
||||
case 1:
|
||||
reset = GPIO_PC_RESET1;
|
||||
break;
|
||||
default:
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (state->flags & SS_RESET)
|
||||
GPSR = reset;
|
||||
else
|
||||
GPCR = reset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nanoengine_pcmcia_socket_state(
|
||||
struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
|
||||
{
|
||||
unsigned long levels = GPLR;
|
||||
unsigned i = skt->nr;
|
||||
|
||||
if (i >= num_nano_pcmcia_sockets)
|
||||
return;
|
||||
|
||||
memset(state, 0, sizeof(struct pcmcia_state));
|
||||
switch (i) {
|
||||
case 0:
|
||||
state->ready = (levels & GPIO_PC_READY0) ? 1 : 0;
|
||||
state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0;
|
||||
break;
|
||||
case 1:
|
||||
state->ready = (levels & GPIO_PC_READY1) ? 1 : 0;
|
||||
state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
state->bvd1 = 1;
|
||||
state->bvd2 = 1;
|
||||
state->wrprot = 0; /* Not available */
|
||||
state->vs_3v = 1; /* Can only apply 3.3V */
|
||||
state->vs_Xv = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable card status IRQs on (re-)initialisation. This can
|
||||
* be called at initialisation, power management event, or
|
||||
* pcmcia event.
|
||||
*/
|
||||
static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
unsigned i = skt->nr;
|
||||
|
||||
if (i >= num_nano_pcmcia_sockets)
|
||||
return;
|
||||
|
||||
soc_pcmcia_enable_irqs(skt,
|
||||
nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable card status IRQs on suspend.
|
||||
*/
|
||||
static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
unsigned i = skt->nr;
|
||||
|
||||
if (i >= num_nano_pcmcia_sockets)
|
||||
return;
|
||||
|
||||
soc_pcmcia_disable_irqs(skt,
|
||||
nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
|
||||
}
|
||||
|
||||
static struct pcmcia_low_level nanoengine_pcmcia_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.hw_init = nanoengine_pcmcia_hw_init,
|
||||
.hw_shutdown = nanoengine_pcmcia_hw_shutdown,
|
||||
|
||||
.configure_socket = nanoengine_pcmcia_configure_socket,
|
||||
.socket_state = nanoengine_pcmcia_socket_state,
|
||||
.socket_init = nanoengine_pcmcia_socket_init,
|
||||
.socket_suspend = nanoengine_pcmcia_socket_suspend,
|
||||
};
|
||||
|
||||
int pcmcia_nanoengine_init(struct device *dev)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
if (machine_is_nanoengine())
|
||||
ret = sa11xx_drv_pcmcia_probe(
|
||||
dev, &nanoengine_pcmcia_ops, 0, 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -31,20 +31,20 @@
|
||||
======================================================================*/
|
||||
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include "soc_common.h"
|
||||
@ -74,7 +74,8 @@ EXPORT_SYMBOL(soc_pcmcia_debug);
|
||||
|
||||
#endif
|
||||
|
||||
#define to_soc_pcmcia_socket(x) container_of(x, struct soc_pcmcia_socket, socket)
|
||||
#define to_soc_pcmcia_socket(x) \
|
||||
container_of(x, struct soc_pcmcia_socket, socket)
|
||||
|
||||
static unsigned short
|
||||
calc_speed(unsigned short *spds, int num, unsigned short dflt)
|
||||
@ -91,11 +92,15 @@ calc_speed(unsigned short *spds, int num, unsigned short dflt)
|
||||
return speed;
|
||||
}
|
||||
|
||||
void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
|
||||
void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
|
||||
struct soc_pcmcia_timing *timing)
|
||||
{
|
||||
timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
|
||||
timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
|
||||
timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
|
||||
timing->io =
|
||||
calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
|
||||
timing->mem =
|
||||
calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
|
||||
timing->attr =
|
||||
calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
|
||||
}
|
||||
EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
|
||||
|
||||
@ -137,8 +142,8 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
|
||||
*
|
||||
* Convert PCMCIA socket state to our socket configure structure.
|
||||
*/
|
||||
static int
|
||||
soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
|
||||
static int soc_common_pcmcia_config_skt(
|
||||
struct soc_pcmcia_socket *skt, socket_state_t *state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -150,7 +155,8 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat
|
||||
*/
|
||||
if (skt->irq_state != 1 && state->io_irq) {
|
||||
skt->irq_state = 1;
|
||||
set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
|
||||
set_irq_type(skt->socket.pci_irq,
|
||||
IRQ_TYPE_EDGE_FALLING);
|
||||
} else if (skt->irq_state == 1 && state->io_irq == 0) {
|
||||
skt->irq_state = 0;
|
||||
set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
|
||||
@ -304,24 +310,24 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
|
||||
* of power configuration, reset, &c. We also record the value of
|
||||
* `state' in order to regurgitate it to the PCMCIA core later.
|
||||
*/
|
||||
static int
|
||||
soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
|
||||
static int soc_common_pcmcia_set_socket(
|
||||
struct pcmcia_socket *sock, socket_state_t *state)
|
||||
{
|
||||
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
|
||||
|
||||
debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
|
||||
(state->csc_mask==0)?"<NONE> ":"",
|
||||
(state->csc_mask&SS_DETECT)?"DETECT ":"",
|
||||
(state->csc_mask&SS_READY)?"READY ":"",
|
||||
(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
|
||||
(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
|
||||
(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
|
||||
(state->flags==0)?"<NONE> ":"",
|
||||
(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
|
||||
(state->flags&SS_IOCARD)?"IOCARD ":"",
|
||||
(state->flags&SS_RESET)?"RESET ":"",
|
||||
(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
|
||||
(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
|
||||
debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
|
||||
(state->csc_mask == 0) ? "<NONE> " : "",
|
||||
(state->csc_mask & SS_DETECT) ? "DETECT " : "",
|
||||
(state->csc_mask & SS_READY) ? "READY " : "",
|
||||
(state->csc_mask & SS_BATDEAD) ? "BATDEAD " : "",
|
||||
(state->csc_mask & SS_BATWARN) ? "BATWARN " : "",
|
||||
(state->csc_mask & SS_STSCHG) ? "STSCHG " : "",
|
||||
(state->flags == 0) ? "<NONE> " : "",
|
||||
(state->flags & SS_PWR_AUTO) ? "PWR_AUTO " : "",
|
||||
(state->flags & SS_IOCARD) ? "IOCARD " : "",
|
||||
(state->flags & SS_RESET) ? "RESET " : "",
|
||||
(state->flags & SS_SPKR_ENA) ? "SPKR_ENA " : "",
|
||||
(state->flags & SS_OUTPUT_ENA) ? "OUTPUT_ENA " : "",
|
||||
state->Vcc, state->Vpp, state->io_irq);
|
||||
|
||||
return soc_common_pcmcia_config_skt(skt, state);
|
||||
@ -336,8 +342,8 @@ soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
static int
|
||||
soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
|
||||
static int soc_common_pcmcia_set_io_map(
|
||||
struct pcmcia_socket *sock, struct pccard_io_map *map)
|
||||
{
|
||||
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
|
||||
unsigned short speed = map->speed;
|
||||
@ -346,14 +352,14 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
|
||||
map->map, map->speed, (unsigned long long)map->start,
|
||||
(unsigned long long)map->stop);
|
||||
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
|
||||
(map->flags==0)?"<NONE>":"",
|
||||
(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
|
||||
(map->flags&MAP_16BIT)?"16BIT ":"",
|
||||
(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
|
||||
(map->flags&MAP_0WS)?"0WS ":"",
|
||||
(map->flags&MAP_WRPROT)?"WRPROT ":"",
|
||||
(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
|
||||
(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
|
||||
(map->flags == 0) ? "<NONE>" : "",
|
||||
(map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
|
||||
(map->flags & MAP_16BIT) ? "16BIT " : "",
|
||||
(map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
|
||||
(map->flags & MAP_0WS) ? "0WS " : "",
|
||||
(map->flags & MAP_WRPROT) ? "WRPROT " : "",
|
||||
(map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "",
|
||||
(map->flags & MAP_PREFETCH) ? "PREFETCH " : "");
|
||||
|
||||
if (map->map >= MAX_IO_WIN) {
|
||||
printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
|
||||
@ -390,8 +396,8 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
|
||||
*
|
||||
* Returns: 0 on success, -ERRNO on error
|
||||
*/
|
||||
static int
|
||||
soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
|
||||
static int soc_common_pcmcia_set_mem_map(
|
||||
struct pcmcia_socket *sock, struct pccard_mem_map *map)
|
||||
{
|
||||
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
|
||||
struct resource *res;
|
||||
@ -400,14 +406,14 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
|
||||
debug(skt, 2, "map %u speed %u card_start %08x\n",
|
||||
map->map, map->speed, map->card_start);
|
||||
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
|
||||
(map->flags==0)?"<NONE>":"",
|
||||
(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
|
||||
(map->flags&MAP_16BIT)?"16BIT ":"",
|
||||
(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
|
||||
(map->flags&MAP_0WS)?"0WS ":"",
|
||||
(map->flags&MAP_WRPROT)?"WRPROT ":"",
|
||||
(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
|
||||
(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
|
||||
(map->flags == 0) ? "<NONE>" : "",
|
||||
(map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
|
||||
(map->flags & MAP_16BIT) ? "16BIT " : "",
|
||||
(map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
|
||||
(map->flags & MAP_0WS) ? "0WS " : "",
|
||||
(map->flags & MAP_WRPROT) ? "WRPROT " : "",
|
||||
(map->flags & MAP_ATTRIB) ? "ATTRIB " : "",
|
||||
(map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "");
|
||||
|
||||
if (map->map >= MAX_WIN)
|
||||
return -EINVAL;
|
||||
@ -462,8 +468,8 @@ static struct bittbl conf_bits[] = {
|
||||
{ SS_OUTPUT_ENA, "SS_OUTPUT_ENA" },
|
||||
};
|
||||
|
||||
static void
|
||||
dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
|
||||
static void dump_bits(char **p, const char *prefix,
|
||||
unsigned int val, struct bittbl *bits, int sz)
|
||||
{
|
||||
char *b = *p;
|
||||
int i;
|
||||
@ -481,13 +487,14 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
|
||||
*
|
||||
* Returns: the number of characters added to the buffer
|
||||
*/
|
||||
static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_status(
|
||||
struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct soc_pcmcia_socket *skt =
|
||||
container_of(dev, struct soc_pcmcia_socket, socket.dev);
|
||||
char *p = buf;
|
||||
|
||||
p+=sprintf(p, "slot : %d\n", skt->nr);
|
||||
p += sprintf(p, "slot : %d\n", skt->nr);
|
||||
|
||||
dump_bits(&p, "status", skt->status,
|
||||
status_bits, ARRAY_SIZE(status_bits));
|
||||
@ -496,12 +503,12 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, ch
|
||||
dump_bits(&p, "cs_flags", skt->cs_state.flags,
|
||||
conf_bits, ARRAY_SIZE(conf_bits));
|
||||
|
||||
p+=sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc);
|
||||
p+=sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp);
|
||||
p+=sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq,
|
||||
p += sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc);
|
||||
p += sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp);
|
||||
p += sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq,
|
||||
skt->socket.pci_irq);
|
||||
if (skt->ops->show_timing)
|
||||
p+=skt->ops->show_timing(skt, p);
|
||||
p += skt->ops->show_timing(skt, p);
|
||||
|
||||
return p-buf;
|
||||
}
|
||||
@ -594,7 +601,7 @@ soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
|
||||
|
||||
mutex_lock(&soc_pcmcia_sockets_lock);
|
||||
list_for_each_entry(skt, &soc_pcmcia_sockets, node)
|
||||
if ( skt->ops->frequency_change )
|
||||
if (skt->ops->frequency_change)
|
||||
ret += skt->ops->frequency_change(skt, val, freqs);
|
||||
mutex_unlock(&soc_pcmcia_sockets_lock);
|
||||
|
||||
@ -620,7 +627,8 @@ fs_initcall(soc_pcmcia_cpufreq_register);
|
||||
|
||||
static void soc_pcmcia_cpufreq_unregister(void)
|
||||
{
|
||||
cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
|
||||
cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
}
|
||||
module_exit(soc_pcmcia_cpufreq_unregister);
|
||||
|
||||
|
@ -39,10 +39,10 @@
|
||||
#include <mach/regs-ost.h>
|
||||
#endif
|
||||
|
||||
#define RTC_DEF_DIVIDER 32768 - 1
|
||||
#define RTC_DEF_DIVIDER (32768 - 1)
|
||||
#define RTC_DEF_TRIM 0
|
||||
|
||||
static unsigned long rtc_freq = 1024;
|
||||
static const unsigned long RTC_FREQ = 1024;
|
||||
static unsigned long timer_freq;
|
||||
static struct rtc_time rtc_alarm;
|
||||
static DEFINE_SPINLOCK(sa1100_rtc_lock);
|
||||
@ -61,7 +61,8 @@ static inline int rtc_periodic_alarm(struct rtc_time *tm)
|
||||
* Calculate the next alarm time given the requested alarm time mask
|
||||
* and the current time.
|
||||
*/
|
||||
static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
|
||||
static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
|
||||
struct rtc_time *alrm)
|
||||
{
|
||||
unsigned long next_time;
|
||||
unsigned long now_time;
|
||||
@ -116,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
||||
rtsr = RTSR;
|
||||
/* clear interrupt sources */
|
||||
RTSR = 0;
|
||||
RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
|
||||
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
|
||||
* See also the comments in sa1100_rtc_probe(). */
|
||||
if (rtsr & (RTSR_ALE | RTSR_HZE)) {
|
||||
/* This is the original code, before there was the if test
|
||||
* above. This code does not clear interrupts that were not
|
||||
* enabled. */
|
||||
RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
|
||||
} else {
|
||||
/* For some reason, it is possible to enter this routine
|
||||
* without interruptions enabled, it has been tested with
|
||||
* several units (Bug in SA11xx chip?).
|
||||
*
|
||||
* This situation leads to an infinite "loop" of interrupt
|
||||
* routine calling and as a result the processor seems to
|
||||
* lock on its first call to open(). */
|
||||
RTSR = RTSR_AL | RTSR_HZ;
|
||||
}
|
||||
|
||||
/* clear alarm interrupt if it has occurred */
|
||||
if (rtsr & RTSR_AL)
|
||||
@ -139,8 +156,58 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int sa1100_irq_set_freq(struct device *dev, int freq)
|
||||
{
|
||||
if (freq < 1 || freq > timer_freq) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
rtc->irq_freq = freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtc_timer1_count;
|
||||
|
||||
static int sa1100_irq_set_state(struct device *dev, int enabled)
|
||||
{
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
if (enabled) {
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
OSMR1 = timer_freq / rtc->irq_freq + OSCR;
|
||||
OIER |= OIER_E1;
|
||||
rtc_timer1_count = 1;
|
||||
} else {
|
||||
OIER &= ~OIER_E1;
|
||||
}
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
|
||||
{
|
||||
unsigned long diff;
|
||||
unsigned long period = timer_freq / rtc->irq_freq;
|
||||
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
|
||||
do {
|
||||
OSMR1 += period;
|
||||
diff = OSMR1 - OSCR;
|
||||
/* If OSCR > OSMR1, diff is a very large number (unsigned
|
||||
* math). This means we have a lost interrupt. */
|
||||
} while (diff > period);
|
||||
OIER |= OIER_E1;
|
||||
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t timer1_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev_id);
|
||||
@ -158,7 +225,11 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
|
||||
rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
|
||||
|
||||
if (rtc_timer1_count == 1)
|
||||
rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
|
||||
rtc_timer1_count =
|
||||
(rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
|
||||
|
||||
/* retrigger. */
|
||||
sa1100_timer1_retrigger(rtc);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -166,8 +237,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
|
||||
static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||
{
|
||||
if (data & RTC_PF) {
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
/* interpolate missed periods and set match for the next */
|
||||
unsigned long period = timer_freq / rtc_freq;
|
||||
unsigned long period = timer_freq / rtc->irq_freq;
|
||||
unsigned long oscr = OSCR;
|
||||
unsigned long osmr1 = OSMR1;
|
||||
unsigned long missed = (oscr - osmr1)/period;
|
||||
@ -178,7 +251,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||
* Here we compare (match - OSCR) 8 instead of 0 --
|
||||
* see comment in pxa_timer_interrupt() for explanation.
|
||||
*/
|
||||
while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
|
||||
while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
|
||||
data += 0x100;
|
||||
OSSR = OSSR_M1; /* clear match on timer 1 */
|
||||
OSMR1 = osmr1 + period;
|
||||
@ -190,25 +263,29 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||
static int sa1100_rtc_open(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
|
||||
"rtc 1Hz", dev);
|
||||
"rtc 1Hz", dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
|
||||
goto fail_ui;
|
||||
}
|
||||
ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
|
||||
"rtc Alrm", dev);
|
||||
"rtc Alrm", dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
|
||||
goto fail_ai;
|
||||
}
|
||||
ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
|
||||
"rtc timer", dev);
|
||||
"rtc timer", dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
|
||||
goto fail_pi;
|
||||
}
|
||||
rtc->max_user_freq = RTC_FREQ;
|
||||
sa1100_irq_set_freq(dev, RTC_FREQ);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_pi:
|
||||
@ -236,7 +313,7 @@ static void sa1100_rtc_release(struct device *dev)
|
||||
static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
case RTC_AIE_OFF:
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
RTSR &= ~RTSR_ALE;
|
||||
@ -257,25 +334,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||
RTSR |= RTSR_HZE;
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
return 0;
|
||||
case RTC_PIE_OFF:
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
OIER &= ~OIER_E1;
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
return 0;
|
||||
case RTC_PIE_ON:
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
OSMR1 = timer_freq / rtc_freq + OSCR;
|
||||
OIER |= OIER_E1;
|
||||
rtc_timer1_count = 1;
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
return 0;
|
||||
case RTC_IRQP_READ:
|
||||
return put_user(rtc_freq, (unsigned long *)arg);
|
||||
case RTC_IRQP_SET:
|
||||
if (arg < 1 || arg > timer_freq)
|
||||
return -EINVAL;
|
||||
rtc_freq = arg;
|
||||
return 0;
|
||||
}
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
@ -327,12 +385,15 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
|
||||
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
{
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
|
||||
seq_printf(seq, "update_IRQ\t: %s\n",
|
||||
(RTSR & RTSR_HZE) ? "yes" : "no");
|
||||
seq_printf(seq, "periodic_IRQ\t: %s\n",
|
||||
(OIER & OIER_E1) ? "yes" : "no");
|
||||
seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
|
||||
seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
|
||||
seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -347,6 +408,8 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
|
||||
.read_alarm = sa1100_rtc_read_alarm,
|
||||
.set_alarm = sa1100_rtc_set_alarm,
|
||||
.proc = sa1100_rtc_proc,
|
||||
.irq_set_freq = sa1100_irq_set_freq,
|
||||
.irq_set_state = sa1100_irq_set_state,
|
||||
};
|
||||
|
||||
static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||
@ -364,7 +427,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||
*/
|
||||
if (RTTR == 0) {
|
||||
RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
|
||||
dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
|
||||
dev_warn(&pdev->dev, "warning: "
|
||||
"initializing default clock divider/trim value\n");
|
||||
/* The current RTC value probably doesn't make sense either */
|
||||
RCNR = 0;
|
||||
}
|
||||
@ -372,13 +436,42 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
|
||||
THIS_MODULE);
|
||||
THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc))
|
||||
return PTR_ERR(rtc);
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
|
||||
/* Set the irq_freq */
|
||||
/*TODO: Find out who is messing with this value after we initialize
|
||||
* it here.*/
|
||||
rtc->irq_freq = RTC_FREQ;
|
||||
|
||||
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
|
||||
* See also the comments in sa1100_rtc_interrupt().
|
||||
*
|
||||
* Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
|
||||
* interrupt pending, even though interrupts were never enabled.
|
||||
* In this case, this bit it must be reset before enabling
|
||||
* interruptions to avoid a nonexistent interrupt to occur.
|
||||
*
|
||||
* In principle, the same problem would apply to bit 0, although it has
|
||||
* never been observed to happen.
|
||||
*
|
||||
* This issue is addressed both here and in sa1100_rtc_interrupt().
|
||||
* If the issue is not addressed here, in the times when the processor
|
||||
* wakes up with the bit set there will be one spurious interrupt.
|
||||
*
|
||||
* The issue is also dealt with in sa1100_rtc_interrupt() to be on the
|
||||
* safe side, once the condition that lead to this strange
|
||||
* initialization is unknown and could in principle happen during
|
||||
* normal processing.
|
||||
*
|
||||
* Notice that clearing bit 1 and 0 is accomplished by writting ONES to
|
||||
* the corresponding bits in RTSR. */
|
||||
RTSR = RTSR_AL | RTSR_HZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -386,7 +479,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_device *rtc = platform_get_drvdata(pdev);
|
||||
|
||||
if (rtc)
|
||||
if (rtc)
|
||||
rtc_device_unregister(rtc);
|
||||
|
||||
return 0;
|
||||
|
@ -499,7 +499,7 @@ static int __init parse_crash_elf64_headers(void)
|
||||
/* Do some basic Verification. */
|
||||
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
|
||||
(ehdr.e_type != ET_CORE) ||
|
||||
!vmcore_elf_check_arch(&ehdr) ||
|
||||
!vmcore_elf64_check_arch(&ehdr) ||
|
||||
ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
|
||||
ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
ehdr.e_version != EV_CURRENT ||
|
||||
|
@ -20,7 +20,14 @@ extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
|
||||
#define vmcore_elf_check_arch_cross(x) 0
|
||||
#endif
|
||||
|
||||
#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
|
||||
/*
|
||||
* Architecture code can redefine this if there are any special checks
|
||||
* needed for 64-bit ELF vmcores. In case of 32-bit only architecture,
|
||||
* this can be set to zero.
|
||||
*/
|
||||
#ifndef vmcore_elf64_check_arch
|
||||
#define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* is_kdump_kernel() checks whether this kernel is booting after a panic of
|
||||
|
@ -38,6 +38,7 @@ static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
|
||||
static char gpfx; /* prefix for global symbol name (sometimes '_') */
|
||||
static struct stat sb; /* Remember .st_size, etc. */
|
||||
static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
|
||||
static const char *altmcount; /* alternate mcount symbol name */
|
||||
|
||||
/* setjmp() return values */
|
||||
enum {
|
||||
@ -299,7 +300,9 @@ do_file(char const *const fname)
|
||||
fail_file();
|
||||
} break;
|
||||
case EM_386: reltype = R_386_32; break;
|
||||
case EM_ARM: reltype = R_ARM_ABS32; break;
|
||||
case EM_ARM: reltype = R_ARM_ABS32;
|
||||
altmcount = "__gnu_mcount_nc";
|
||||
break;
|
||||
case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
|
||||
case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
|
||||
case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
|
||||
@ -357,7 +360,7 @@ do_file(char const *const fname)
|
||||
int
|
||||
main(int argc, char const *argv[])
|
||||
{
|
||||
const char ftrace[] = "kernel/trace/ftrace.o";
|
||||
const char ftrace[] = "/ftrace.o";
|
||||
int ftrace_size = sizeof(ftrace) - 1;
|
||||
int n_error = 0; /* gcc-4.3.0 false positive complaint */
|
||||
|
||||
|
@ -275,11 +275,12 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
|
||||
Elf_Sym const *const symp =
|
||||
&sym0[Elf_r_sym(relp)];
|
||||
char const *symname = &str0[w(symp->st_name)];
|
||||
char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
|
||||
|
||||
if ('.' == symname[0])
|
||||
++symname; /* ppc64 hack */
|
||||
if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
|
||||
symname))
|
||||
if (0 == strcmp(mcount, symname) ||
|
||||
(altmcount && 0 == strcmp(altmcount, symname)))
|
||||
mcountsym = Elf_r_sym(relp);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user