Merge branches 'at91', 'ixp', 'master', 'misc', 'pxa' and 'realview' into devel
* at91: [ARM] 4802/1: Fix typo and remove vague comment [ARM] 4660/3: at91: allow selecting UART for early kernel messages [ARM] 4739/1: at91sam9263: make gpio bank C and D irqs work * ixp: [ARM] 4809/2: ixp4xx: Merge dsmg600-power.c into dsmg600-setup.c [ARM] 4808/2: ixp4xx: Merge nas100d-power.c into nas100d-setup.c [ARM] 4807/2: ixp4xx: Merge nslu2-power.c into nslu2-setup.c [ARM] 4806/1: ixp4xx: Ethernet support for the nslu2 and nas100d boards [ARM] 4805/1: ixp4xx: Use leds-gpio driver instead of IXP4XX-GPIO-LED driver [ARM] 4715/2: Ethernet support for IXDP425 boards [ARM] 4714/2: Headers for IXP4xx built-in Ethernet and WAN drivers [ARM] 4713/3: Adds drivers for IXP4xx QMgr and NPE features [ARM] 4712/2: Adds functions to read and write IXP4xx "feature" bits [ARM] 4774/2: ixp4xx: Register dsmg600 rtc i2c_board_info [ARM] 4773/2: ixp4xx: Register nas100d rtc i2c_board_info [ARM] 4772/2: ixp4xx: Register nslu2 rtc i2c_board_info [ARM] 4769/2: ixp4xx: Button updates for the dsmg600 board [ARM] 4768/2: ixp4xx: Button and LED updates for the nas100d board [ARM] 4767/2: ixp4xx: Add bitops.h include to io.h [ARM] 4766/2: ixp4xx: Update ixp4xx_defconfig, enabling all supported boards * master: [ARM] 4810/1: - Fix 'section mismatch' building warnings [ARM] xtime_seqlock: fix more ARM machines for xtime deadlocking [ARM] 21285 serial: fix build error * misc: [ARM] 4736/1: Export atags to userspace and allow kexec to use customised atags * pxa: [ARM] 4798/1: pcm027: fix missing header file [ARM] 4803/1: pxa: fix building issue of poodle.c caused by patch 4737/1 [ARM] 4801/1: pxa: fix building issues of missing pxa2xx-regs.h [ARM] pxa: introduce sysdev for pxa3xx static memory controller [ARM] pxa: add preliminary suspend/resume code for pxa3xx [ARM] pxa: introduce sysdev for GPIO register saving/restoring [ARM] pxa: introduce sysdev for IRQ register saving/restoring [ARM] pxa: fix the warning of undeclared "struct pxaohci_platform_data" [ARM] pxa: change set_kset_name() to direct name assignment for MFP sysclass * realview: [ARM] 4822/1: RealView: Change the REALVIEW_MPCORE configuration option [ARM] 4821/1: RealView: Remove the platform dependencies from localtimer.c [ARM] 4820/1: RealView: Select the timer IRQ at run-time [ARM] 4819/1: RealView: Fix entry-macro.S to work with multiple platforms [ARM] 4818/1: RealView: Add core-tile detection [ARM] 4817/1: RealView: Move the AMBA resource definitions to realview_eb.c [ARM] 4816/1: RealView: Move the platform-specific definitions into board-eb.h [ARM] 4815/1: RealView: Add clockevents suport for the local timers [ARM] 4814/1: RealView: Add broadcasting clockevents support for ARM11MPCore [ARM] 4813/1: Add SMP helper functions for clockevents support [ARM] 4812/1: RealView: clockevents support for the RealView platforms [ARM] 4811/1: RealView: clocksource support for the RealView platforms
This commit is contained in:
commit
0d899e1b00
@ -33,6 +33,11 @@ config GENERIC_CLOCKEVENTS
|
||||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_CLOCKEVENTS_BROADCAST
|
||||
bool
|
||||
depends on GENERIC_CLOCKEVENTS
|
||||
default y if SMP && !LOCAL_TIMERS
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
@ -168,6 +173,8 @@ config ARCH_REALVIEW
|
||||
bool "ARM Ltd. RealView family"
|
||||
select ARM_AMBA
|
||||
select ICST307
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
This enables support for ARM Ltd RealView boards.
|
||||
|
||||
@ -604,7 +611,7 @@ source "kernel/time/Kconfig"
|
||||
|
||||
config SMP
|
||||
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && REALVIEW_MPCORE
|
||||
depends on EXPERIMENTAL && REALVIEW_EB_ARM11MP
|
||||
help
|
||||
This enables support for systems with more than one CPU. If you have
|
||||
a system with only one CPU, like most personal computers, say N. If
|
||||
@ -638,7 +645,7 @@ config HOTPLUG_CPU
|
||||
|
||||
config LOCAL_TIMERS
|
||||
bool "Use local timer interrupts"
|
||||
depends on SMP && REALVIEW_MPCORE
|
||||
depends on SMP && REALVIEW_EB_ARM11MP
|
||||
default y
|
||||
help
|
||||
Enable support for local timers on SMP platforms, rather then the
|
||||
@ -894,6 +901,13 @@ config KEXEC
|
||||
initially work for you. It may help to enable device hotplugging
|
||||
support.
|
||||
|
||||
config ATAGS_PROC
|
||||
bool "Export atags in procfs"
|
||||
default n
|
||||
help
|
||||
Should the atags used to boot the kernel be exported in an "atags"
|
||||
file in procfs. Useful with kexec.
|
||||
|
||||
endmenu
|
||||
|
||||
if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA)
|
||||
|
@ -69,9 +69,7 @@ void __init ioctime_init(void)
|
||||
static irqreturn_t
|
||||
ioc_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
timer_tick();
|
||||
write_sequnlock(&xtime_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@ obj-$(CONFIG_PCI) += bios32.o isa.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
|
||||
obj-$(CONFIG_ATAGS_PROC) += atags.o
|
||||
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
|
||||
|
||||
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
||||
|
86
arch/arm/kernel/atags.c
Normal file
86
arch/arm/kernel/atags.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
struct buffer {
|
||||
size_t size;
|
||||
char *data;
|
||||
};
|
||||
static struct buffer tags_buffer;
|
||||
|
||||
static int
|
||||
read_buffer(char* page, char** start, off_t off, int count,
|
||||
int* eof, void* data)
|
||||
{
|
||||
struct buffer *buffer = (struct buffer *)data;
|
||||
|
||||
if (off >= buffer->size) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = min((int) (buffer->size - off), count);
|
||||
|
||||
memcpy(page, &buffer->data[off], count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
create_proc_entries(void)
|
||||
{
|
||||
struct proc_dir_entry* tags_entry;
|
||||
|
||||
tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
|
||||
if (!tags_entry)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
|
||||
static char __initdata *atags_copy;
|
||||
|
||||
void __init save_atags(const struct tag *tags)
|
||||
{
|
||||
atags_copy = atags_copy_buf;
|
||||
memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
|
||||
}
|
||||
|
||||
|
||||
static int __init init_atags_procfs(void)
|
||||
{
|
||||
struct tag *tag;
|
||||
int error;
|
||||
|
||||
if (!atags_copy) {
|
||||
printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
|
||||
;
|
||||
|
||||
tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
|
||||
tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
|
||||
if (tags_buffer.data == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
|
||||
|
||||
error = create_proc_entries();
|
||||
if (error) {
|
||||
printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
|
||||
kfree(tags_buffer.data);
|
||||
tags_buffer.size = 0;
|
||||
tags_buffer.data = NULL;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
arch_initcall(init_atags_procfs);
|
5
arch/arm/kernel/atags.h
Normal file
5
arch/arm/kernel/atags.h
Normal file
@ -0,0 +1,5 @@
|
||||
#ifdef CONFIG_ATAGS_PROC
|
||||
extern void save_atags(struct tag *tags);
|
||||
#else
|
||||
static inline void save_atags(struct tag *tags) { }
|
||||
#endif
|
@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode);
|
||||
extern unsigned long kexec_start_address;
|
||||
extern unsigned long kexec_indirection_page;
|
||||
extern unsigned long kexec_mach_type;
|
||||
extern unsigned long kexec_boot_atags;
|
||||
|
||||
/*
|
||||
* Provide a dummy crash_notes definition while crash dump arrives to arm.
|
||||
@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image)
|
||||
kexec_start_address = image->start;
|
||||
kexec_indirection_page = page_list;
|
||||
kexec_mach_type = machine_arch_type;
|
||||
kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
|
||||
|
||||
/* copy our kernel relocation code to the control code page */
|
||||
memcpy(reboot_code_buffer,
|
||||
|
@ -7,23 +7,6 @@
|
||||
.globl relocate_new_kernel
|
||||
relocate_new_kernel:
|
||||
|
||||
/* Move boot params back to where the kernel expects them */
|
||||
|
||||
ldr r0,kexec_boot_params_address
|
||||
teq r0,#0
|
||||
beq 8f
|
||||
|
||||
ldr r1,kexec_boot_params_copy
|
||||
mov r6,#KEXEC_BOOT_PARAMS_SIZE/4
|
||||
7:
|
||||
ldr r5,[r1],#4
|
||||
str r5,[r0],#4
|
||||
subs r6,r6,#1
|
||||
bne 7b
|
||||
|
||||
8:
|
||||
/* Boot params moved, now go on with the kernel */
|
||||
|
||||
ldr r0,kexec_indirection_page
|
||||
ldr r1,kexec_start_address
|
||||
|
||||
@ -67,7 +50,7 @@ relocate_new_kernel:
|
||||
mov lr,r1
|
||||
mov r0,#0
|
||||
ldr r1,kexec_mach_type
|
||||
ldr r2,kexec_boot_params_address
|
||||
ldr r2,kexec_boot_atags
|
||||
mov pc,lr
|
||||
|
||||
.globl kexec_start_address
|
||||
@ -82,14 +65,9 @@ kexec_indirection_page:
|
||||
kexec_mach_type:
|
||||
.long 0x0
|
||||
|
||||
/* phy addr where new kernel will expect to find boot params */
|
||||
.globl kexec_boot_params_address
|
||||
kexec_boot_params_address:
|
||||
.long 0x0
|
||||
|
||||
/* phy addr where old kernel put a copy of orig boot params */
|
||||
.globl kexec_boot_params_copy
|
||||
kexec_boot_params_copy:
|
||||
/* phy addr of the atags for the new kernel */
|
||||
.globl kexec_boot_atags
|
||||
kexec_boot_atags:
|
||||
.long 0x0
|
||||
|
||||
relocate_new_kernel_end:
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kexec.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/elf.h>
|
||||
@ -39,6 +38,7 @@
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "atags.h"
|
||||
|
||||
#ifndef MEM_SIZE
|
||||
#define MEM_SIZE (16*1024*1024)
|
||||
@ -62,6 +62,7 @@ extern int root_mountflags;
|
||||
extern void _stext, _text, _etext, __data_start, _edata, _end;
|
||||
|
||||
unsigned int processor_id;
|
||||
EXPORT_SYMBOL(processor_id);
|
||||
unsigned int __machine_arch_type;
|
||||
EXPORT_SYMBOL(__machine_arch_type);
|
||||
|
||||
@ -784,23 +785,6 @@ static int __init customize_machine(void)
|
||||
}
|
||||
arch_initcall(customize_machine);
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
|
||||
/* Physical addr of where the boot params should be for this machine */
|
||||
extern unsigned long kexec_boot_params_address;
|
||||
|
||||
/* Physical addr of the buffer into which the boot params are copied */
|
||||
extern unsigned long kexec_boot_params_copy;
|
||||
|
||||
/* Pointer to the boot params buffer, for manipulation and display */
|
||||
unsigned long kexec_boot_params;
|
||||
EXPORT_SYMBOL(kexec_boot_params);
|
||||
|
||||
/* The buffer itself - make sure it is sized correctly */
|
||||
static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
|
||||
|
||||
#endif
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
struct tag *tags = (struct tag *)&init_tags;
|
||||
@ -819,18 +803,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
else if (mdesc->boot_params)
|
||||
tags = phys_to_virt(mdesc->boot_params);
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
|
||||
kexec_boot_params = (unsigned long)kexec_boot_params_buf;
|
||||
if (__atags_pointer) {
|
||||
kexec_boot_params_address = __atags_pointer;
|
||||
memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
|
||||
} else if (mdesc->boot_params) {
|
||||
kexec_boot_params_address = mdesc->boot_params;
|
||||
memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we have the old style parameters, convert them to
|
||||
* a tag list.
|
||||
@ -846,6 +818,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
if (tags->hdr.tag == ATAG_CORE) {
|
||||
if (meminfo.nr_banks != 0)
|
||||
squash_mem_tags(tags);
|
||||
save_atags(tags);
|
||||
parse_tags(tags);
|
||||
}
|
||||
|
||||
|
@ -290,6 +290,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||
local_irq_enable();
|
||||
local_fiq_enable();
|
||||
|
||||
/*
|
||||
* Setup local timer for this CPU.
|
||||
*/
|
||||
local_timer_setup(cpu);
|
||||
|
||||
calibrate_delay();
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
@ -299,11 +304,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||
*/
|
||||
cpu_set(cpu, cpu_online_map);
|
||||
|
||||
/*
|
||||
* Setup local timer for this CPU.
|
||||
*/
|
||||
local_timer_setup(cpu);
|
||||
|
||||
/*
|
||||
* OK, it's off to the idle thread for us
|
||||
*/
|
||||
@ -454,6 +454,27 @@ int smp_call_function(void (*func)(void *info), void *info, int retry,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(smp_call_function);
|
||||
|
||||
int smp_call_function_single(int cpu, void (*func)(void *info), void *info,
|
||||
int retry, int wait)
|
||||
{
|
||||
/* prevent preemption and reschedule on another processor */
|
||||
int current_cpu = get_cpu();
|
||||
int ret = 0;
|
||||
|
||||
if (cpu == current_cpu) {
|
||||
local_irq_disable();
|
||||
func(info);
|
||||
local_irq_enable();
|
||||
} else
|
||||
ret = smp_call_function_on_cpu(func, info, retry, wait,
|
||||
cpumask_of_cpu(cpu));
|
||||
|
||||
put_cpu();
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(smp_call_function_single);
|
||||
|
||||
void show_ipi_list(struct seq_file *p)
|
||||
{
|
||||
unsigned int cpu;
|
||||
@ -481,8 +502,7 @@ void show_local_irqs(struct seq_file *p)
|
||||
static void ipi_timer(void)
|
||||
{
|
||||
irq_enter();
|
||||
profile_tick(CPU_PROFILING);
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
local_timer_interrupt();
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
@ -621,6 +641,11 @@ void smp_send_timer(void)
|
||||
send_ipi_message(mask, IPI_TIMER);
|
||||
}
|
||||
|
||||
void smp_timer_broadcast(cpumask_t mask)
|
||||
{
|
||||
send_ipi_message(mask, IPI_TIMER);
|
||||
}
|
||||
|
||||
void smp_send_stop(void)
|
||||
{
|
||||
cpumask_t mask = cpu_online_map;
|
||||
|
@ -49,8 +49,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
|
||||
volatile long nr_ticks;
|
||||
|
||||
if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
/* Get number to ticks performed before interrupt and clear PIT interrupt */
|
||||
nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
|
||||
do {
|
||||
@ -58,7 +56,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
|
||||
nr_ticks--;
|
||||
} while (nr_ticks);
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
return IRQ_HANDLED;
|
||||
} else
|
||||
return IRQ_NONE; /* not handled */
|
||||
|
@ -189,6 +189,20 @@ config IXP4XX_INDIRECT_PCI
|
||||
need to use the indirect method instead. If you don't know
|
||||
what you need, leave this option unselected.
|
||||
|
||||
config IXP4XX_QMGR
|
||||
tristate "IXP4xx Queue Manager support"
|
||||
help
|
||||
This driver supports IXP4xx built-in hardware queue manager
|
||||
and is automatically selected by Ethernet and HSS drivers.
|
||||
|
||||
config IXP4XX_NPE
|
||||
tristate "IXP4xx Network Processor Engine support"
|
||||
select HOTPLUG
|
||||
select FW_LOADER
|
||||
help
|
||||
This driver supports IXP4xx built-in network coprocessors
|
||||
and is automatically selected by Ethernet and HSS drivers.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
@ -23,10 +23,12 @@ obj-$(CONFIG_MACH_AVILA) += avila-setup.o
|
||||
obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
|
||||
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
|
||||
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
|
||||
obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o
|
||||
obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o
|
||||
obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o
|
||||
obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o
|
||||
obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o
|
||||
obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o
|
||||
obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
|
||||
obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o
|
||||
|
||||
obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o
|
||||
obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o
|
||||
obj-$(CONFIG_IXP4XX_NPE) += ixp4xx_npe.o
|
||||
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-ixp4xx/dsmg600-power.c
|
||||
*
|
||||
* DSM-G600 Power/Reset driver
|
||||
* Author: Michael Westerhof <mwester@dls.net>
|
||||
*
|
||||
* Based on nslu2-power.c
|
||||
* Copyright (C) 2005 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* which was based on nslu2-io.c
|
||||
* Copyright (C) 2004 Karen Spearel
|
||||
*
|
||||
* Maintainers: http://www.nslu2-linux.org/
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
extern void ctrl_alt_del(void);
|
||||
|
||||
/* This is used to make sure the power-button pusher is serious. The button
|
||||
* must be held until the value of this counter reaches zero.
|
||||
*/
|
||||
static volatile int power_button_countdown;
|
||||
|
||||
/* Must hold the button down for at least this many counts to be processed */
|
||||
#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
|
||||
|
||||
static void dsmg600_power_handler(unsigned long data);
|
||||
static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
|
||||
|
||||
static void dsmg600_power_handler(unsigned long data)
|
||||
{
|
||||
/* This routine is called twice per second to check the
|
||||
* state of the power button.
|
||||
*/
|
||||
|
||||
if (*IXP4XX_GPIO_GPINR & DSMG600_PB_BM) {
|
||||
|
||||
/* IO Pin is 1 (button pushed) */
|
||||
if (power_button_countdown == 0) {
|
||||
/* Signal init to do the ctrlaltdel action, this will bypass
|
||||
* init if it hasn't started and do a kernel_restart.
|
||||
*/
|
||||
ctrl_alt_del();
|
||||
|
||||
/* Change the state of the power LED to "blink" */
|
||||
gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
|
||||
}
|
||||
power_button_countdown--;
|
||||
|
||||
} else {
|
||||
power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
|
||||
}
|
||||
|
||||
mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* This is the paper-clip reset, it shuts the machine down directly. */
|
||||
machine_power_off();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init dsmg600_power_init(void)
|
||||
{
|
||||
if (!(machine_is_dsmg600()))
|
||||
return 0;
|
||||
|
||||
if (request_irq(DSMG600_RB_IRQ, &dsmg600_reset_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_LOW, "DSM-G600 reset button",
|
||||
NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
|
||||
DSMG600_RB_IRQ);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* The power button on the D-Link DSM-G600 is on GPIO 15, but
|
||||
* it cannot handle interrupts on that GPIO line. So we'll
|
||||
* have to poll it with a kernel timer.
|
||||
*/
|
||||
|
||||
/* Make sure that the power button GPIO is set up as an input */
|
||||
gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
|
||||
|
||||
/* Set the initial value for the power button IRQ handler */
|
||||
power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
|
||||
|
||||
mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dsmg600_power_exit(void)
|
||||
{
|
||||
if (!(machine_is_dsmg600()))
|
||||
return;
|
||||
|
||||
del_timer_sync(&dsmg600_power_timer);
|
||||
|
||||
free_irq(DSMG600_RB_IRQ, NULL);
|
||||
}
|
||||
|
||||
module_init(dsmg600_power_init);
|
||||
module_exit(dsmg600_power_exit);
|
||||
|
||||
MODULE_AUTHOR("Michael Westerhof <mwester@dls.net>");
|
||||
MODULE_DESCRIPTION("DSM-G600 Power/Reset driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,25 +1,37 @@
|
||||
/*
|
||||
* DSM-G600 board-setup
|
||||
*
|
||||
* Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
|
||||
* Copyright (C) 2006 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* based ixdp425-setup.c:
|
||||
* based on ixdp425-setup.c:
|
||||
* Copyright (C) 2003-2004 MontaVista Software, Inc.
|
||||
* based on nslu2-power.c:
|
||||
* Copyright (C) 2005 Tower Technologies
|
||||
* based on nslu2-io.c:
|
||||
* Copyright (C) 2004 Karen Spearel
|
||||
*
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
* Author: Michael Westerhof <mwester@dls.net>
|
||||
* Author: Rod Whitby <rod@whitby.id.au>
|
||||
* Maintainers: http://www.nslu2-linux.org/
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
static struct flash_platform_data dsmg600_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
@ -51,29 +63,34 @@ static struct platform_device dsmg600_i2c_gpio = {
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LEDS_CLASS
|
||||
static struct resource dsmg600_led_resources[] = {
|
||||
static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
|
||||
{
|
||||
.name = "power",
|
||||
.start = DSMG600_LED_PWR_GPIO,
|
||||
.end = DSMG600_LED_PWR_GPIO,
|
||||
.flags = IXP4XX_GPIO_HIGH,
|
||||
},
|
||||
{
|
||||
.name = "wlan",
|
||||
.start = DSMG600_LED_WLAN_GPIO,
|
||||
.end = DSMG600_LED_WLAN_GPIO,
|
||||
.flags = IXP4XX_GPIO_LOW,
|
||||
I2C_BOARD_INFO("rtc-pcf8563", 0x51),
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device dsmg600_leds = {
|
||||
.name = "IXP4XX-GPIO-LED",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(dsmg600_led_resources),
|
||||
.resource = dsmg600_led_resources,
|
||||
static struct gpio_led dsmg600_led_pins[] = {
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = DSMG600_LED_PWR_GPIO,
|
||||
},
|
||||
{
|
||||
.name = "wlan",
|
||||
.gpio = DSMG600_LED_WLAN_GPIO,
|
||||
.active_low = true,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data dsmg600_led_data = {
|
||||
.num_leds = ARRAY_SIZE(dsmg600_led_pins),
|
||||
.leds = dsmg600_led_pins,
|
||||
};
|
||||
|
||||
static struct platform_device dsmg600_leds = {
|
||||
.name = "leds-gpio",
|
||||
.id = -1,
|
||||
.dev.platform_data = &dsmg600_led_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct resource dsmg600_uart_resources[] = {
|
||||
{
|
||||
@ -121,6 +138,7 @@ static struct platform_device dsmg600_uart = {
|
||||
static struct platform_device *dsmg600_devices[] __initdata = {
|
||||
&dsmg600_i2c_gpio,
|
||||
&dsmg600_flash,
|
||||
&dsmg600_leds,
|
||||
};
|
||||
|
||||
static void dsmg600_power_off(void)
|
||||
@ -132,6 +150,57 @@ static void dsmg600_power_off(void)
|
||||
gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
|
||||
}
|
||||
|
||||
/* This is used to make sure the power-button pusher is serious. The button
|
||||
* must be held until the value of this counter reaches zero.
|
||||
*/
|
||||
static int power_button_countdown;
|
||||
|
||||
/* Must hold the button down for at least this many counts to be processed */
|
||||
#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
|
||||
|
||||
static void dsmg600_power_handler(unsigned long data);
|
||||
static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
|
||||
|
||||
static void dsmg600_power_handler(unsigned long data)
|
||||
{
|
||||
/* This routine is called twice per second to check the
|
||||
* state of the power button.
|
||||
*/
|
||||
|
||||
if (gpio_get_value(DSMG600_PB_GPIO)) {
|
||||
|
||||
/* IO Pin is 1 (button pushed) */
|
||||
if (power_button_countdown > 0)
|
||||
power_button_countdown--;
|
||||
|
||||
} else {
|
||||
|
||||
/* Done on button release, to allow for auto-power-on mods. */
|
||||
if (power_button_countdown == 0) {
|
||||
/* Signal init to do the ctrlaltdel action,
|
||||
* this will bypass init if it hasn't started
|
||||
* and do a kernel_restart.
|
||||
*/
|
||||
ctrl_alt_del();
|
||||
|
||||
/* Change the state of the power LED to "blink" */
|
||||
gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
|
||||
} else {
|
||||
power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* This is the paper-clip reset, it shuts the machine down directly. */
|
||||
machine_power_off();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void __init dsmg600_timer_init(void)
|
||||
{
|
||||
/* The xtal on this machine is non-standard. */
|
||||
@ -156,7 +225,8 @@ static void __init dsmg600_init(void)
|
||||
dsmg600_flash_resource.end =
|
||||
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
|
||||
|
||||
pm_power_off = dsmg600_power_off;
|
||||
i2c_register_board_info(0, dsmg600_i2c_board_info,
|
||||
ARRAY_SIZE(dsmg600_i2c_board_info));
|
||||
|
||||
/* The UART is required on the DSM-G600 (Redboot cannot use the
|
||||
* NIC) -- do it here so that it does *not* get removed if
|
||||
@ -166,10 +236,28 @@ static void __init dsmg600_init(void)
|
||||
|
||||
platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
|
||||
|
||||
#ifdef CONFIG_LEDS_CLASS
|
||||
/* We don't care whether or not this works. */
|
||||
(void)platform_device_register(&dsmg600_leds);
|
||||
#endif
|
||||
pm_power_off = dsmg600_power_off;
|
||||
|
||||
if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_LOW,
|
||||
"DSM-G600 reset button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
|
||||
gpio_to_irq(DSMG600_RB_GPIO));
|
||||
}
|
||||
|
||||
/* The power button on the D-Link DSM-G600 is on GPIO 15, but
|
||||
* it cannot handle interrupts on that GPIO line. So we'll
|
||||
* have to poll it with a kernel timer.
|
||||
*/
|
||||
|
||||
/* Make sure that the power button GPIO is set up as an input */
|
||||
gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
|
||||
|
||||
/* Set the initial value for the power button IRQ handler */
|
||||
power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
|
||||
|
||||
mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
|
||||
|
@ -177,6 +177,31 @@ static struct platform_device ixdp425_uart = {
|
||||
.resource = ixdp425_uart_resources
|
||||
};
|
||||
|
||||
/* Built-in 10/100 Ethernet MAC interfaces */
|
||||
static struct eth_plat_info ixdp425_plat_eth[] = {
|
||||
{
|
||||
.phy = 0,
|
||||
.rxq = 3,
|
||||
.txreadyq = 20,
|
||||
}, {
|
||||
.phy = 1,
|
||||
.rxq = 4,
|
||||
.txreadyq = 21,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device ixdp425_eth[] = {
|
||||
{
|
||||
.name = "ixp4xx_eth",
|
||||
.id = IXP4XX_ETH_NPEB,
|
||||
.dev.platform_data = ixdp425_plat_eth,
|
||||
}, {
|
||||
.name = "ixp4xx_eth",
|
||||
.id = IXP4XX_ETH_NPEC,
|
||||
.dev.platform_data = ixdp425_plat_eth + 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device *ixdp425_devices[] __initdata = {
|
||||
&ixdp425_i2c_gpio,
|
||||
&ixdp425_flash,
|
||||
@ -184,7 +209,9 @@ static struct platform_device *ixdp425_devices[] __initdata = {
|
||||
defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
|
||||
&ixdp425_flash_nand,
|
||||
#endif
|
||||
&ixdp425_uart
|
||||
&ixdp425_uart,
|
||||
&ixdp425_eth[0],
|
||||
&ixdp425_eth[1],
|
||||
};
|
||||
|
||||
static void __init ixdp425_init(void)
|
||||
|
741
arch/arm/mach-ixp4xx/ixp4xx_npe.c
Normal file
741
arch/arm/mach-ixp4xx/ixp4xx_npe.c
Normal file
@ -0,0 +1,741 @@
|
||||
/*
|
||||
* Intel IXP4xx Network Processor Engine driver for Linux
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The code is based on publicly available information:
|
||||
* - Intel IXP4xx Developer's Manual and other e-papers
|
||||
* - Intel IXP400 Access Library Software (BSD license)
|
||||
* - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
|
||||
* Thanks, Christian.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/arch/npe.h>
|
||||
|
||||
#define DEBUG_MSG 0
|
||||
#define DEBUG_FW 0
|
||||
|
||||
#define NPE_COUNT 3
|
||||
#define MAX_RETRIES 1000 /* microseconds */
|
||||
#define NPE_42X_DATA_SIZE 0x800 /* in dwords */
|
||||
#define NPE_46X_DATA_SIZE 0x1000
|
||||
#define NPE_A_42X_INSTR_SIZE 0x1000
|
||||
#define NPE_B_AND_C_42X_INSTR_SIZE 0x800
|
||||
#define NPE_46X_INSTR_SIZE 0x1000
|
||||
#define REGS_SIZE 0x1000
|
||||
|
||||
#define NPE_PHYS_REG 32
|
||||
|
||||
#define FW_MAGIC 0xFEEDF00D
|
||||
#define FW_BLOCK_TYPE_INSTR 0x0
|
||||
#define FW_BLOCK_TYPE_DATA 0x1
|
||||
#define FW_BLOCK_TYPE_EOF 0xF
|
||||
|
||||
/* NPE exec status (read) and command (write) */
|
||||
#define CMD_NPE_STEP 0x01
|
||||
#define CMD_NPE_START 0x02
|
||||
#define CMD_NPE_STOP 0x03
|
||||
#define CMD_NPE_CLR_PIPE 0x04
|
||||
#define CMD_CLR_PROFILE_CNT 0x0C
|
||||
#define CMD_RD_INS_MEM 0x10 /* instruction memory */
|
||||
#define CMD_WR_INS_MEM 0x11
|
||||
#define CMD_RD_DATA_MEM 0x12 /* data memory */
|
||||
#define CMD_WR_DATA_MEM 0x13
|
||||
#define CMD_RD_ECS_REG 0x14 /* exec access register */
|
||||
#define CMD_WR_ECS_REG 0x15
|
||||
|
||||
#define STAT_RUN 0x80000000
|
||||
#define STAT_STOP 0x40000000
|
||||
#define STAT_CLEAR 0x20000000
|
||||
#define STAT_ECS_K 0x00800000 /* pipeline clean */
|
||||
|
||||
#define NPE_STEVT 0x1B
|
||||
#define NPE_STARTPC 0x1C
|
||||
#define NPE_REGMAP 0x1E
|
||||
#define NPE_CINDEX 0x1F
|
||||
|
||||
#define INSTR_WR_REG_SHORT 0x0000C000
|
||||
#define INSTR_WR_REG_BYTE 0x00004000
|
||||
#define INSTR_RD_FIFO 0x0F888220
|
||||
#define INSTR_RESET_MBOX 0x0FAC8210
|
||||
|
||||
#define ECS_BG_CTXT_REG_0 0x00 /* Background Executing Context */
|
||||
#define ECS_BG_CTXT_REG_1 0x01 /* Stack level */
|
||||
#define ECS_BG_CTXT_REG_2 0x02
|
||||
#define ECS_PRI_1_CTXT_REG_0 0x04 /* Priority 1 Executing Context */
|
||||
#define ECS_PRI_1_CTXT_REG_1 0x05 /* Stack level */
|
||||
#define ECS_PRI_1_CTXT_REG_2 0x06
|
||||
#define ECS_PRI_2_CTXT_REG_0 0x08 /* Priority 2 Executing Context */
|
||||
#define ECS_PRI_2_CTXT_REG_1 0x09 /* Stack level */
|
||||
#define ECS_PRI_2_CTXT_REG_2 0x0A
|
||||
#define ECS_DBG_CTXT_REG_0 0x0C /* Debug Executing Context */
|
||||
#define ECS_DBG_CTXT_REG_1 0x0D /* Stack level */
|
||||
#define ECS_DBG_CTXT_REG_2 0x0E
|
||||
#define ECS_INSTRUCT_REG 0x11 /* NPE Instruction Register */
|
||||
|
||||
#define ECS_REG_0_ACTIVE 0x80000000 /* all levels */
|
||||
#define ECS_REG_0_NEXTPC_MASK 0x1FFF0000 /* BG/PRI1/PRI2 levels */
|
||||
#define ECS_REG_0_LDUR_BITS 8
|
||||
#define ECS_REG_0_LDUR_MASK 0x00000700 /* all levels */
|
||||
#define ECS_REG_1_CCTXT_BITS 16
|
||||
#define ECS_REG_1_CCTXT_MASK 0x000F0000 /* all levels */
|
||||
#define ECS_REG_1_SELCTXT_BITS 0
|
||||
#define ECS_REG_1_SELCTXT_MASK 0x0000000F /* all levels */
|
||||
#define ECS_DBG_REG_2_IF 0x00100000 /* debug level */
|
||||
#define ECS_DBG_REG_2_IE 0x00080000 /* debug level */
|
||||
|
||||
/* NPE watchpoint_fifo register bit */
|
||||
#define WFIFO_VALID 0x80000000
|
||||
|
||||
/* NPE messaging_status register bit definitions */
|
||||
#define MSGSTAT_OFNE 0x00010000 /* OutFifoNotEmpty */
|
||||
#define MSGSTAT_IFNF 0x00020000 /* InFifoNotFull */
|
||||
#define MSGSTAT_OFNF 0x00040000 /* OutFifoNotFull */
|
||||
#define MSGSTAT_IFNE 0x00080000 /* InFifoNotEmpty */
|
||||
#define MSGSTAT_MBINT 0x00100000 /* Mailbox interrupt */
|
||||
#define MSGSTAT_IFINT 0x00200000 /* InFifo interrupt */
|
||||
#define MSGSTAT_OFINT 0x00400000 /* OutFifo interrupt */
|
||||
#define MSGSTAT_WFINT 0x00800000 /* WatchFifo interrupt */
|
||||
|
||||
/* NPE messaging_control register bit definitions */
|
||||
#define MSGCTL_OUT_FIFO 0x00010000 /* enable output FIFO */
|
||||
#define MSGCTL_IN_FIFO 0x00020000 /* enable input FIFO */
|
||||
#define MSGCTL_OUT_FIFO_WRITE 0x01000000 /* enable FIFO + WRITE */
|
||||
#define MSGCTL_IN_FIFO_WRITE 0x02000000
|
||||
|
||||
/* NPE mailbox_status value for reset */
|
||||
#define RESET_MBOX_STAT 0x0000F0F0
|
||||
|
||||
const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
|
||||
|
||||
#define print_npe(pri, npe, fmt, ...) \
|
||||
printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
|
||||
|
||||
#if DEBUG_MSG
|
||||
#define debug_msg(npe, fmt, ...) \
|
||||
print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define debug_msg(npe, fmt, ...)
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
u32 reg, val;
|
||||
} ecs_reset[] = {
|
||||
{ ECS_BG_CTXT_REG_0, 0xA0000000 },
|
||||
{ ECS_BG_CTXT_REG_1, 0x01000000 },
|
||||
{ ECS_BG_CTXT_REG_2, 0x00008000 },
|
||||
{ ECS_PRI_1_CTXT_REG_0, 0x20000080 },
|
||||
{ ECS_PRI_1_CTXT_REG_1, 0x01000000 },
|
||||
{ ECS_PRI_1_CTXT_REG_2, 0x00008000 },
|
||||
{ ECS_PRI_2_CTXT_REG_0, 0x20000080 },
|
||||
{ ECS_PRI_2_CTXT_REG_1, 0x01000000 },
|
||||
{ ECS_PRI_2_CTXT_REG_2, 0x00008000 },
|
||||
{ ECS_DBG_CTXT_REG_0, 0x20000000 },
|
||||
{ ECS_DBG_CTXT_REG_1, 0x00000000 },
|
||||
{ ECS_DBG_CTXT_REG_2, 0x001E0000 },
|
||||
{ ECS_INSTRUCT_REG, 0x1003C00F },
|
||||
};
|
||||
|
||||
static struct npe npe_tab[NPE_COUNT] = {
|
||||
{
|
||||
.id = 0,
|
||||
.regs = (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT,
|
||||
.regs_phys = IXP4XX_NPEA_BASE_PHYS,
|
||||
}, {
|
||||
.id = 1,
|
||||
.regs = (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT,
|
||||
.regs_phys = IXP4XX_NPEB_BASE_PHYS,
|
||||
}, {
|
||||
.id = 2,
|
||||
.regs = (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT,
|
||||
.regs_phys = IXP4XX_NPEC_BASE_PHYS,
|
||||
}
|
||||
};
|
||||
|
||||
int npe_running(struct npe *npe)
|
||||
{
|
||||
return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
|
||||
}
|
||||
|
||||
static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
|
||||
{
|
||||
__raw_writel(data, &npe->regs->exec_data);
|
||||
__raw_writel(addr, &npe->regs->exec_addr);
|
||||
__raw_writel(cmd, &npe->regs->exec_status_cmd);
|
||||
}
|
||||
|
||||
static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
|
||||
{
|
||||
__raw_writel(addr, &npe->regs->exec_addr);
|
||||
__raw_writel(cmd, &npe->regs->exec_status_cmd);
|
||||
/* Iintroduce extra read cycles after issuing read command to NPE
|
||||
so that we read the register after the NPE has updated it.
|
||||
This is to overcome race condition between XScale and NPE */
|
||||
__raw_readl(&npe->regs->exec_data);
|
||||
__raw_readl(&npe->regs->exec_data);
|
||||
return __raw_readl(&npe->regs->exec_data);
|
||||
}
|
||||
|
||||
static void npe_clear_active(struct npe *npe, u32 reg)
|
||||
{
|
||||
u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
|
||||
npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
|
||||
}
|
||||
|
||||
static void npe_start(struct npe *npe)
|
||||
{
|
||||
/* ensure only Background Context Stack Level is active */
|
||||
npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
|
||||
npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
|
||||
npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
|
||||
|
||||
__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
|
||||
__raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
|
||||
}
|
||||
|
||||
static void npe_stop(struct npe *npe)
|
||||
{
|
||||
__raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
|
||||
__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
|
||||
}
|
||||
|
||||
static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
|
||||
u32 ldur)
|
||||
{
|
||||
u32 wc;
|
||||
int i;
|
||||
|
||||
/* set the Active bit, and the LDUR, in the debug level */
|
||||
npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
|
||||
ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
|
||||
|
||||
/* set CCTXT at ECS DEBUG L3 to specify in which context to execute
|
||||
the instruction, and set SELCTXT at ECS DEBUG Level to specify
|
||||
which context store to access.
|
||||
Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
|
||||
*/
|
||||
npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
|
||||
(ctx << ECS_REG_1_CCTXT_BITS) |
|
||||
(ctx << ECS_REG_1_SELCTXT_BITS));
|
||||
|
||||
/* clear the pipeline */
|
||||
__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
|
||||
|
||||
/* load NPE instruction into the instruction register */
|
||||
npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
|
||||
|
||||
/* we need this value later to wait for completion of NPE execution
|
||||
step */
|
||||
wc = __raw_readl(&npe->regs->watch_count);
|
||||
|
||||
/* issue a Step One command via the Execution Control register */
|
||||
__raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
|
||||
|
||||
/* Watch Count register increments when NPE completes an instruction */
|
||||
for (i = 0; i < MAX_RETRIES; i++) {
|
||||
if (wc != __raw_readl(&npe->regs->watch_count))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
|
||||
u8 val, u32 ctx)
|
||||
{
|
||||
/* here we build the NPE assembler instruction: mov8 d0, #0 */
|
||||
u32 instr = INSTR_WR_REG_BYTE | /* OpCode */
|
||||
addr << 9 | /* base Operand */
|
||||
(val & 0x1F) << 4 | /* lower 5 bits to immediate data */
|
||||
(val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
|
||||
return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
|
||||
}
|
||||
|
||||
static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
|
||||
u16 val, u32 ctx)
|
||||
{
|
||||
/* here we build the NPE assembler instruction: mov16 d0, #0 */
|
||||
u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
|
||||
addr << 9 | /* base Operand */
|
||||
(val & 0x1F) << 4 | /* lower 5 bits to immediate data */
|
||||
(val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
|
||||
return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
|
||||
}
|
||||
|
||||
static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
|
||||
u32 val, u32 ctx)
|
||||
{
|
||||
/* write in 16 bit steps first the high and then the low value */
|
||||
if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
|
||||
return -ETIMEDOUT;
|
||||
return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
|
||||
}
|
||||
|
||||
static int npe_reset(struct npe *npe)
|
||||
{
|
||||
u32 val, ctl, exec_count, ctx_reg2;
|
||||
int i;
|
||||
|
||||
ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
|
||||
0x3F3FFFFF;
|
||||
|
||||
/* disable parity interrupt */
|
||||
__raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
|
||||
|
||||
/* pre exec - debug instruction */
|
||||
/* turn off the halt bit by clearing Execution Count register. */
|
||||
exec_count = __raw_readl(&npe->regs->exec_count);
|
||||
__raw_writel(0, &npe->regs->exec_count);
|
||||
/* ensure that IF and IE are on (temporarily), so that we don't end up
|
||||
stepping forever */
|
||||
ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
|
||||
npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
|
||||
ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
|
||||
|
||||
/* clear the FIFOs */
|
||||
while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
|
||||
;
|
||||
while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
|
||||
/* read from the outFIFO until empty */
|
||||
print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
|
||||
__raw_readl(&npe->regs->in_out_fifo));
|
||||
|
||||
while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
|
||||
/* step execution of the NPE intruction to read inFIFO using
|
||||
the Debug Executing Context stack */
|
||||
if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* reset the mailbox reg from the XScale side */
|
||||
__raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
|
||||
/* from NPE side */
|
||||
if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* Reset the physical registers in the NPE register file */
|
||||
for (val = 0; val < NPE_PHYS_REG; val++) {
|
||||
if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
|
||||
return -ETIMEDOUT;
|
||||
/* address is either 0 or 4 */
|
||||
if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Reset the context store = each context's Context Store registers */
|
||||
|
||||
/* Context 0 has no STARTPC. Instead, this value is used to set NextPC
|
||||
for Background ECS, to set where NPE starts executing code */
|
||||
val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
|
||||
val &= ~ECS_REG_0_NEXTPC_MASK;
|
||||
val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
|
||||
npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i) { /* Context 0 has no STEVT nor STARTPC */
|
||||
/* STEVT = off, 0x80 */
|
||||
if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
|
||||
return -ETIMEDOUT;
|
||||
if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
/* REGMAP = d0->p0, d8->p2, d16->p4 */
|
||||
if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
|
||||
return -ETIMEDOUT;
|
||||
if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* post exec */
|
||||
/* clear active bit in debug level */
|
||||
npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
|
||||
/* clear the pipeline */
|
||||
__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
|
||||
/* restore previous values */
|
||||
__raw_writel(exec_count, &npe->regs->exec_count);
|
||||
npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
|
||||
|
||||
/* write reset values to Execution Context Stack registers */
|
||||
for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
|
||||
npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
|
||||
ecs_reset[val].val);
|
||||
|
||||
/* clear the profile counter */
|
||||
__raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
|
||||
|
||||
__raw_writel(0, &npe->regs->exec_count);
|
||||
__raw_writel(0, &npe->regs->action_points[0]);
|
||||
__raw_writel(0, &npe->regs->action_points[1]);
|
||||
__raw_writel(0, &npe->regs->action_points[2]);
|
||||
__raw_writel(0, &npe->regs->action_points[3]);
|
||||
__raw_writel(0, &npe->regs->watch_count);
|
||||
|
||||
val = ixp4xx_read_feature_bits();
|
||||
/* reset the NPE */
|
||||
ixp4xx_write_feature_bits(val &
|
||||
~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
|
||||
for (i = 0; i < MAX_RETRIES; i++) {
|
||||
if (!(ixp4xx_read_feature_bits() &
|
||||
(IXP4XX_FEATURE_RESET_NPEA << npe->id)))
|
||||
break; /* reset completed */
|
||||
udelay(1);
|
||||
}
|
||||
if (i == MAX_RETRIES)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* deassert reset */
|
||||
ixp4xx_write_feature_bits(val |
|
||||
(IXP4XX_FEATURE_RESET_NPEA << npe->id));
|
||||
for (i = 0; i < MAX_RETRIES; i++) {
|
||||
if (ixp4xx_read_feature_bits() &
|
||||
(IXP4XX_FEATURE_RESET_NPEA << npe->id))
|
||||
break; /* NPE is back alive */
|
||||
udelay(1);
|
||||
}
|
||||
if (i == MAX_RETRIES)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
npe_stop(npe);
|
||||
|
||||
/* restore NPE configuration bus Control Register - parity settings */
|
||||
__raw_writel(ctl, &npe->regs->messaging_control);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int npe_send_message(struct npe *npe, const void *msg, const char *what)
|
||||
{
|
||||
const u32 *send = msg;
|
||||
int cycles = 0;
|
||||
|
||||
debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
|
||||
what, send[0], send[1]);
|
||||
|
||||
if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
|
||||
debug_msg(npe, "NPE input FIFO not empty\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
__raw_writel(send[0], &npe->regs->in_out_fifo);
|
||||
|
||||
if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
|
||||
debug_msg(npe, "NPE input FIFO full\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
__raw_writel(send[1], &npe->regs->in_out_fifo);
|
||||
|
||||
while ((cycles < MAX_RETRIES) &&
|
||||
(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
|
||||
udelay(1);
|
||||
cycles++;
|
||||
}
|
||||
|
||||
if (cycles == MAX_RETRIES) {
|
||||
debug_msg(npe, "Timeout sending message\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
debug_msg(npe, "Sending a message took %i cycles\n", cycles);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int npe_recv_message(struct npe *npe, void *msg, const char *what)
|
||||
{
|
||||
u32 *recv = msg;
|
||||
int cycles = 0, cnt = 0;
|
||||
|
||||
debug_msg(npe, "Trying to receive message %s\n", what);
|
||||
|
||||
while (cycles < MAX_RETRIES) {
|
||||
if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
|
||||
recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
|
||||
if (cnt == 2)
|
||||
break;
|
||||
} else {
|
||||
udelay(1);
|
||||
cycles++;
|
||||
}
|
||||
}
|
||||
|
||||
switch(cnt) {
|
||||
case 1:
|
||||
debug_msg(npe, "Received [%08X]\n", recv[0]);
|
||||
break;
|
||||
case 2:
|
||||
debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cycles == MAX_RETRIES) {
|
||||
debug_msg(npe, "Timeout waiting for message\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
|
||||
{
|
||||
int result;
|
||||
u32 *send = msg, recv[2];
|
||||
|
||||
if ((result = npe_send_message(npe, msg, what)) != 0)
|
||||
return result;
|
||||
if ((result = npe_recv_message(npe, recv, what)) != 0)
|
||||
return result;
|
||||
|
||||
if ((recv[0] != send[0]) || (recv[1] != send[1])) {
|
||||
debug_msg(npe, "Message %s: unexpected message received\n",
|
||||
what);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
|
||||
{
|
||||
const struct firmware *fw_entry;
|
||||
|
||||
struct dl_block {
|
||||
u32 type;
|
||||
u32 offset;
|
||||
} *blk;
|
||||
|
||||
struct dl_image {
|
||||
u32 magic;
|
||||
u32 id;
|
||||
u32 size;
|
||||
union {
|
||||
u32 data[0];
|
||||
struct dl_block blocks[0];
|
||||
};
|
||||
} *image;
|
||||
|
||||
struct dl_codeblock {
|
||||
u32 npe_addr;
|
||||
u32 size;
|
||||
u32 data[0];
|
||||
} *cb;
|
||||
|
||||
int i, j, err, data_size, instr_size, blocks, table_end;
|
||||
u32 cmd;
|
||||
|
||||
if ((err = request_firmware(&fw_entry, name, dev)) != 0)
|
||||
return err;
|
||||
|
||||
err = -EINVAL;
|
||||
if (fw_entry->size < sizeof(struct dl_image)) {
|
||||
print_npe(KERN_ERR, npe, "incomplete firmware file\n");
|
||||
goto err;
|
||||
}
|
||||
image = (struct dl_image*)fw_entry->data;
|
||||
|
||||
#if DEBUG_FW
|
||||
print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
|
||||
image->magic, image->id, image->size, image->size * 4);
|
||||
#endif
|
||||
|
||||
if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
|
||||
image->id = swab32(image->id);
|
||||
image->size = swab32(image->size);
|
||||
} else if (image->magic != FW_MAGIC) {
|
||||
print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
|
||||
image->magic);
|
||||
goto err;
|
||||
}
|
||||
if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
|
||||
print_npe(KERN_ERR, npe,
|
||||
"inconsistent size of firmware file\n");
|
||||
goto err;
|
||||
}
|
||||
if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
|
||||
print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
|
||||
goto err;
|
||||
}
|
||||
if (image->magic == swab32(FW_MAGIC))
|
||||
for (i = 0; i < image->size; i++)
|
||||
image->data[i] = swab32(image->data[i]);
|
||||
|
||||
if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) {
|
||||
print_npe(KERN_INFO, npe, "IXP46x firmware ignored on "
|
||||
"IXP42x\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (npe_running(npe)) {
|
||||
print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
|
||||
"already running\n");
|
||||
err = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
#if 0
|
||||
npe_stop(npe);
|
||||
npe_reset(npe);
|
||||
#endif
|
||||
|
||||
print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
|
||||
"revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
|
||||
(image->id >> 8) & 0xFF, image->id & 0xFF);
|
||||
|
||||
if (!cpu_is_ixp46x()) {
|
||||
if (!npe->id)
|
||||
instr_size = NPE_A_42X_INSTR_SIZE;
|
||||
else
|
||||
instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
|
||||
data_size = NPE_42X_DATA_SIZE;
|
||||
} else {
|
||||
instr_size = NPE_46X_INSTR_SIZE;
|
||||
data_size = NPE_46X_DATA_SIZE;
|
||||
}
|
||||
|
||||
for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
|
||||
blocks++)
|
||||
if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
|
||||
break;
|
||||
if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
|
||||
print_npe(KERN_INFO, npe, "firmware EOF block marker not "
|
||||
"found\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
#if DEBUG_FW
|
||||
print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
|
||||
#endif
|
||||
|
||||
table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
|
||||
for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
|
||||
if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
|
||||
|| blk->offset < table_end) {
|
||||
print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
|
||||
"firmware block #%i\n", blk->offset, i);
|
||||
goto err;
|
||||
}
|
||||
|
||||
cb = (struct dl_codeblock*)&image->data[blk->offset];
|
||||
if (blk->type == FW_BLOCK_TYPE_INSTR) {
|
||||
if (cb->npe_addr + cb->size > instr_size)
|
||||
goto too_big;
|
||||
cmd = CMD_WR_INS_MEM;
|
||||
} else if (blk->type == FW_BLOCK_TYPE_DATA) {
|
||||
if (cb->npe_addr + cb->size > data_size)
|
||||
goto too_big;
|
||||
cmd = CMD_WR_DATA_MEM;
|
||||
} else {
|
||||
print_npe(KERN_INFO, npe, "invalid firmware block #%i "
|
||||
"type 0x%X\n", i, blk->type);
|
||||
goto err;
|
||||
}
|
||||
if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
|
||||
print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
|
||||
"fit in firmware image: type %c, start 0x%X,"
|
||||
" length 0x%X\n", i,
|
||||
blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
|
||||
cb->npe_addr, cb->size);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (j = 0; j < cb->size; j++)
|
||||
npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
|
||||
}
|
||||
|
||||
npe_start(npe);
|
||||
if (!npe_running(npe))
|
||||
print_npe(KERN_ERR, npe, "unable to start\n");
|
||||
release_firmware(fw_entry);
|
||||
return 0;
|
||||
|
||||
too_big:
|
||||
print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
|
||||
"memory: type %c, start 0x%X, length 0x%X\n", i,
|
||||
blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
|
||||
cb->npe_addr, cb->size);
|
||||
err:
|
||||
release_firmware(fw_entry);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
struct npe *npe_request(int id)
|
||||
{
|
||||
if (id < NPE_COUNT)
|
||||
if (npe_tab[id].valid)
|
||||
if (try_module_get(THIS_MODULE))
|
||||
return &npe_tab[id];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void npe_release(struct npe *npe)
|
||||
{
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
|
||||
static int __init npe_init_module(void)
|
||||
{
|
||||
|
||||
int i, found = 0;
|
||||
|
||||
for (i = 0; i < NPE_COUNT; i++) {
|
||||
struct npe *npe = &npe_tab[i];
|
||||
if (!(ixp4xx_read_feature_bits() &
|
||||
(IXP4XX_FEATURE_RESET_NPEA << i)))
|
||||
continue; /* NPE already disabled or not present */
|
||||
if (!(npe->mem_res = request_mem_region(npe->regs_phys,
|
||||
REGS_SIZE,
|
||||
npe_name(npe)))) {
|
||||
print_npe(KERN_ERR, npe,
|
||||
"failed to request memory region\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (npe_reset(npe))
|
||||
continue;
|
||||
npe->valid = 1;
|
||||
found++;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit npe_cleanup_module(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NPE_COUNT; i++)
|
||||
if (npe_tab[i].mem_res) {
|
||||
npe_reset(&npe_tab[i]);
|
||||
release_resource(npe_tab[i].mem_res);
|
||||
}
|
||||
}
|
||||
|
||||
module_init(npe_init_module);
|
||||
module_exit(npe_cleanup_module);
|
||||
|
||||
MODULE_AUTHOR("Krzysztof Halasa");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
EXPORT_SYMBOL(npe_names);
|
||||
EXPORT_SYMBOL(npe_running);
|
||||
EXPORT_SYMBOL(npe_request);
|
||||
EXPORT_SYMBOL(npe_release);
|
||||
EXPORT_SYMBOL(npe_load_firmware);
|
||||
EXPORT_SYMBOL(npe_send_message);
|
||||
EXPORT_SYMBOL(npe_recv_message);
|
||||
EXPORT_SYMBOL(npe_send_recv_message);
|
274
arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
Normal file
274
arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Intel IXP4xx Queue Manager driver for Linux
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/arch/qmgr.h>
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
struct qmgr_regs __iomem *qmgr_regs;
|
||||
static struct resource *mem_res;
|
||||
static spinlock_t qmgr_lock;
|
||||
static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
|
||||
static void (*irq_handlers[HALF_QUEUES])(void *pdev);
|
||||
static void *irq_pdevs[HALF_QUEUES];
|
||||
|
||||
void qmgr_set_irq(unsigned int queue, int src,
|
||||
void (*handler)(void *pdev), void *pdev)
|
||||
{
|
||||
u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
|
||||
int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
|
||||
unsigned long flags;
|
||||
|
||||
src &= 7;
|
||||
spin_lock_irqsave(&qmgr_lock, flags);
|
||||
__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
|
||||
irq_handlers[queue] = handler;
|
||||
irq_pdevs[queue] = pdev;
|
||||
spin_unlock_irqrestore(&qmgr_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t qmgr_irq1(int irq, void *pdev)
|
||||
{
|
||||
int i;
|
||||
u32 val = __raw_readl(&qmgr_regs->irqstat[0]);
|
||||
__raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */
|
||||
|
||||
for (i = 0; i < HALF_QUEUES; i++)
|
||||
if (val & (1 << i))
|
||||
irq_handlers[i](irq_pdevs[i]);
|
||||
|
||||
return val ? IRQ_HANDLED : 0;
|
||||
}
|
||||
|
||||
|
||||
void qmgr_enable_irq(unsigned int queue)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qmgr_lock, flags);
|
||||
__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue),
|
||||
&qmgr_regs->irqen[0]);
|
||||
spin_unlock_irqrestore(&qmgr_lock, flags);
|
||||
}
|
||||
|
||||
void qmgr_disable_irq(unsigned int queue)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qmgr_lock, flags);
|
||||
__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue),
|
||||
&qmgr_regs->irqen[0]);
|
||||
spin_unlock_irqrestore(&qmgr_lock, flags);
|
||||
}
|
||||
|
||||
static inline void shift_mask(u32 *mask)
|
||||
{
|
||||
mask[3] = mask[3] << 1 | mask[2] >> 31;
|
||||
mask[2] = mask[2] << 1 | mask[1] >> 31;
|
||||
mask[1] = mask[1] << 1 | mask[0] >> 31;
|
||||
mask[0] <<= 1;
|
||||
}
|
||||
|
||||
int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
|
||||
unsigned int nearly_empty_watermark,
|
||||
unsigned int nearly_full_watermark)
|
||||
{
|
||||
u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
|
||||
int err;
|
||||
|
||||
if (queue >= HALF_QUEUES)
|
||||
return -ERANGE;
|
||||
|
||||
if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
|
||||
return -EINVAL;
|
||||
|
||||
switch (len) {
|
||||
case 16:
|
||||
cfg = 0 << 24;
|
||||
mask[0] = 0x1;
|
||||
break;
|
||||
case 32:
|
||||
cfg = 1 << 24;
|
||||
mask[0] = 0x3;
|
||||
break;
|
||||
case 64:
|
||||
cfg = 2 << 24;
|
||||
mask[0] = 0xF;
|
||||
break;
|
||||
case 128:
|
||||
cfg = 3 << 24;
|
||||
mask[0] = 0xFF;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg |= nearly_empty_watermark << 26;
|
||||
cfg |= nearly_full_watermark << 29;
|
||||
len /= 16; /* in 16-dwords: 1, 2, 4 or 8 */
|
||||
mask[1] = mask[2] = mask[3] = 0;
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irq(&qmgr_lock);
|
||||
if (__raw_readl(&qmgr_regs->sram[queue])) {
|
||||
err = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!(used_sram_bitmap[0] & mask[0]) &&
|
||||
!(used_sram_bitmap[1] & mask[1]) &&
|
||||
!(used_sram_bitmap[2] & mask[2]) &&
|
||||
!(used_sram_bitmap[3] & mask[3]))
|
||||
break; /* found free space */
|
||||
|
||||
addr++;
|
||||
shift_mask(mask);
|
||||
if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
|
||||
printk(KERN_ERR "qmgr: no free SRAM space for"
|
||||
" queue %i\n", queue);
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
used_sram_bitmap[0] |= mask[0];
|
||||
used_sram_bitmap[1] |= mask[1];
|
||||
used_sram_bitmap[2] |= mask[2];
|
||||
used_sram_bitmap[3] |= mask[3];
|
||||
__raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
|
||||
spin_unlock_irq(&qmgr_lock);
|
||||
|
||||
#if DEBUG
|
||||
printk(KERN_DEBUG "qmgr: requested queue %i, addr = 0x%02X\n",
|
||||
queue, addr);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
err:
|
||||
spin_unlock_irq(&qmgr_lock);
|
||||
module_put(THIS_MODULE);
|
||||
return err;
|
||||
}
|
||||
|
||||
void qmgr_release_queue(unsigned int queue)
|
||||
{
|
||||
u32 cfg, addr, mask[4];
|
||||
|
||||
BUG_ON(queue >= HALF_QUEUES); /* not in valid range */
|
||||
|
||||
spin_lock_irq(&qmgr_lock);
|
||||
cfg = __raw_readl(&qmgr_regs->sram[queue]);
|
||||
addr = (cfg >> 14) & 0xFF;
|
||||
|
||||
BUG_ON(!addr); /* not requested */
|
||||
|
||||
switch ((cfg >> 24) & 3) {
|
||||
case 0: mask[0] = 0x1; break;
|
||||
case 1: mask[0] = 0x3; break;
|
||||
case 2: mask[0] = 0xF; break;
|
||||
case 3: mask[0] = 0xFF; break;
|
||||
}
|
||||
|
||||
while (addr--)
|
||||
shift_mask(mask);
|
||||
|
||||
__raw_writel(0, &qmgr_regs->sram[queue]);
|
||||
|
||||
used_sram_bitmap[0] &= ~mask[0];
|
||||
used_sram_bitmap[1] &= ~mask[1];
|
||||
used_sram_bitmap[2] &= ~mask[2];
|
||||
used_sram_bitmap[3] &= ~mask[3];
|
||||
irq_handlers[queue] = NULL; /* catch IRQ bugs */
|
||||
spin_unlock_irq(&qmgr_lock);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
#if DEBUG
|
||||
printk(KERN_DEBUG "qmgr: released queue %i\n", queue);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int qmgr_init(void)
|
||||
{
|
||||
int i, err;
|
||||
mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
|
||||
IXP4XX_QMGR_REGION_SIZE,
|
||||
"IXP4xx Queue Manager");
|
||||
if (mem_res == NULL)
|
||||
return -EBUSY;
|
||||
|
||||
qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
|
||||
if (qmgr_regs == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto error_map;
|
||||
}
|
||||
|
||||
/* reset qmgr registers */
|
||||
for (i = 0; i < 4; i++) {
|
||||
__raw_writel(0x33333333, &qmgr_regs->stat1[i]);
|
||||
__raw_writel(0, &qmgr_regs->irqsrc[i]);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
__raw_writel(0, &qmgr_regs->stat2[i]);
|
||||
__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
|
||||
__raw_writel(0, &qmgr_regs->irqen[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < QUEUES; i++)
|
||||
__raw_writel(0, &qmgr_regs->sram[i]);
|
||||
|
||||
err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0,
|
||||
"IXP4xx Queue Manager", NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
|
||||
IRQ_IXP4XX_QM1);
|
||||
goto error_irq;
|
||||
}
|
||||
|
||||
used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
|
||||
spin_lock_init(&qmgr_lock);
|
||||
|
||||
printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
|
||||
return 0;
|
||||
|
||||
error_irq:
|
||||
iounmap(qmgr_regs);
|
||||
error_map:
|
||||
release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void qmgr_remove(void)
|
||||
{
|
||||
free_irq(IRQ_IXP4XX_QM1, NULL);
|
||||
synchronize_irq(IRQ_IXP4XX_QM1);
|
||||
iounmap(qmgr_regs);
|
||||
release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
|
||||
}
|
||||
|
||||
module_init(qmgr_init);
|
||||
module_exit(qmgr_remove);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Krzysztof Halasa");
|
||||
|
||||
EXPORT_SYMBOL(qmgr_regs);
|
||||
EXPORT_SYMBOL(qmgr_set_irq);
|
||||
EXPORT_SYMBOL(qmgr_enable_irq);
|
||||
EXPORT_SYMBOL(qmgr_disable_irq);
|
||||
EXPORT_SYMBOL(qmgr_request_queue);
|
||||
EXPORT_SYMBOL(qmgr_release_queue);
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-ixp4xx/nas100d-power.c
|
||||
*
|
||||
* NAS 100d Power/Reset driver
|
||||
*
|
||||
* Copyright (C) 2005 Tower Technologies
|
||||
*
|
||||
* based on nas100d-io.c
|
||||
* Copyright (C) 2004 Karen Spearel
|
||||
*
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
* Maintainers: http://www.nslu2-linux.org/
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* Signal init to do the ctrlaltdel action, this will bypass init if
|
||||
* it hasn't started and do a kernel_restart.
|
||||
*/
|
||||
ctrl_alt_del();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init nas100d_power_init(void)
|
||||
{
|
||||
if (!(machine_is_nas100d()))
|
||||
return 0;
|
||||
|
||||
set_irq_type(NAS100D_RB_IRQ, IRQT_LOW);
|
||||
|
||||
if (request_irq(NAS100D_RB_IRQ, &nas100d_reset_handler,
|
||||
IRQF_DISABLED, "NAS100D reset button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
|
||||
NAS100D_RB_IRQ);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit nas100d_power_exit(void)
|
||||
{
|
||||
if (!(machine_is_nas100d()))
|
||||
return;
|
||||
|
||||
free_irq(NAS100D_RB_IRQ, NULL);
|
||||
}
|
||||
|
||||
module_init(nas100d_power_init);
|
||||
module_exit(nas100d_power_exit);
|
||||
|
||||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
||||
MODULE_DESCRIPTION("NAS100D Power/Reset driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -3,8 +3,14 @@
|
||||
*
|
||||
* NAS 100d board-setup
|
||||
*
|
||||
* based ixdp425-setup.c:
|
||||
* Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
|
||||
*
|
||||
* based on ixdp425-setup.c:
|
||||
* Copyright (C) 2003-2004 MontaVista Software, Inc.
|
||||
* based on nas100d-power.c:
|
||||
* Copyright (C) 2005 Tower Technologies
|
||||
* based on nas100d-io.c
|
||||
* Copyright (C) 2004 Karen Spearel
|
||||
*
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
* Author: Rod Whitby <rod@whitby.id.au>
|
||||
@ -12,15 +18,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
static struct flash_platform_data nas100d_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
@ -39,35 +52,40 @@ static struct platform_device nas100d_flash = {
|
||||
.resource = &nas100d_flash_resource,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LEDS_IXP4XX
|
||||
static struct resource nas100d_led_resources[] = {
|
||||
static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
|
||||
{
|
||||
.name = "wlan", /* green led */
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.flags = IXP4XX_GPIO_LOW,
|
||||
},
|
||||
{
|
||||
.name = "ready", /* blue power led (off is flashing!) */
|
||||
.start = 15,
|
||||
.end = 15,
|
||||
.flags = IXP4XX_GPIO_LOW,
|
||||
},
|
||||
{
|
||||
.name = "disk", /* yellow led */
|
||||
.start = 3,
|
||||
.end = 3,
|
||||
.flags = IXP4XX_GPIO_LOW,
|
||||
I2C_BOARD_INFO("rtc-pcf8563", 0x51),
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device nas100d_leds = {
|
||||
.name = "IXP4XX-GPIO-LED",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(nas100d_led_resources),
|
||||
.resource = nas100d_led_resources,
|
||||
static struct gpio_led nas100d_led_pins[] = {
|
||||
{
|
||||
.name = "wlan", /* green led */
|
||||
.gpio = NAS100D_LED_WLAN_GPIO,
|
||||
.active_low = true,
|
||||
},
|
||||
{
|
||||
.name = "power", /* blue power led (off=flashing) */
|
||||
.gpio = NAS100D_LED_PWR_GPIO,
|
||||
.active_low = true,
|
||||
},
|
||||
{
|
||||
.name = "disk", /* yellow led */
|
||||
.gpio = NAS100D_LED_DISK_GPIO,
|
||||
.active_low = true,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data nas100d_led_data = {
|
||||
.num_leds = ARRAY_SIZE(nas100d_led_pins),
|
||||
.leds = nas100d_led_pins,
|
||||
};
|
||||
|
||||
static struct platform_device nas100d_leds = {
|
||||
.name = "leds-gpio",
|
||||
.id = -1,
|
||||
.dev.platform_data = &nas100d_led_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
|
||||
.sda_pin = NAS100D_SDA_PIN,
|
||||
@ -125,12 +143,28 @@ static struct platform_device nas100d_uart = {
|
||||
.resource = nas100d_uart_resources,
|
||||
};
|
||||
|
||||
/* Built-in 10/100 Ethernet MAC interfaces */
|
||||
static struct eth_plat_info nas100d_plat_eth[] = {
|
||||
{
|
||||
.phy = 0,
|
||||
.rxq = 3,
|
||||
.txreadyq = 20,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device nas100d_eth[] = {
|
||||
{
|
||||
.name = "ixp4xx_eth",
|
||||
.id = IXP4XX_ETH_NPEB,
|
||||
.dev.platform_data = nas100d_plat_eth,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device *nas100d_devices[] __initdata = {
|
||||
&nas100d_i2c_gpio,
|
||||
&nas100d_flash,
|
||||
#ifdef CONFIG_LEDS_IXP4XX
|
||||
&nas100d_leds,
|
||||
#endif
|
||||
&nas100d_eth[0],
|
||||
};
|
||||
|
||||
static void nas100d_power_off(void)
|
||||
@ -144,8 +178,63 @@ static void nas100d_power_off(void)
|
||||
gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH);
|
||||
}
|
||||
|
||||
/* This is used to make sure the power-button pusher is serious. The button
|
||||
* must be held until the value of this counter reaches zero.
|
||||
*/
|
||||
static int power_button_countdown;
|
||||
|
||||
/* Must hold the button down for at least this many counts to be processed */
|
||||
#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
|
||||
|
||||
static void nas100d_power_handler(unsigned long data);
|
||||
static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler, 0, 0);
|
||||
|
||||
static void nas100d_power_handler(unsigned long data)
|
||||
{
|
||||
/* This routine is called twice per second to check the
|
||||
* state of the power button.
|
||||
*/
|
||||
|
||||
if (gpio_get_value(NAS100D_PB_GPIO)) {
|
||||
|
||||
/* IO Pin is 1 (button pushed) */
|
||||
if (power_button_countdown > 0)
|
||||
power_button_countdown--;
|
||||
|
||||
} else {
|
||||
|
||||
/* Done on button release, to allow for auto-power-on mods. */
|
||||
if (power_button_countdown == 0) {
|
||||
/* Signal init to do the ctrlaltdel action,
|
||||
* this will bypass init if it hasn't started
|
||||
* and do a kernel_restart.
|
||||
*/
|
||||
ctrl_alt_del();
|
||||
|
||||
/* Change the state of the power LED to "blink" */
|
||||
gpio_line_set(NAS100D_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
|
||||
} else {
|
||||
power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* This is the paper-clip reset, it shuts the machine down directly. */
|
||||
machine_power_off();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void __init nas100d_init(void)
|
||||
{
|
||||
DECLARE_MAC_BUF(mac_buf);
|
||||
uint8_t __iomem *f;
|
||||
int i;
|
||||
|
||||
ixp4xx_sys_init();
|
||||
|
||||
/* gpio 14 and 15 are _not_ clocks */
|
||||
@ -155,7 +244,8 @@ static void __init nas100d_init(void)
|
||||
nas100d_flash_resource.end =
|
||||
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
|
||||
|
||||
pm_power_off = nas100d_power_off;
|
||||
i2c_register_board_info(0, nas100d_i2c_board_info,
|
||||
ARRAY_SIZE(nas100d_i2c_board_info));
|
||||
|
||||
/*
|
||||
* This is only useful on a modified machine, but it is valuable
|
||||
@ -165,6 +255,48 @@ static void __init nas100d_init(void)
|
||||
(void)platform_device_register(&nas100d_uart);
|
||||
|
||||
platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
|
||||
|
||||
pm_power_off = nas100d_power_off;
|
||||
|
||||
if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_LOW,
|
||||
"NAS100D reset button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
|
||||
gpio_to_irq(NAS100D_RB_GPIO));
|
||||
}
|
||||
|
||||
/* The power button on the Iomega NAS100d is on GPIO 14, but
|
||||
* it cannot handle interrupts on that GPIO line. So we'll
|
||||
* have to poll it with a kernel timer.
|
||||
*/
|
||||
|
||||
/* Make sure that the power button GPIO is set up as an input */
|
||||
gpio_line_config(NAS100D_PB_GPIO, IXP4XX_GPIO_IN);
|
||||
|
||||
/* Set the initial value for the power button IRQ handler */
|
||||
power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
|
||||
|
||||
mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
|
||||
|
||||
/*
|
||||
* Map in a portion of the flash and read the MAC address.
|
||||
* Since it is stored in BE in the flash itself, we need to
|
||||
* byteswap it if we're in LE mode.
|
||||
*/
|
||||
f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000);
|
||||
if (f) {
|
||||
for (i = 0; i < 6; i++)
|
||||
#ifdef __ARMEB__
|
||||
nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + i);
|
||||
#else
|
||||
nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + (i^3));
|
||||
#endif
|
||||
iounmap(f);
|
||||
}
|
||||
printk(KERN_INFO "NAS100D: Using MAC address %s for port 0\n",
|
||||
print_mac(mac_buf, nas100d_plat_eth[0].hwaddr));
|
||||
|
||||
}
|
||||
|
||||
MACHINE_START(NAS100D, "Iomega NAS 100d")
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-ixp4xx/nslu2-power.c
|
||||
*
|
||||
* NSLU2 Power/Reset driver
|
||||
*
|
||||
* Copyright (C) 2005 Tower Technologies
|
||||
*
|
||||
* based on nslu2-io.c
|
||||
* Copyright (C) 2004 Karen Spearel
|
||||
*
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
* Maintainers: http://www.nslu2-linux.org/
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* Signal init to do the ctrlaltdel action, this will bypass init if
|
||||
* it hasn't started and do a kernel_restart.
|
||||
*/
|
||||
ctrl_alt_del();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* This is the paper-clip reset, it shuts the machine down directly.
|
||||
*/
|
||||
machine_power_off();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init nslu2_power_init(void)
|
||||
{
|
||||
if (!(machine_is_nslu2()))
|
||||
return 0;
|
||||
|
||||
*IXP4XX_GPIO_GPISR = 0x20400000; /* read the 2 irqs to clr */
|
||||
|
||||
set_irq_type(NSLU2_RB_IRQ, IRQT_LOW);
|
||||
set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH);
|
||||
|
||||
if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler,
|
||||
IRQF_DISABLED, "NSLU2 reset button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
|
||||
NSLU2_RB_IRQ);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (request_irq(NSLU2_PB_IRQ, &nslu2_power_handler,
|
||||
IRQF_DISABLED, "NSLU2 power button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Power Button IRQ %d not available\n",
|
||||
NSLU2_PB_IRQ);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit nslu2_power_exit(void)
|
||||
{
|
||||
if (!(machine_is_nslu2()))
|
||||
return;
|
||||
|
||||
free_irq(NSLU2_RB_IRQ, NULL);
|
||||
free_irq(NSLU2_PB_IRQ, NULL);
|
||||
}
|
||||
|
||||
module_init(nslu2_power_init);
|
||||
module_exit(nslu2_power_exit);
|
||||
|
||||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
||||
MODULE_DESCRIPTION("NSLU2 Power/Reset driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -3,27 +3,35 @@
|
||||
*
|
||||
* NSLU2 board-setup
|
||||
*
|
||||
* based ixdp425-setup.c:
|
||||
* Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
|
||||
*
|
||||
* based on ixdp425-setup.c:
|
||||
* Copyright (C) 2003-2004 MontaVista Software, Inc.
|
||||
* based on nslu2-power.c:
|
||||
* Copyright (C) 2005 Tower Technologies
|
||||
*
|
||||
* Author: Mark Rakes <mrakes at mac.com>
|
||||
* Author: Rod Whitby <rod@whitby.id.au>
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
* Maintainers: http://www.nslu2-linux.org/
|
||||
*
|
||||
* Fixed missing init_time in MACHINE_START kas11 10/22/04
|
||||
* Changed to conform to new style __init ixdp425 kas11 10/22/04
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
static struct flash_platform_data nslu2_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
@ -47,41 +55,43 @@ static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
|
||||
.scl_pin = NSLU2_SCL_PIN,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LEDS_IXP4XX
|
||||
static struct resource nslu2_led_resources[] = {
|
||||
static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
|
||||
{
|
||||
.name = "ready", /* green led */
|
||||
.start = NSLU2_LED_GRN_GPIO,
|
||||
.end = NSLU2_LED_GRN_GPIO,
|
||||
.flags = IXP4XX_GPIO_HIGH,
|
||||
},
|
||||
{
|
||||
.name = "status", /* red led */
|
||||
.start = NSLU2_LED_RED_GPIO,
|
||||
.end = NSLU2_LED_RED_GPIO,
|
||||
.flags = IXP4XX_GPIO_HIGH,
|
||||
},
|
||||
{
|
||||
.name = "disk-1",
|
||||
.start = NSLU2_LED_DISK1_GPIO,
|
||||
.end = NSLU2_LED_DISK1_GPIO,
|
||||
.flags = IXP4XX_GPIO_LOW,
|
||||
},
|
||||
{
|
||||
.name = "disk-2",
|
||||
.start = NSLU2_LED_DISK2_GPIO,
|
||||
.end = NSLU2_LED_DISK2_GPIO,
|
||||
.flags = IXP4XX_GPIO_LOW,
|
||||
I2C_BOARD_INFO("rtc-x1205", 0x6f),
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device nslu2_leds = {
|
||||
.name = "IXP4XX-GPIO-LED",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(nslu2_led_resources),
|
||||
.resource = nslu2_led_resources,
|
||||
static struct gpio_led nslu2_led_pins[] = {
|
||||
{
|
||||
.name = "ready", /* green led */
|
||||
.gpio = NSLU2_LED_GRN_GPIO,
|
||||
},
|
||||
{
|
||||
.name = "status", /* red led */
|
||||
.gpio = NSLU2_LED_RED_GPIO,
|
||||
},
|
||||
{
|
||||
.name = "disk-1",
|
||||
.gpio = NSLU2_LED_DISK1_GPIO,
|
||||
.active_low = true,
|
||||
},
|
||||
{
|
||||
.name = "disk-2",
|
||||
.gpio = NSLU2_LED_DISK2_GPIO,
|
||||
.active_low = true,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data nslu2_led_data = {
|
||||
.num_leds = ARRAY_SIZE(nslu2_led_pins),
|
||||
.leds = nslu2_led_pins,
|
||||
};
|
||||
|
||||
static struct platform_device nslu2_leds = {
|
||||
.name = "leds-gpio",
|
||||
.id = -1,
|
||||
.dev.platform_data = &nslu2_led_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_device nslu2_i2c_gpio = {
|
||||
.name = "i2c-gpio",
|
||||
@ -140,13 +150,29 @@ static struct platform_device nslu2_uart = {
|
||||
.resource = nslu2_uart_resources,
|
||||
};
|
||||
|
||||
/* Built-in 10/100 Ethernet MAC interfaces */
|
||||
static struct eth_plat_info nslu2_plat_eth[] = {
|
||||
{
|
||||
.phy = 1,
|
||||
.rxq = 3,
|
||||
.txreadyq = 20,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device nslu2_eth[] = {
|
||||
{
|
||||
.name = "ixp4xx_eth",
|
||||
.id = IXP4XX_ETH_NPEB,
|
||||
.dev.platform_data = nslu2_plat_eth,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device *nslu2_devices[] __initdata = {
|
||||
&nslu2_i2c_gpio,
|
||||
&nslu2_flash,
|
||||
&nslu2_beeper,
|
||||
#ifdef CONFIG_LEDS_IXP4XX
|
||||
&nslu2_leds,
|
||||
#endif
|
||||
&nslu2_eth[0],
|
||||
};
|
||||
|
||||
static void nslu2_power_off(void)
|
||||
@ -160,6 +186,25 @@ static void nslu2_power_off(void)
|
||||
gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
|
||||
}
|
||||
|
||||
static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* Signal init to do the ctrlaltdel action, this will bypass init if
|
||||
* it hasn't started and do a kernel_restart.
|
||||
*/
|
||||
ctrl_alt_del();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
|
||||
{
|
||||
/* This is the paper-clip reset, it shuts the machine down directly.
|
||||
*/
|
||||
machine_power_off();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void __init nslu2_timer_init(void)
|
||||
{
|
||||
/* The xtal on this machine is non-standard. */
|
||||
@ -175,13 +220,18 @@ static struct sys_timer nslu2_timer = {
|
||||
|
||||
static void __init nslu2_init(void)
|
||||
{
|
||||
DECLARE_MAC_BUF(mac_buf);
|
||||
uint8_t __iomem *f;
|
||||
int i;
|
||||
|
||||
ixp4xx_sys_init();
|
||||
|
||||
nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
|
||||
nslu2_flash_resource.end =
|
||||
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
|
||||
|
||||
pm_power_off = nslu2_power_off;
|
||||
i2c_register_board_info(0, nslu2_i2c_board_info,
|
||||
ARRAY_SIZE(nslu2_i2c_board_info));
|
||||
|
||||
/*
|
||||
* This is only useful on a modified machine, but it is valuable
|
||||
@ -191,6 +241,43 @@ static void __init nslu2_init(void)
|
||||
(void)platform_device_register(&nslu2_uart);
|
||||
|
||||
platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
|
||||
|
||||
pm_power_off = nslu2_power_off;
|
||||
|
||||
if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_LOW,
|
||||
"NSLU2 reset button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
|
||||
gpio_to_irq(NSLU2_RB_GPIO));
|
||||
}
|
||||
|
||||
if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_HIGH,
|
||||
"NSLU2 power button", NULL) < 0) {
|
||||
|
||||
printk(KERN_DEBUG "Power Button IRQ %d not available\n",
|
||||
gpio_to_irq(NSLU2_PB_GPIO));
|
||||
}
|
||||
|
||||
/*
|
||||
* Map in a portion of the flash and read the MAC address.
|
||||
* Since it is stored in BE in the flash itself, we need to
|
||||
* byteswap it if we're in LE mode.
|
||||
*/
|
||||
f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x40000);
|
||||
if (f) {
|
||||
for (i = 0; i < 6; i++)
|
||||
#ifdef __ARMEB__
|
||||
nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + i);
|
||||
#else
|
||||
nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + (i^3));
|
||||
#endif
|
||||
iounmap(f);
|
||||
}
|
||||
printk(KERN_INFO "NSLU2: Using MAC address %s for port 0\n",
|
||||
print_mac(mac_buf, nslu2_plat_eth[0].hwaddr));
|
||||
|
||||
}
|
||||
|
||||
MACHINE_START(NSLU2, "Linksys NSLU2")
|
||||
|
@ -6,7 +6,7 @@
|
||||
obj-y += clock.o devices.o generic.o irq.o dma.o time.o
|
||||
obj-$(CONFIG_PXA25x) += pxa25x.o
|
||||
obj-$(CONFIG_PXA27x) += pxa27x.o
|
||||
obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o
|
||||
obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o
|
||||
obj-$(CONFIG_CPU_PXA300) += pxa300.o
|
||||
obj-$(CONFIG_CPU_PXA320) += pxa320.o
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
#include <asm/arch/pxafb.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/i2c.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
||||
#include "devices.h"
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
@ -226,3 +227,59 @@ void __init pxa_map_io(void)
|
||||
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
|
||||
get_clk_frequency_khz(1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static unsigned long saved_gplr[4];
|
||||
static unsigned long saved_gpdr[4];
|
||||
static unsigned long saved_grer[4];
|
||||
static unsigned long saved_gfer[4];
|
||||
|
||||
static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
int i, gpio;
|
||||
|
||||
for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
|
||||
saved_gplr[i] = GPLR(gpio);
|
||||
saved_gpdr[i] = GPDR(gpio);
|
||||
saved_grer[i] = GRER(gpio);
|
||||
saved_gfer[i] = GFER(gpio);
|
||||
|
||||
/* Clear GPIO transition detect bits */
|
||||
GEDR(gpio) = GEDR(gpio);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa_gpio_resume(struct sys_device *dev)
|
||||
{
|
||||
int i, gpio;
|
||||
|
||||
for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
|
||||
/* restore level with set/clear */
|
||||
GPSR(gpio) = saved_gplr[i];
|
||||
GPCR(gpio) = ~saved_gplr[i];
|
||||
|
||||
GRER(gpio) = saved_grer[i];
|
||||
GFER(gpio) = saved_gfer[i];
|
||||
GPDR(gpio) = saved_gpdr[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pxa_gpio_suspend NULL
|
||||
#define pxa_gpio_resume NULL
|
||||
#endif
|
||||
|
||||
struct sysdev_class pxa_gpio_sysclass = {
|
||||
.name = "gpio",
|
||||
.suspend = pxa_gpio_suspend,
|
||||
.resume = pxa_gpio_resume,
|
||||
};
|
||||
|
||||
static int __init pxa_gpio_init(void)
|
||||
{
|
||||
return sysdev_class_register(&pxa_gpio_sysclass);
|
||||
}
|
||||
|
||||
core_initcall(pxa_gpio_init);
|
||||
|
@ -52,3 +52,6 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
|
||||
#define pxa3xx_get_clk_frequency_khz(x) (0)
|
||||
#define pxa3xx_get_memclk_frequency_10khz() (0)
|
||||
#endif
|
||||
|
||||
extern struct sysdev_class pxa_irq_sysclass;
|
||||
extern struct sysdev_class pxa_gpio_sysclass;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
@ -321,3 +322,64 @@ void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
|
||||
pxa_low_gpio_chip.set_wake = set_wake;
|
||||
pxa_muxed_gpio_chip.set_wake = set_wake;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static unsigned long saved_icmr[2];
|
||||
|
||||
static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
switch (dev->id) {
|
||||
case 0:
|
||||
saved_icmr[0] = ICMR;
|
||||
ICMR = 0;
|
||||
break;
|
||||
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
|
||||
case 1:
|
||||
saved_icmr[1] = ICMR2;
|
||||
ICMR2 = 0;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa_irq_resume(struct sys_device *dev)
|
||||
{
|
||||
switch (dev->id) {
|
||||
case 0:
|
||||
ICMR = saved_icmr[0];
|
||||
ICLR = 0;
|
||||
ICCR = 1;
|
||||
break;
|
||||
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
|
||||
case 1:
|
||||
ICMR2 = saved_icmr[1];
|
||||
ICLR2 = 0;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pxa_irq_suspend NULL
|
||||
#define pxa_irq_resume NULL
|
||||
#endif
|
||||
|
||||
struct sysdev_class pxa_irq_sysclass = {
|
||||
.name = "irq",
|
||||
.suspend = pxa_irq_suspend,
|
||||
.resume = pxa_irq_resume,
|
||||
};
|
||||
|
||||
static int __init pxa_irq_init(void)
|
||||
{
|
||||
return sysdev_class_register(&pxa_irq_sysclass);
|
||||
}
|
||||
|
||||
core_initcall(pxa_irq_init);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/mfp.h>
|
||||
#include <asm/arch/mfp-pxa3xx.h>
|
||||
#include <asm/arch/pxa3xx-regs.h>
|
||||
|
||||
/* mfp_spin_lock is used to ensure that MFP register configuration
|
||||
* (most likely a read-modify-write operation) is atomic, and that
|
||||
@ -223,11 +224,19 @@ static int pxa3xx_mfp_resume(struct sys_device *d)
|
||||
struct pxa3xx_mfp_pin *p = &mfp_table[pin];
|
||||
__mfp_config_run(p);
|
||||
}
|
||||
|
||||
/* clear RDH bit when MFP settings are restored
|
||||
*
|
||||
* NOTE: the last 3 bits DxS are write-1-to-clear so carefully
|
||||
* preserve them here in case they will be referenced later
|
||||
*/
|
||||
ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class mfp_sysclass = {
|
||||
set_kset_name("mfp"),
|
||||
.name = "mfp",
|
||||
.suspend = pxa3xx_mfp_suspend,
|
||||
.resume = pxa3xx_mfp_resume,
|
||||
};
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
#include <asm/arch/pxa2xx_spi.h>
|
||||
#include <asm/arch/pcm027.h>
|
||||
#include "generic.h"
|
||||
|
@ -164,7 +164,7 @@ static struct resource poodlets_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned long poodle_get_hsync_len(void)
|
||||
static unsigned long poodle_get_hsync_invperiod(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -174,9 +174,9 @@ static void poodle_null_hsync(void)
|
||||
}
|
||||
|
||||
static struct corgits_machinfo poodle_ts_machinfo = {
|
||||
.get_hsync_len = poodle_get_hsync_len,
|
||||
.put_hsync = poodle_null_hsync,
|
||||
.wait_hsync = poodle_null_hsync,
|
||||
.get_hsync_invperiod = poodle_get_hsync_invperiod,
|
||||
.put_hsync = poodle_null_hsync,
|
||||
.wait_hsync = poodle_null_hsync,
|
||||
};
|
||||
|
||||
static struct platform_device poodle_ts_device = {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/irqs.h>
|
||||
@ -141,11 +142,6 @@ static struct clk pxa25x_clks[] = {
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
#define RESTORE_GPLEVEL(n) do { \
|
||||
GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List of global PXA peripheral registers to preserve.
|
||||
* More ones like CP and general purpose register values are preserved
|
||||
@ -153,10 +149,6 @@ static struct clk pxa25x_clks[] = {
|
||||
*/
|
||||
enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
|
||||
SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
|
||||
SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
|
||||
SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
|
||||
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
|
||||
|
||||
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
|
||||
@ -165,7 +157,6 @@ enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_PSTR,
|
||||
|
||||
SLEEP_SAVE_ICMR,
|
||||
SLEEP_SAVE_CKEN,
|
||||
|
||||
SLEEP_SAVE_SIZE
|
||||
@ -174,17 +165,12 @@ enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
|
||||
{
|
||||
SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
|
||||
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
|
||||
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
|
||||
SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
|
||||
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
|
||||
|
||||
SAVE(GAFR0_L); SAVE(GAFR0_U);
|
||||
SAVE(GAFR1_L); SAVE(GAFR1_U);
|
||||
SAVE(GAFR2_L); SAVE(GAFR2_U);
|
||||
|
||||
SAVE(ICMR); ICMR = 0;
|
||||
SAVE(CKEN);
|
||||
SAVE(PSTR);
|
||||
|
||||
@ -198,22 +184,14 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
|
||||
PSPR = 0;
|
||||
|
||||
/* restore registers */
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
|
||||
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
|
||||
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
|
||||
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
|
||||
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
|
||||
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
|
||||
|
||||
PSSR = PSSR_RDH | PSSR_PH;
|
||||
|
||||
RESTORE(CKEN);
|
||||
|
||||
ICLR = 0;
|
||||
ICCR = 1;
|
||||
RESTORE(ICMR);
|
||||
RESTORE(PSTR);
|
||||
}
|
||||
|
||||
@ -304,9 +282,17 @@ static struct platform_device *pxa25x_devices[] __initdata = {
|
||||
&pxa25x_device_assp,
|
||||
};
|
||||
|
||||
static struct sys_device pxa25x_sysdev[] = {
|
||||
{
|
||||
.cls = &pxa_irq_sysclass,
|
||||
}, {
|
||||
.cls = &pxa_gpio_sysclass,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pxa25x_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, ret = 0;
|
||||
|
||||
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
|
||||
if (cpu_is_pxa25x())
|
||||
@ -320,9 +306,18 @@ static int __init pxa25x_init(void)
|
||||
|
||||
pxa25x_init_pm();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pxa25x_sysdev); i++) {
|
||||
ret = sysdev_register(&pxa25x_sysdev[i]);
|
||||
if (ret)
|
||||
pr_err("failed to register sysdev[%d]\n", i);
|
||||
}
|
||||
|
||||
ret = platform_add_devices(pxa25x_devices,
|
||||
ARRAY_SIZE(pxa25x_devices));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
|
||||
if (cpu_is_pxa25x())
|
||||
ret = platform_device_register(&pxa_device_hwuart);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
@ -171,11 +172,6 @@ static struct clk pxa27x_clks[] = {
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
#define RESTORE_GPLEVEL(n) do { \
|
||||
GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List of global PXA peripheral registers to preserve.
|
||||
* More ones like CP and general purpose register values are preserved
|
||||
@ -183,10 +179,6 @@ static struct clk pxa27x_clks[] = {
|
||||
*/
|
||||
enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
|
||||
SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
|
||||
SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
|
||||
SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
|
||||
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
|
||||
|
||||
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
|
||||
@ -196,7 +188,6 @@ enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_PSTR,
|
||||
|
||||
SLEEP_SAVE_ICMR,
|
||||
SLEEP_SAVE_CKEN,
|
||||
|
||||
SLEEP_SAVE_MDREFR,
|
||||
@ -208,10 +199,6 @@ enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
void pxa27x_cpu_pm_save(unsigned long *sleep_save)
|
||||
{
|
||||
SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3);
|
||||
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3);
|
||||
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3);
|
||||
SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3);
|
||||
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3);
|
||||
|
||||
SAVE(GAFR0_L); SAVE(GAFR0_U);
|
||||
@ -223,12 +210,8 @@ void pxa27x_cpu_pm_save(unsigned long *sleep_save)
|
||||
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
|
||||
SAVE(PFER); SAVE(PKWR);
|
||||
|
||||
SAVE(ICMR); ICMR = 0;
|
||||
SAVE(CKEN);
|
||||
SAVE(PSTR);
|
||||
|
||||
/* Clear GPIO transition detect bits */
|
||||
GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3;
|
||||
}
|
||||
|
||||
void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
|
||||
@ -237,15 +220,10 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
|
||||
PSPR = 0;
|
||||
|
||||
/* restore registers */
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1);
|
||||
RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3);
|
||||
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
|
||||
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
|
||||
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
|
||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U);
|
||||
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3);
|
||||
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3);
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3);
|
||||
|
||||
RESTORE(MDREFR);
|
||||
@ -256,9 +234,6 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
|
||||
|
||||
RESTORE(CKEN);
|
||||
|
||||
ICLR = 0;
|
||||
ICCR = 1;
|
||||
RESTORE(ICMR);
|
||||
RESTORE(PSTR);
|
||||
}
|
||||
|
||||
@ -409,9 +384,22 @@ static struct platform_device *devices[] __initdata = {
|
||||
&pxa27x_device_ssp3,
|
||||
};
|
||||
|
||||
static struct sys_device pxa27x_sysdev[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.cls = &pxa_irq_sysclass,
|
||||
}, {
|
||||
.id = 1,
|
||||
.cls = &pxa_irq_sysclass,
|
||||
}, {
|
||||
.cls = &pxa_gpio_sysclass,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pxa27x_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, ret = 0;
|
||||
|
||||
if (cpu_is_pxa27x()) {
|
||||
clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
|
||||
|
||||
@ -420,8 +408,15 @@ static int __init pxa27x_init(void)
|
||||
|
||||
pxa27x_init_pm();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pxa27x_sysdev); i++) {
|
||||
ret = sysdev_register(&pxa27x_sysdev[i]);
|
||||
if (ret)
|
||||
pr_err("failed to register sysdev[%d]\n", i);
|
||||
}
|
||||
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/pxa3xx-regs.h>
|
||||
@ -39,6 +40,7 @@
|
||||
#define RO_CLK 60000000
|
||||
|
||||
#define ACCR_D0CS (1 << 26)
|
||||
#define ACCR_PCCE (1 << 11)
|
||||
|
||||
/* crystal frequency to static memory controller multiplier (SMCFS) */
|
||||
static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
|
||||
@ -203,7 +205,6 @@ static struct clk pxa3xx_clks[] = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#define SLEEP_SAVE_SIZE 4
|
||||
|
||||
#define ISRAM_START 0x5c000000
|
||||
#define ISRAM_SIZE SZ_256K
|
||||
@ -211,25 +212,29 @@ static struct clk pxa3xx_clks[] = {
|
||||
static void __iomem *sram;
|
||||
static unsigned long wakeup_src;
|
||||
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
enum { SLEEP_SAVE_START = 0,
|
||||
SLEEP_SAVE_CKENA,
|
||||
SLEEP_SAVE_CKENB,
|
||||
SLEEP_SAVE_ACCR,
|
||||
|
||||
SLEEP_SAVE_SIZE,
|
||||
};
|
||||
|
||||
static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
|
||||
{
|
||||
pr_debug("PM: CKENA=%08x CKENB=%08x\n", CKENA, CKENB);
|
||||
|
||||
if (CKENA & (1 << CKEN_USBH)) {
|
||||
printk(KERN_ERR "PM: USB host clock not stopped?\n");
|
||||
CKENA &= ~(1 << CKEN_USBH);
|
||||
}
|
||||
// CKENA |= 1 << (CKEN_ISC & 31);
|
||||
|
||||
/*
|
||||
* Low power modes require the HSIO2 clock to be enabled.
|
||||
*/
|
||||
CKENB |= 1 << (CKEN_HSIO2 & 31);
|
||||
SAVE(CKENA);
|
||||
SAVE(CKENB);
|
||||
SAVE(ACCR);
|
||||
}
|
||||
|
||||
static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
|
||||
{
|
||||
CKENB &= ~(1 << (CKEN_HSIO2 & 31));
|
||||
RESTORE(ACCR);
|
||||
RESTORE(CKENA);
|
||||
RESTORE(CKENB);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -265,6 +270,46 @@ static void pxa3xx_cpu_standby(unsigned int pwrmode)
|
||||
printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: currently, the OBM (OEM Boot Module) binary comes along with
|
||||
* PXA3xx development kits assumes that the resuming process continues
|
||||
* with the address stored within the first 4 bytes of SDRAM. The PSPR
|
||||
* register is used privately by BootROM and OBM, and _must_ be set to
|
||||
* 0x5c014000 for the moment.
|
||||
*/
|
||||
static void pxa3xx_cpu_pm_suspend(void)
|
||||
{
|
||||
volatile unsigned long *p = (volatile void *)0xc0000000;
|
||||
unsigned long saved_data = *p;
|
||||
|
||||
extern void pxa3xx_cpu_suspend(void);
|
||||
extern void pxa3xx_cpu_resume(void);
|
||||
|
||||
/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
|
||||
CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
|
||||
CKENB |= 1 << (CKEN_HSIO2 & 0x1f);
|
||||
|
||||
/* clear and setup wakeup source */
|
||||
AD3SR = ~0;
|
||||
AD3ER = wakeup_src;
|
||||
ASCR = ASCR;
|
||||
ARSR = ARSR;
|
||||
|
||||
PCFR |= (1u << 13); /* L1_DIS */
|
||||
PCFR &= ~((1u << 12) | (1u << 1)); /* L0_EN | SL_ROD */
|
||||
|
||||
PSPR = 0x5c014000;
|
||||
|
||||
/* overwrite with the resume address */
|
||||
*p = virt_to_phys(pxa3xx_cpu_resume);
|
||||
|
||||
pxa3xx_cpu_suspend();
|
||||
|
||||
*p = saved_data;
|
||||
|
||||
AD3ER = 0;
|
||||
}
|
||||
|
||||
static void pxa3xx_cpu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
/*
|
||||
@ -279,6 +324,7 @@ static void pxa3xx_cpu_pm_enter(suspend_state_t state)
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_MEM:
|
||||
pxa3xx_cpu_pm_suspend();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -452,9 +498,21 @@ static struct platform_device *devices[] __initdata = {
|
||||
&pxa3xx_device_ssp4,
|
||||
};
|
||||
|
||||
static struct sys_device pxa3xx_sysdev[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.cls = &pxa_irq_sysclass,
|
||||
}, {
|
||||
.id = 1,
|
||||
.cls = &pxa_irq_sysclass,
|
||||
}, {
|
||||
.cls = &pxa_gpio_sysclass,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pxa3xx_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, ret = 0;
|
||||
|
||||
if (cpu_is_pxa3xx()) {
|
||||
clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
|
||||
@ -464,9 +522,16 @@ static int __init pxa3xx_init(void)
|
||||
|
||||
pxa3xx_init_pm();
|
||||
|
||||
return platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
for (i = 0; i < ARRAY_SIZE(pxa3xx_sysdev); i++) {
|
||||
ret = sysdev_register(&pxa3xx_sysdev[i]);
|
||||
if (ret)
|
||||
pr_err("failed to register sysdev[%d]\n", i);
|
||||
}
|
||||
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
subsys_initcall(pxa3xx_init);
|
||||
|
@ -50,6 +50,108 @@ pxa_cpu_save_sp:
|
||||
str r0, [r1]
|
||||
ldr pc, [sp], #4
|
||||
|
||||
#ifdef CONFIG_PXA3xx
|
||||
/*
|
||||
* pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
|
||||
*
|
||||
* NOTE: unfortunately, pxa_cpu_save_cp can not be reused here since
|
||||
* the auxiliary control register address is different between pxa3xx
|
||||
* and pxa{25x,27x}
|
||||
*/
|
||||
|
||||
ENTRY(pxa3xx_cpu_suspend)
|
||||
|
||||
#ifndef CONFIG_IWMMXT
|
||||
mra r2, r3, acc0
|
||||
#endif
|
||||
stmfd sp!, {r2 - r12, lr} @ save registers on stack
|
||||
|
||||
mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode
|
||||
mrc p15, 0, r4, c15, c1, 0 @ CP access reg
|
||||
mrc p15, 0, r5, c13, c0, 0 @ PID
|
||||
mrc p15, 0, r6, c3, c0, 0 @ domain ID
|
||||
mrc p15, 0, r7, c2, c0, 0 @ translation table base addr
|
||||
mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg
|
||||
mrc p15, 0, r9, c1, c0, 0 @ control reg
|
||||
|
||||
bic r3, r3, #2 @ clear frequency change bit
|
||||
|
||||
@ store them plus current virtual stack ptr on stack
|
||||
mov r10, sp
|
||||
stmfd sp!, {r3 - r10}
|
||||
|
||||
@ store physical address of stack pointer
|
||||
mov r0, sp
|
||||
bl sleep_phys_sp
|
||||
ldr r1, =sleep_save_sp
|
||||
str r0, [r1]
|
||||
|
||||
@ clean data cache
|
||||
bl xsc3_flush_kern_cache_all
|
||||
|
||||
mov r0, #0x06 @ S2D3C4 mode
|
||||
mcr p14, 0, r0, c7, c0, 0 @ enter sleep
|
||||
|
||||
20: b 20b @ waiting for sleep
|
||||
|
||||
.data
|
||||
.align 5
|
||||
/*
|
||||
* pxa3xx_cpu_resume
|
||||
*/
|
||||
|
||||
ENTRY(pxa3xx_cpu_resume)
|
||||
|
||||
mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
|
||||
msr cpsr_c, r0
|
||||
|
||||
ldr r0, sleep_save_sp @ stack phys addr
|
||||
ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr
|
||||
|
||||
mov r1, #0
|
||||
mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB
|
||||
mcr p15, 0, r1, c7, c10, 4 @ drain write (&fill) buffer
|
||||
mcr p15, 0, r1, c7, c5, 4 @ flush prefetch buffer
|
||||
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
|
||||
|
||||
mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode.
|
||||
mcr p15, 0, r4, c15, c1, 0 @ CP access reg
|
||||
mcr p15, 0, r5, c13, c0, 0 @ PID
|
||||
mcr p15, 0, r6, c3, c0, 0 @ domain ID
|
||||
mcr p15, 0, r7, c2, c0, 0 @ translation table base addr
|
||||
mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg
|
||||
|
||||
@ temporarily map resume_turn_on_mmu into the page table,
|
||||
@ otherwise prefetch abort occurs after MMU is turned on
|
||||
mov r1, r7
|
||||
bic r1, r1, #0x00ff
|
||||
bic r1, r1, #0x3f00
|
||||
ldr r2, =0x542e
|
||||
|
||||
adr r3, resume_turn_on_mmu
|
||||
mov r3, r3, lsr #20
|
||||
orr r4, r2, r3, lsl #20
|
||||
ldr r5, [r1, r3, lsl #2]
|
||||
str r4, [r1, r3, lsl #2]
|
||||
|
||||
@ Mapping page table address in the page table
|
||||
mov r6, r1, lsr #20
|
||||
orr r7, r2, r6, lsl #20
|
||||
ldr r8, [r1, r6, lsl #2]
|
||||
str r7, [r1, r6, lsl #2]
|
||||
|
||||
ldr r2, =pxa3xx_resume_after_mmu @ absolute virtual address
|
||||
b resume_turn_on_mmu @ cache align execution
|
||||
|
||||
.text
|
||||
pxa3xx_resume_after_mmu:
|
||||
/* restore the temporary mapping */
|
||||
str r5, [r1, r3, lsl #2]
|
||||
str r8, [r1, r6, lsl #2]
|
||||
b resume_after_mmu
|
||||
|
||||
#endif /* CONFIG_PXA3xx */
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
/*
|
||||
* pxa27x_cpu_suspend()
|
||||
|
88
arch/arm/mach-pxa/smemc.c
Normal file
88
arch/arm/mach-pxa/smemc.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Static Memory Controller
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#define SMEMC_PHYS_BASE (0x4A000000)
|
||||
#define SMEMC_PHYS_SIZE (0x90)
|
||||
|
||||
#define MSC0 (0x08) /* Static Memory Controller Register 0 */
|
||||
#define MSC1 (0x0C) /* Static Memory Controller Register 1 */
|
||||
#define SXCNFG (0x1C) /* Synchronous Static Memory Control Register */
|
||||
#define MEMCLKCFG (0x68) /* Clock Configuration */
|
||||
#define CSADRCFG0 (0x80) /* Address Configuration Register for CS0 */
|
||||
#define CSADRCFG1 (0x84) /* Address Configuration Register for CS1 */
|
||||
#define CSADRCFG2 (0x88) /* Address Configuration Register for CS2 */
|
||||
#define CSADRCFG3 (0x8C) /* Address Configuration Register for CS3 */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static void __iomem *smemc_mmio_base;
|
||||
|
||||
static unsigned long msc[2];
|
||||
static unsigned long sxcnfg, memclkcfg;
|
||||
static unsigned long csadrcfg[4];
|
||||
|
||||
static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
msc[0] = __raw_readl(smemc_mmio_base + MSC0);
|
||||
msc[1] = __raw_readl(smemc_mmio_base + MSC1);
|
||||
sxcnfg = __raw_readl(smemc_mmio_base + SXCNFG);
|
||||
memclkcfg = __raw_readl(smemc_mmio_base + MEMCLKCFG);
|
||||
csadrcfg[0] = __raw_readl(smemc_mmio_base + CSADRCFG0);
|
||||
csadrcfg[1] = __raw_readl(smemc_mmio_base + CSADRCFG1);
|
||||
csadrcfg[2] = __raw_readl(smemc_mmio_base + CSADRCFG2);
|
||||
csadrcfg[3] = __raw_readl(smemc_mmio_base + CSADRCFG3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa3xx_smemc_resume(struct sys_device *dev)
|
||||
{
|
||||
__raw_writel(msc[0], smemc_mmio_base + MSC0);
|
||||
__raw_writel(msc[1], smemc_mmio_base + MSC1);
|
||||
__raw_writel(sxcnfg, smemc_mmio_base + SXCNFG);
|
||||
__raw_writel(memclkcfg, smemc_mmio_base + MEMCLKCFG);
|
||||
__raw_writel(csadrcfg[0], smemc_mmio_base + CSADRCFG0);
|
||||
__raw_writel(csadrcfg[1], smemc_mmio_base + CSADRCFG1);
|
||||
__raw_writel(csadrcfg[2], smemc_mmio_base + CSADRCFG2);
|
||||
__raw_writel(csadrcfg[3], smemc_mmio_base + CSADRCFG3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class smemc_sysclass = {
|
||||
.name = "smemc",
|
||||
.suspend = pxa3xx_smemc_suspend,
|
||||
.resume = pxa3xx_smemc_resume,
|
||||
};
|
||||
|
||||
static struct sys_device smemc_sysdev = {
|
||||
.id = 0,
|
||||
.cls = &smemc_sysclass,
|
||||
};
|
||||
|
||||
static int __init smemc_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (cpu_is_pxa3xx()) {
|
||||
smemc_mmio_base = ioremap(SMEMC_PHYS_BASE, SMEMC_PHYS_SIZE);
|
||||
if (smemc_mmio_base == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
ret = sysdev_class_register(&smemc_sysclass);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sysdev_register(&smemc_sysdev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(smemc_init);
|
||||
#endif
|
@ -36,6 +36,7 @@
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/udc.h>
|
||||
|
@ -7,24 +7,21 @@ config MACH_REALVIEW_EB
|
||||
help
|
||||
Include support for the ARM(R) RealView Emulation Baseboard platform.
|
||||
|
||||
config REALVIEW_MPCORE
|
||||
bool "Support MPcore tile"
|
||||
config REALVIEW_EB_ARM11MP
|
||||
bool "Support ARM11MPCore tile"
|
||||
depends on MACH_REALVIEW_EB
|
||||
select CACHE_L2X0
|
||||
help
|
||||
Enable support for the MPCore tile on the Realview platform.
|
||||
Since there are device address and interrupt differences, a
|
||||
kernel built with this option enabled is not compatible with
|
||||
other tiles.
|
||||
Enable support for the ARM11MPCore tile on the Realview platform.
|
||||
|
||||
config REALVIEW_MPCORE_REVB
|
||||
bool "Support MPcore RevB tile"
|
||||
depends on REALVIEW_MPCORE
|
||||
config REALVIEW_EB_ARM11MP_REVB
|
||||
bool "Support ARM11MPCore RevB tile"
|
||||
depends on REALVIEW_EB_ARM11MP
|
||||
default n
|
||||
help
|
||||
Enable support for the MPCore RevB tile on the Realview platform.
|
||||
Since there are device address differences, a
|
||||
Enable support for the ARM11MPCore RevB tile on the Realview
|
||||
platform. Since there are device address differences, a
|
||||
kernel built with this option enabled is not compatible with
|
||||
other tiles.
|
||||
other revisions of the ARM11MPCore tile.
|
||||
|
||||
endmenu
|
||||
|
@ -4,6 +4,5 @@
|
||||
|
||||
obj-y := core.o clock.o
|
||||
obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardware.h>
|
||||
@ -37,7 +39,6 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/mmc.h>
|
||||
|
||||
@ -48,6 +49,9 @@
|
||||
|
||||
#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
|
||||
|
||||
/* used by entry-macro.S */
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
/*
|
||||
* This is the RealView sched_clock implementation. This has
|
||||
* a resolution of 41.7ns, and a maximum value of about 179s.
|
||||
@ -121,26 +125,6 @@ struct platform_device realview_flash_device = {
|
||||
.resource = &realview_flash_resource,
|
||||
};
|
||||
|
||||
static struct resource realview_smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = REALVIEW_ETH_BASE,
|
||||
.end = REALVIEW_ETH_BASE + SZ_64K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_ETH,
|
||||
.end = IRQ_ETH,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device realview_smc91x_device = {
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(realview_smc91x_resources),
|
||||
.resource = realview_smc91x_resources,
|
||||
};
|
||||
|
||||
static struct resource realview_i2c_resource = {
|
||||
.start = REALVIEW_I2C_BASE,
|
||||
.end = REALVIEW_I2C_BASE + SZ_4K - 1,
|
||||
@ -484,45 +468,64 @@ void realview_leds_event(led_event_t ledevt)
|
||||
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns number of ms since last clock interrupt. Note that interrupts
|
||||
* will have been disabled by do_gettimeoffset()
|
||||
*/
|
||||
static unsigned long realview_gettimeoffset(void)
|
||||
static void timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
{
|
||||
unsigned long ticks1, ticks2, status;
|
||||
unsigned long ctrl;
|
||||
|
||||
/*
|
||||
* Get the current number of ticks. Note that there is a race
|
||||
* condition between us reading the timer and checking for
|
||||
* an interrupt. We get around this by ensuring that the
|
||||
* counter has not reloaded between our two reads.
|
||||
*/
|
||||
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
|
||||
do {
|
||||
ticks1 = ticks2;
|
||||
status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
|
||||
+ ((IRQ_TIMERINT0_1 >> 5) << 2));
|
||||
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
|
||||
} while (ticks2 > ticks1);
|
||||
switch(mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
|
||||
/*
|
||||
* Number of ticks since last interrupt.
|
||||
*/
|
||||
ticks1 = TIMER_RELOAD - ticks2;
|
||||
ctrl = TIMER_CTRL_PERIODIC;
|
||||
ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set, and timer enabled in 'next_event' hook */
|
||||
ctrl = TIMER_CTRL_ONESHOT;
|
||||
ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
ctrl = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt pending? If so, we've reloaded once already.
|
||||
*
|
||||
* FIXME: Need to check this is effectively timer 0 that expires
|
||||
*/
|
||||
if (status & IRQMASK_TIMERINT0_1)
|
||||
ticks1 += TIMER_RELOAD;
|
||||
writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the ticks to usecs
|
||||
*/
|
||||
return TICKS2USECS(ticks1);
|
||||
static int timer_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device timer0_clockevent = {
|
||||
.name = "timer0",
|
||||
.shift = 32,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = timer_set_mode,
|
||||
.set_next_event = timer_set_next_event,
|
||||
.rating = 300,
|
||||
.cpumask = CPU_MASK_ALL,
|
||||
};
|
||||
|
||||
static void __init realview_clockevents_init(unsigned int timer_irq)
|
||||
{
|
||||
timer0_clockevent.irq = timer_irq;
|
||||
timer0_clockevent.mult =
|
||||
div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
|
||||
timer0_clockevent.max_delta_ns =
|
||||
clockevent_delta2ns(0xffffffff, &timer0_clockevent);
|
||||
timer0_clockevent.min_delta_ns =
|
||||
clockevent_delta2ns(0xf, &timer0_clockevent);
|
||||
|
||||
clockevents_register_device(&timer0_clockevent);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -530,15 +533,12 @@ static unsigned long realview_gettimeoffset(void)
|
||||
*/
|
||||
static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
// ...clear the interrupt
|
||||
struct clock_event_device *evt = &timer0_clockevent;
|
||||
|
||||
/* clear the interrupt */
|
||||
writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
|
||||
|
||||
timer_tick();
|
||||
|
||||
#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
|
||||
smp_send_timer();
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
#endif
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -549,13 +549,49 @@ static struct irqaction realview_timer_irq = {
|
||||
.handler = realview_timer_interrupt,
|
||||
};
|
||||
|
||||
static cycle_t realview_get_cycles(void)
|
||||
{
|
||||
return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_realview = {
|
||||
.name = "timer3",
|
||||
.rating = 200,
|
||||
.read = realview_get_cycles,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 20,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static void __init realview_clocksource_init(void)
|
||||
{
|
||||
/* setup timer 0 as free-running clocksource */
|
||||
writel(0, TIMER3_VA_BASE + TIMER_CTRL);
|
||||
writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
|
||||
writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
|
||||
writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
|
||||
TIMER3_VA_BASE + TIMER_CTRL);
|
||||
|
||||
clocksource_realview.mult =
|
||||
clocksource_khz2mult(1000, clocksource_realview.shift);
|
||||
clocksource_register(&clocksource_realview);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up timer interrupt, and return the current time in seconds.
|
||||
* Set up the clock source and clock events devices
|
||||
*/
|
||||
static void __init realview_timer_init(void)
|
||||
void __init realview_timer_init(unsigned int timer_irq)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||
/*
|
||||
* The dummy clock device has to be registered before the main device
|
||||
* so that the latter will broadcast the clock events
|
||||
*/
|
||||
local_timer_setup(smp_processor_id());
|
||||
#endif
|
||||
|
||||
/*
|
||||
* set clock frequency:
|
||||
* REALVIEW_REFCLK is 32KHz
|
||||
@ -576,18 +612,11 @@ static void __init realview_timer_init(void)
|
||||
writel(0, TIMER2_VA_BASE + TIMER_CTRL);
|
||||
writel(0, TIMER3_VA_BASE + TIMER_CTRL);
|
||||
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
|
||||
writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
|
||||
TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
|
||||
}
|
||||
setup_irq(timer_irq, &realview_timer_irq);
|
||||
|
||||
struct sys_timer realview_timer = {
|
||||
.init = realview_timer_init,
|
||||
.offset = realview_gettimeoffset,
|
||||
};
|
||||
realview_clocksource_init();
|
||||
realview_clockevents_init(timer_irq);
|
||||
}
|
||||
|
@ -27,8 +27,6 @@
|
||||
#include <asm/leds.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
extern struct sys_timer realview_timer;
|
||||
|
||||
#define AMBA_DEVICE(name,busid,base,plat) \
|
||||
static struct amba_device name##_device = { \
|
||||
.dev = { \
|
||||
@ -38,7 +36,7 @@ static struct amba_device name##_device = { \
|
||||
}, \
|
||||
.res = { \
|
||||
.start = REALVIEW_##base##_BASE, \
|
||||
.end = (REALVIEW_##base##_BASE) + SZ_4K - 1,\
|
||||
.end = (REALVIEW_##base##_BASE) + SZ_4K - 1, \
|
||||
.flags = IORESOURCE_MEM, \
|
||||
}, \
|
||||
.dma_mask = ~0, \
|
||||
@ -46,74 +44,19 @@ static struct amba_device name##_device = { \
|
||||
/* .dma = base##_DMA,*/ \
|
||||
}
|
||||
|
||||
/*
|
||||
* These devices are connected via the core APB bridge
|
||||
*/
|
||||
#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
|
||||
#define GPIO2_DMA { 0, 0 }
|
||||
#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
|
||||
#define GPIO3_DMA { 0, 0 }
|
||||
|
||||
#define AACI_IRQ { IRQ_AACI, NO_IRQ }
|
||||
#define AACI_DMA { 0x80, 0x81 }
|
||||
#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_MMCI0B }
|
||||
#define MMCI0_DMA { 0x84, 0 }
|
||||
#define KMI0_IRQ { IRQ_KMI0, NO_IRQ }
|
||||
#define KMI0_DMA { 0, 0 }
|
||||
#define KMI1_IRQ { IRQ_KMI1, NO_IRQ }
|
||||
#define KMI1_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected directly to the multi-layer AHB switch
|
||||
*/
|
||||
#define SMC_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define SMC_DMA { 0, 0 }
|
||||
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define MPMC_DMA { 0, 0 }
|
||||
#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
|
||||
#define CLCD_DMA { 0, 0 }
|
||||
#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
|
||||
#define DMAC_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected via the core APB bridge
|
||||
*/
|
||||
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define SCTL_DMA { 0, 0 }
|
||||
#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
|
||||
#define WATCHDOG_DMA { 0, 0 }
|
||||
#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
|
||||
#define GPIO0_DMA { 0, 0 }
|
||||
#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
|
||||
#define GPIO1_DMA { 0, 0 }
|
||||
#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
|
||||
#define RTC_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected via the DMA APB bridge
|
||||
*/
|
||||
#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
|
||||
#define SCI_DMA { 7, 6 }
|
||||
#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
|
||||
#define UART0_DMA { 15, 14 }
|
||||
#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
|
||||
#define UART1_DMA { 13, 12 }
|
||||
#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
|
||||
#define UART2_DMA { 11, 10 }
|
||||
#define UART3_IRQ { IRQ_UART3, NO_IRQ }
|
||||
#define UART3_DMA { 0x86, 0x87 }
|
||||
#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
|
||||
#define SSP_DMA { 9, 8 }
|
||||
|
||||
|
||||
extern struct platform_device realview_flash_device;
|
||||
extern struct platform_device realview_smc91x_device;
|
||||
extern struct platform_device realview_i2c_device;
|
||||
extern struct mmc_platform_data realview_mmc0_plat_data;
|
||||
extern struct mmc_platform_data realview_mmc1_plat_data;
|
||||
extern struct clk realview_clcd_clk;
|
||||
extern struct clcd_board clcd_plat_data;
|
||||
extern void __iomem *gic_cpu_base_addr;
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
extern void __iomem *twd_base_addr;
|
||||
extern unsigned int twd_size;
|
||||
#endif
|
||||
|
||||
extern void realview_leds_event(led_event_t ledevt);
|
||||
extern void realview_timer_init(unsigned int timer_irq);
|
||||
|
||||
#endif
|
||||
|
@ -14,19 +14,75 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/hardware/arm_twd.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \
|
||||
((cpu) * REALVIEW_TWD_SIZE))
|
||||
static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
|
||||
|
||||
/*
|
||||
* Used on SMP for either the local timer or IPI_TIMER
|
||||
*/
|
||||
void local_timer_interrupt(void)
|
||||
{
|
||||
struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
|
||||
|
||||
clk->event_handler(clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
|
||||
#define TWD_BASE(cpu) (twd_base_addr + (cpu) * twd_size)
|
||||
|
||||
/* set up by the platform code */
|
||||
void __iomem *twd_base_addr;
|
||||
unsigned int twd_size;
|
||||
|
||||
static unsigned long mpcore_timer_rate;
|
||||
|
||||
static void local_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
{
|
||||
void __iomem *base = TWD_BASE(smp_processor_id());
|
||||
unsigned long ctrl;
|
||||
|
||||
switch(mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* timer load already set up */
|
||||
ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
|
||||
| TWD_TIMER_CONTROL_PERIODIC;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set, and timer enabled in 'next_event' hook */
|
||||
ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
ctrl = 0;
|
||||
}
|
||||
|
||||
__raw_writel(ctrl, base + TWD_TIMER_CONTROL);
|
||||
}
|
||||
|
||||
static int local_timer_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
void __iomem *base = TWD_BASE(smp_processor_id());
|
||||
unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL);
|
||||
|
||||
__raw_writel(evt, base + TWD_TIMER_COUNTER);
|
||||
__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* local_timer_ack: checks for a local timer interrupt.
|
||||
*
|
||||
@ -45,12 +101,11 @@ int local_timer_ack(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __cpuinit local_timer_setup(unsigned int cpu)
|
||||
static void __cpuinit twd_calibrate_rate(unsigned int cpu)
|
||||
{
|
||||
void __iomem *base = TWD_BASE(cpu);
|
||||
unsigned int load, offset;
|
||||
unsigned long load, count;
|
||||
u64 waitjiffies;
|
||||
unsigned int count;
|
||||
|
||||
/*
|
||||
* If this is the first time round, we need to work out how fast
|
||||
@ -88,36 +143,36 @@ void __cpuinit local_timer_setup(unsigned int cpu)
|
||||
load = mpcore_timer_rate / HZ;
|
||||
|
||||
__raw_writel(load, base + TWD_TIMER_LOAD);
|
||||
__raw_writel(0x7, base + TWD_TIMER_CONTROL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now maneuver our local tick into the right part of the jiffy.
|
||||
* Start by working out where within the tick our local timer
|
||||
* interrupt should go.
|
||||
*/
|
||||
offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1);
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
void __cpuinit local_timer_setup(unsigned int cpu)
|
||||
{
|
||||
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* gettimeoffset() will return a number of us since the last tick.
|
||||
* Convert this number of us to a local timer tick count.
|
||||
* Be careful of integer overflow whilst keeping maximum precision.
|
||||
*
|
||||
* with HZ=100 and 1MHz (fpga) ~ 1GHz processor:
|
||||
* load = 1 ~ 10,000
|
||||
* mpcore_timer_rate/10000 = 100 ~ 100,000
|
||||
*
|
||||
* so the multiply value will be less than 10^9 always.
|
||||
*/
|
||||
load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100;
|
||||
twd_calibrate_rate(cpu);
|
||||
|
||||
/* Add on our offset to get the load value */
|
||||
load = (load + offset) % (mpcore_timer_rate / HZ);
|
||||
|
||||
__raw_writel(load, base + TWD_TIMER_COUNTER);
|
||||
clk->name = "local_timer";
|
||||
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
clk->rating = 350;
|
||||
clk->set_mode = local_timer_set_mode;
|
||||
clk->set_next_event = local_timer_set_next_event;
|
||||
clk->irq = IRQ_LOCALTIMER;
|
||||
clk->cpumask = cpumask_of_cpu(cpu);
|
||||
clk->shift = 20;
|
||||
clk->mult = div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
|
||||
clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
|
||||
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
|
||||
|
||||
/* Make sure our local interrupt controller has this enabled */
|
||||
__raw_writel(1 << IRQ_LOCALTIMER,
|
||||
__io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET);
|
||||
local_irq_save(flags);
|
||||
get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
|
||||
local_irq_restore(flags);
|
||||
|
||||
clockevents_register_device(clk);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -127,3 +182,26 @@ void __cpuexit local_timer_stop(unsigned int cpu)
|
||||
{
|
||||
__raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL);
|
||||
}
|
||||
|
||||
#else /* CONFIG_LOCAL_TIMERS */
|
||||
|
||||
static void dummy_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
{
|
||||
}
|
||||
|
||||
void __cpuinit local_timer_setup(unsigned int cpu)
|
||||
{
|
||||
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
||||
|
||||
clk->name = "dummy_timer";
|
||||
clk->features = CLOCK_EVT_FEAT_DUMMY;
|
||||
clk->rating = 200;
|
||||
clk->set_mode = dummy_timer_set_mode;
|
||||
clk->broadcast = smp_timer_broadcast;
|
||||
clk->cpumask = cpumask_of_cpu(cpu);
|
||||
|
||||
clockevents_register_device(clk);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_LOCAL_TIMERS */
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <asm/hardware/arm_scu.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
extern void realview_secondary_startup(void);
|
||||
|
||||
@ -31,9 +32,13 @@ static unsigned int __init get_core_count(void)
|
||||
{
|
||||
unsigned int ncores;
|
||||
|
||||
ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG);
|
||||
if (machine_is_realview_eb() && core_tile_eb11mp()) {
|
||||
ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG);
|
||||
ncores = (ncores & 0x03) + 1;
|
||||
} else
|
||||
ncores = 1;
|
||||
|
||||
return (ncores & 0x03) + 1;
|
||||
return ncores;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
@ -52,7 +57,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(REALVIEW_GIC_CPU_BASE));
|
||||
gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
@ -187,10 +192,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
/*
|
||||
* Enable the local timer for primary CPU
|
||||
* Enable the local timer for primary CPU. If the device is
|
||||
* dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
|
||||
* realview_timer_init
|
||||
*/
|
||||
local_timer_setup(cpu);
|
||||
if (machine_is_realview_eb() && core_tile_eb11mp())
|
||||
local_timer_setup(cpu);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialise the present map, which describes the set of CPUs
|
||||
|
@ -36,7 +36,9 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/mmc.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include <asm/arch/board-eb.h>
|
||||
#include <asm/arch/irqs.h>
|
||||
|
||||
#include "core.h"
|
||||
@ -58,26 +60,7 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
|
||||
.pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
#ifdef CONFIG_REALVIEW_MPCORE
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
|
||||
.length = SZ_8K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
|
||||
.length = SZ_4K,
|
||||
@ -103,11 +86,95 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct map_desc realview_eb11mp_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_CPU_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_CPU_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_EB11MP_L220_BASE),
|
||||
.length = SZ_8K,
|
||||
.type = MT_DEVICE,
|
||||
}
|
||||
};
|
||||
|
||||
static void __init realview_eb_map_io(void)
|
||||
{
|
||||
iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc));
|
||||
if (core_tile_eb11mp())
|
||||
iotable_init(realview_eb11mp_io_desc, ARRAY_SIZE(realview_eb11mp_io_desc));
|
||||
}
|
||||
|
||||
/*
|
||||
* RealView EB AMBA devices
|
||||
*/
|
||||
|
||||
/*
|
||||
* These devices are connected via the core APB bridge
|
||||
*/
|
||||
#define GPIO2_IRQ { IRQ_EB_GPIO2, NO_IRQ }
|
||||
#define GPIO2_DMA { 0, 0 }
|
||||
#define GPIO3_IRQ { IRQ_EB_GPIO3, NO_IRQ }
|
||||
#define GPIO3_DMA { 0, 0 }
|
||||
|
||||
#define AACI_IRQ { IRQ_EB_AACI, NO_IRQ }
|
||||
#define AACI_DMA { 0x80, 0x81 }
|
||||
#define MMCI0_IRQ { IRQ_EB_MMCI0A, IRQ_EB_MMCI0B }
|
||||
#define MMCI0_DMA { 0x84, 0 }
|
||||
#define KMI0_IRQ { IRQ_EB_KMI0, NO_IRQ }
|
||||
#define KMI0_DMA { 0, 0 }
|
||||
#define KMI1_IRQ { IRQ_EB_KMI1, NO_IRQ }
|
||||
#define KMI1_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected directly to the multi-layer AHB switch
|
||||
*/
|
||||
#define SMC_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define SMC_DMA { 0, 0 }
|
||||
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define MPMC_DMA { 0, 0 }
|
||||
#define CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ }
|
||||
#define CLCD_DMA { 0, 0 }
|
||||
#define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ }
|
||||
#define DMAC_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected via the core APB bridge
|
||||
*/
|
||||
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define SCTL_DMA { 0, 0 }
|
||||
#define WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ }
|
||||
#define WATCHDOG_DMA { 0, 0 }
|
||||
#define GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ }
|
||||
#define GPIO0_DMA { 0, 0 }
|
||||
#define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ }
|
||||
#define GPIO1_DMA { 0, 0 }
|
||||
#define RTC_IRQ { IRQ_EB_RTC, NO_IRQ }
|
||||
#define RTC_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected via the DMA APB bridge
|
||||
*/
|
||||
#define SCI_IRQ { IRQ_EB_SCI, NO_IRQ }
|
||||
#define SCI_DMA { 7, 6 }
|
||||
#define UART0_IRQ { IRQ_EB_UART0, NO_IRQ }
|
||||
#define UART0_DMA { 15, 14 }
|
||||
#define UART1_IRQ { IRQ_EB_UART1, NO_IRQ }
|
||||
#define UART1_DMA { 13, 12 }
|
||||
#define UART2_IRQ { IRQ_EB_UART2, NO_IRQ }
|
||||
#define UART2_DMA { 11, 10 }
|
||||
#define UART3_IRQ { IRQ_EB_UART3, NO_IRQ }
|
||||
#define UART3_DMA { 0x86, 0x87 }
|
||||
#define SSP_IRQ { IRQ_EB_SSP, NO_IRQ }
|
||||
#define SSP_DMA { 9, 8 }
|
||||
|
||||
/* FPGA Primecells */
|
||||
AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
|
||||
AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
|
||||
@ -153,38 +220,127 @@ static struct amba_device *amba_devs[] __initdata = {
|
||||
&kmi1_device,
|
||||
};
|
||||
|
||||
/*
|
||||
* RealView EB platform devices
|
||||
*/
|
||||
|
||||
static struct resource realview_eb_smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = REALVIEW_ETH_BASE,
|
||||
.end = REALVIEW_ETH_BASE + SZ_64K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_EB_ETH,
|
||||
.end = IRQ_EB_ETH,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device realview_eb_smc91x_device = {
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(realview_eb_smc91x_resources),
|
||||
.resource = realview_eb_smc91x_resources,
|
||||
};
|
||||
|
||||
static void __init gic_init_irq(void)
|
||||
{
|
||||
#ifdef CONFIG_REALVIEW_MPCORE
|
||||
unsigned int pldctrl;
|
||||
writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
|
||||
pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
|
||||
pldctrl |= 0x00800000; /* New irq mode */
|
||||
writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
|
||||
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
|
||||
#endif
|
||||
gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
|
||||
gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
|
||||
#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB)
|
||||
gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
|
||||
gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
|
||||
gic_cascade_irq(1, IRQ_EB_IRQ1);
|
||||
if (core_tile_eb11mp()) {
|
||||
unsigned int pldctrl;
|
||||
|
||||
/* new irq mode */
|
||||
writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
|
||||
pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
|
||||
pldctrl |= 0x00800000;
|
||||
writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
|
||||
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);
|
||||
|
||||
#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
|
||||
/* board GIC, secondary */
|
||||
gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64);
|
||||
gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE));
|
||||
gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
|
||||
#endif
|
||||
} else {
|
||||
/* board GIC, primary */
|
||||
gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE);
|
||||
gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
|
||||
gic_cpu_init(0, gic_cpu_base_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up the IRQ numbers for the RealView EB/ARM11MPCore tile
|
||||
*/
|
||||
static void realview_eb11mp_fixup(void)
|
||||
{
|
||||
/* AMBA devices */
|
||||
dmac_device.irq[0] = IRQ_EB11MP_DMA;
|
||||
uart0_device.irq[0] = IRQ_EB11MP_UART0;
|
||||
uart1_device.irq[0] = IRQ_EB11MP_UART1;
|
||||
uart2_device.irq[0] = IRQ_EB11MP_UART2;
|
||||
uart3_device.irq[0] = IRQ_EB11MP_UART3;
|
||||
clcd_device.irq[0] = IRQ_EB11MP_CLCD;
|
||||
wdog_device.irq[0] = IRQ_EB11MP_WDOG;
|
||||
gpio0_device.irq[0] = IRQ_EB11MP_GPIO0;
|
||||
gpio1_device.irq[0] = IRQ_EB11MP_GPIO1;
|
||||
gpio2_device.irq[0] = IRQ_EB11MP_GPIO2;
|
||||
rtc_device.irq[0] = IRQ_EB11MP_RTC;
|
||||
sci0_device.irq[0] = IRQ_EB11MP_SCI;
|
||||
ssp0_device.irq[0] = IRQ_EB11MP_SSP;
|
||||
aaci_device.irq[0] = IRQ_EB11MP_AACI;
|
||||
mmc0_device.irq[0] = IRQ_EB11MP_MMCI0A;
|
||||
mmc0_device.irq[1] = IRQ_EB11MP_MMCI0B;
|
||||
kmi0_device.irq[0] = IRQ_EB11MP_KMI0;
|
||||
kmi1_device.irq[0] = IRQ_EB11MP_KMI1;
|
||||
|
||||
/* platform devices */
|
||||
realview_eb_smc91x_resources[1].start = IRQ_EB11MP_ETH;
|
||||
realview_eb_smc91x_resources[1].end = IRQ_EB11MP_ETH;
|
||||
}
|
||||
|
||||
static void __init realview_eb_timer_init(void)
|
||||
{
|
||||
unsigned int timer_irq;
|
||||
|
||||
if (core_tile_eb11mp()) {
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
|
||||
twd_size = REALVIEW_EB11MP_TWD_SIZE;
|
||||
#endif
|
||||
timer_irq = IRQ_EB11MP_TIMER0_1;
|
||||
} else
|
||||
timer_irq = IRQ_EB_TIMER0_1;
|
||||
|
||||
realview_timer_init(timer_irq);
|
||||
}
|
||||
|
||||
static struct sys_timer realview_eb_timer = {
|
||||
.init = realview_eb_timer_init,
|
||||
};
|
||||
|
||||
static void __init realview_eb_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_REALVIEW_MPCORE
|
||||
/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
|
||||
* Bits: .... ...0 0111 1001 0000 .... .... .... */
|
||||
l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
|
||||
#endif
|
||||
if (core_tile_eb11mp()) {
|
||||
realview_eb11mp_fixup();
|
||||
|
||||
/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
|
||||
* Bits: .... ...0 0111 1001 0000 .... .... .... */
|
||||
l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
|
||||
}
|
||||
|
||||
clk_register(&realview_clcd_clk);
|
||||
|
||||
platform_device_register(&realview_flash_device);
|
||||
platform_device_register(&realview_smc91x_device);
|
||||
platform_device_register(&realview_eb_smc91x_device);
|
||||
platform_device_register(&realview_i2c_device);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
@ -204,6 +360,6 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
|
||||
.boot_params = 0x00000100,
|
||||
.map_io = realview_eb_map_io,
|
||||
.init_irq = gic_init_irq,
|
||||
.timer = &realview_timer,
|
||||
.timer = &realview_eb_timer,
|
||||
.init_machine = realview_eb_init,
|
||||
MACHINE_END
|
||||
|
@ -470,7 +470,7 @@ void __init sa1110_mb_disable(void)
|
||||
* If the system is going to use the SA-1111 DMA engines, set up
|
||||
* the memory bus request/grant pins.
|
||||
*/
|
||||
void __init sa1110_mb_enable(void)
|
||||
void __devinit sa1110_mb_enable(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -57,8 +57,6 @@ unsigned long iop_gettimeoffset(void)
|
||||
static irqreturn_t
|
||||
iop_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
write_tisr(1);
|
||||
|
||||
while ((signed long)(next_jiffy_time - read_tcr1())
|
||||
@ -67,8 +65,6 @@ iop_timer_interrupt(int irq, void *dev_id)
|
||||
next_jiffy_time -= ticks_per_jiffy;
|
||||
}
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -130,9 +130,7 @@ static unsigned long s3c2410_gettimeoffset (void)
|
||||
static irqreturn_t
|
||||
s3c2410_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
timer_tick();
|
||||
write_sequnlock(&xtime_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
|
||||
.socket_suspend = sa1111_pcmcia_socket_suspend,
|
||||
};
|
||||
|
||||
int __init pcmcia_jornada720_init(struct device *dev)
|
||||
int __devinit pcmcia_jornada720_init(struct device *dev)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
|
@ -237,6 +237,12 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
if (port->info && port->info->tty) {
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
unsigned int b = port->uartclk / (16 * quot);
|
||||
tty_encode_baud_rate(tty, b, b);
|
||||
}
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
h_lcr = 0x00;
|
||||
@ -277,8 +283,6 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
|
||||
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
|
||||
/*
|
||||
* Which character status flags should we ignore?
|
||||
*/
|
||||
|
@ -28,4 +28,19 @@ extern unsigned int processor_id;
|
||||
#define cpu_is_ixp46x() ((processor_id & IXP4XX_PROCESSOR_ID_MASK) == \
|
||||
IXP465_PROCESSOR_ID_VALUE)
|
||||
|
||||
static inline u32 ixp4xx_read_feature_bits(void)
|
||||
{
|
||||
unsigned int val = ~*IXP4XX_EXP_CFG2;
|
||||
val &= ~IXP4XX_FEATURE_RESERVED;
|
||||
if (!cpu_is_ixp46x())
|
||||
val &= ~IXP4XX_FEATURE_IXP46X_ONLY;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void ixp4xx_write_feature_bits(u32 value)
|
||||
{
|
||||
*IXP4XX_EXP_CFG2 = ~value;
|
||||
}
|
||||
|
||||
#endif /* _ASM_ARCH_CPU_H */
|
||||
|
@ -40,18 +40,13 @@
|
||||
/* Buttons */
|
||||
|
||||
#define DSMG600_PB_GPIO 15 /* power button */
|
||||
#define DSMG600_PB_BM (1L << DSMG600_PB_GPIO)
|
||||
|
||||
#define DSMG600_RB_GPIO 3 /* reset button */
|
||||
|
||||
#define DSMG600_RB_IRQ IRQ_IXP4XX_GPIO3
|
||||
/* Power control */
|
||||
|
||||
#define DSMG600_PO_GPIO 2 /* power off */
|
||||
|
||||
/* LEDs */
|
||||
|
||||
#define DSMG600_LED_PWR_GPIO 0
|
||||
#define DSMG600_LED_PWR_BM (1L << DSMG600_LED_PWR_GPIO)
|
||||
|
||||
#define DSMG600_LED_WLAN_GPIO 14
|
||||
#define DSMG600_LED_WLAN_BM (1L << DSMG600_LED_WLAN_GPIO)
|
||||
|
@ -27,13 +27,13 @@
|
||||
|
||||
#define pcibios_assign_all_busses() 1
|
||||
|
||||
/* Register locations and bits */
|
||||
#include "ixp4xx-regs.h"
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <asm/arch/cpu.h>
|
||||
#endif
|
||||
|
||||
/* Register locations and bits */
|
||||
#include "ixp4xx-regs.h"
|
||||
|
||||
/* Platform helper functions and definitions */
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
#ifndef __ASM_ARM_ARCH_IO_H
|
||||
#define __ASM_ARM_ARCH_IO_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#define IO_SPACE_LIMIT 0xffff0000
|
||||
|
@ -15,10 +15,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_HARDWARE_H__
|
||||
#error "Do not include this directly, instead #include <asm/hardware.h>"
|
||||
#endif
|
||||
|
||||
#ifndef _ASM_ARM_IXP4XX_H_
|
||||
#define _ASM_ARM_IXP4XX_H_
|
||||
|
||||
@ -607,4 +603,36 @@
|
||||
|
||||
#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */
|
||||
|
||||
/* "fuse" bits of IXP_EXP_CFG2 */
|
||||
#define IXP4XX_FEATURE_RCOMP (1 << 0)
|
||||
#define IXP4XX_FEATURE_USB_DEVICE (1 << 1)
|
||||
#define IXP4XX_FEATURE_HASH (1 << 2)
|
||||
#define IXP4XX_FEATURE_AES (1 << 3)
|
||||
#define IXP4XX_FEATURE_DES (1 << 4)
|
||||
#define IXP4XX_FEATURE_HDLC (1 << 5)
|
||||
#define IXP4XX_FEATURE_AAL (1 << 6)
|
||||
#define IXP4XX_FEATURE_HSS (1 << 7)
|
||||
#define IXP4XX_FEATURE_UTOPIA (1 << 8)
|
||||
#define IXP4XX_FEATURE_NPEB_ETH0 (1 << 9)
|
||||
#define IXP4XX_FEATURE_NPEC_ETH (1 << 10)
|
||||
#define IXP4XX_FEATURE_RESET_NPEA (1 << 11)
|
||||
#define IXP4XX_FEATURE_RESET_NPEB (1 << 12)
|
||||
#define IXP4XX_FEATURE_RESET_NPEC (1 << 13)
|
||||
#define IXP4XX_FEATURE_PCI (1 << 14)
|
||||
#define IXP4XX_FEATURE_ECC_TIMESYNC (1 << 15)
|
||||
#define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT (3 << 16)
|
||||
#define IXP4XX_FEATURE_USB_HOST (1 << 18)
|
||||
#define IXP4XX_FEATURE_NPEA_ETH (1 << 19)
|
||||
#define IXP4XX_FEATURE_NPEB_ETH_1_TO_3 (1 << 20)
|
||||
#define IXP4XX_FEATURE_RSA (1 << 21)
|
||||
#define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22)
|
||||
#define IXP4XX_FEATURE_RESERVED (0xFF << 24)
|
||||
|
||||
#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_ECC_TIMESYNC | \
|
||||
IXP4XX_FEATURE_USB_HOST | \
|
||||
IXP4XX_FEATURE_NPEA_ETH | \
|
||||
IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \
|
||||
IXP4XX_FEATURE_RSA | \
|
||||
IXP4XX_FEATURE_XSCALE_MAX_FREQ)
|
||||
|
||||
#endif
|
||||
|
@ -38,15 +38,15 @@
|
||||
|
||||
/* Buttons */
|
||||
|
||||
#define NAS100D_PB_GPIO 14
|
||||
#define NAS100D_RB_GPIO 4
|
||||
#define NAS100D_PB_GPIO 14 /* power button */
|
||||
#define NAS100D_RB_GPIO 4 /* reset button */
|
||||
|
||||
/* Power control */
|
||||
|
||||
#define NAS100D_PO_GPIO 12 /* power off */
|
||||
|
||||
#define NAS100D_PB_IRQ IRQ_IXP4XX_GPIO14
|
||||
#define NAS100D_RB_IRQ IRQ_IXP4XX_GPIO4
|
||||
/* LEDs */
|
||||
|
||||
/*
|
||||
#define NAS100D_PB_BM (1L << NAS100D_PB_GPIO)
|
||||
#define NAS100D_PO_BM (1L << NAS100D_PO_GPIO)
|
||||
#define NAS100D_RB_BM (1L << NAS100D_RB_GPIO)
|
||||
*/
|
||||
#define NAS100D_LED_WLAN_GPIO 0
|
||||
#define NAS100D_LED_DISK_GPIO 3
|
||||
#define NAS100D_LED_PWR_GPIO 15
|
||||
|
39
include/asm-arm/arch-ixp4xx/npe.h
Normal file
39
include/asm-arm/arch-ixp4xx/npe.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef __IXP4XX_NPE_H
|
||||
#define __IXP4XX_NPE_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
extern const char *npe_names[];
|
||||
|
||||
struct npe_regs {
|
||||
u32 exec_addr, exec_data, exec_status_cmd, exec_count;
|
||||
u32 action_points[4];
|
||||
u32 watchpoint_fifo, watch_count;
|
||||
u32 profile_count;
|
||||
u32 messaging_status, messaging_control;
|
||||
u32 mailbox_status, /*messaging_*/ in_out_fifo;
|
||||
};
|
||||
|
||||
struct npe {
|
||||
struct resource *mem_res;
|
||||
struct npe_regs __iomem *regs;
|
||||
u32 regs_phys;
|
||||
int id;
|
||||
int valid;
|
||||
};
|
||||
|
||||
|
||||
static inline const char *npe_name(struct npe *npe)
|
||||
{
|
||||
return npe_names[npe->id];
|
||||
}
|
||||
|
||||
int npe_running(struct npe *npe);
|
||||
int npe_send_message(struct npe *npe, const void *msg, const char *what);
|
||||
int npe_recv_message(struct npe *npe, void *msg, const char *what);
|
||||
int npe_send_recv_message(struct npe *npe, void *msg, const char *what);
|
||||
int npe_load_firmware(struct npe *npe, const char *name, struct device *dev);
|
||||
struct npe *npe_request(int id);
|
||||
void npe_release(struct npe *npe);
|
||||
|
||||
#endif /* __IXP4XX_NPE_H */
|
@ -39,34 +39,17 @@
|
||||
|
||||
/* Buttons */
|
||||
|
||||
#define NSLU2_PB_GPIO 5
|
||||
#define NSLU2_PB_GPIO 5 /* power button */
|
||||
#define NSLU2_PO_GPIO 8 /* power off */
|
||||
#define NSLU2_RB_GPIO 12
|
||||
|
||||
#define NSLU2_PB_IRQ IRQ_IXP4XX_GPIO5
|
||||
#define NSLU2_RB_IRQ IRQ_IXP4XX_GPIO12
|
||||
|
||||
#define NSLU2_PB_BM (1L << NSLU2_PB_GPIO)
|
||||
#define NSLU2_PO_BM (1L << NSLU2_PO_GPIO)
|
||||
#define NSLU2_RB_BM (1L << NSLU2_RB_GPIO)
|
||||
#define NSLU2_RB_GPIO 12 /* reset button */
|
||||
|
||||
/* Buzzer */
|
||||
|
||||
#define NSLU2_GPIO_BUZZ 4
|
||||
#define NSLU2_BZ_BM (1L << NSLU2_GPIO_BUZZ)
|
||||
|
||||
/* LEDs */
|
||||
|
||||
#define NSLU2_LED_RED_GPIO 0
|
||||
#define NSLU2_LED_GRN_GPIO 1
|
||||
|
||||
#define NSLU2_LED_RED_BM (1L << NSLU2_LED_RED_GPIO)
|
||||
#define NSLU2_LED_GRN_BM (1L << NSLU2_LED_GRN_GPIO)
|
||||
|
||||
#define NSLU2_LED_DISK1_GPIO 3
|
||||
#define NSLU2_LED_DISK2_GPIO 2
|
||||
|
||||
#define NSLU2_LED_DISK1_BM (1L << NSLU2_LED_DISK1_GPIO)
|
||||
#define NSLU2_LED_DISK2_BM (1L << NSLU2_LED_DISK2_GPIO)
|
||||
|
||||
|
||||
|
@ -91,6 +91,27 @@ struct ixp4xx_pata_data {
|
||||
|
||||
struct sys_timer;
|
||||
|
||||
#define IXP4XX_ETH_NPEA 0x00
|
||||
#define IXP4XX_ETH_NPEB 0x10
|
||||
#define IXP4XX_ETH_NPEC 0x20
|
||||
|
||||
/* Information about built-in Ethernet MAC interfaces */
|
||||
struct eth_plat_info {
|
||||
u8 phy; /* MII PHY ID, 0 - 31 */
|
||||
u8 rxq; /* configurable, currently 0 - 31 only */
|
||||
u8 txreadyq;
|
||||
u8 hwaddr[6];
|
||||
};
|
||||
|
||||
/* Information about built-in HSS (synchronous serial) interfaces */
|
||||
struct hss_plat_info {
|
||||
int (*set_clock)(int port, unsigned int clock_type);
|
||||
int (*open)(int port, void *pdev,
|
||||
void (*set_carrier_cb)(void *pdev, int carrier));
|
||||
void (*close)(int port, void *pdev);
|
||||
u8 txreadyq;
|
||||
};
|
||||
|
||||
/*
|
||||
* Frequency of clock used for primary clocksource
|
||||
*/
|
||||
|
126
include/asm-arm/arch-ixp4xx/qmgr.h
Normal file
126
include/asm-arm/arch-ixp4xx/qmgr.h
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef IXP4XX_QMGR_H
|
||||
#define IXP4XX_QMGR_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define HALF_QUEUES 32
|
||||
#define QUEUES 64 /* only 32 lower queues currently supported */
|
||||
#define MAX_QUEUE_LENGTH 4 /* in dwords */
|
||||
|
||||
#define QUEUE_STAT1_EMPTY 1 /* queue status bits */
|
||||
#define QUEUE_STAT1_NEARLY_EMPTY 2
|
||||
#define QUEUE_STAT1_NEARLY_FULL 4
|
||||
#define QUEUE_STAT1_FULL 8
|
||||
#define QUEUE_STAT2_UNDERFLOW 1
|
||||
#define QUEUE_STAT2_OVERFLOW 2
|
||||
|
||||
#define QUEUE_WATERMARK_0_ENTRIES 0
|
||||
#define QUEUE_WATERMARK_1_ENTRY 1
|
||||
#define QUEUE_WATERMARK_2_ENTRIES 2
|
||||
#define QUEUE_WATERMARK_4_ENTRIES 3
|
||||
#define QUEUE_WATERMARK_8_ENTRIES 4
|
||||
#define QUEUE_WATERMARK_16_ENTRIES 5
|
||||
#define QUEUE_WATERMARK_32_ENTRIES 6
|
||||
#define QUEUE_WATERMARK_64_ENTRIES 7
|
||||
|
||||
/* queue interrupt request conditions */
|
||||
#define QUEUE_IRQ_SRC_EMPTY 0
|
||||
#define QUEUE_IRQ_SRC_NEARLY_EMPTY 1
|
||||
#define QUEUE_IRQ_SRC_NEARLY_FULL 2
|
||||
#define QUEUE_IRQ_SRC_FULL 3
|
||||
#define QUEUE_IRQ_SRC_NOT_EMPTY 4
|
||||
#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5
|
||||
#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL 6
|
||||
#define QUEUE_IRQ_SRC_NOT_FULL 7
|
||||
|
||||
struct qmgr_regs {
|
||||
u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */
|
||||
u32 stat1[4]; /* 0x400 - 0x40F */
|
||||
u32 stat2[2]; /* 0x410 - 0x417 */
|
||||
u32 statne_h; /* 0x418 - queue nearly empty */
|
||||
u32 statf_h; /* 0x41C - queue full */
|
||||
u32 irqsrc[4]; /* 0x420 - 0x42F IRC source */
|
||||
u32 irqen[2]; /* 0x430 - 0x437 IRQ enabled */
|
||||
u32 irqstat[2]; /* 0x438 - 0x43F - IRQ access only */
|
||||
u32 reserved[1776];
|
||||
u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */
|
||||
};
|
||||
|
||||
void qmgr_set_irq(unsigned int queue, int src,
|
||||
void (*handler)(void *pdev), void *pdev);
|
||||
void qmgr_enable_irq(unsigned int queue);
|
||||
void qmgr_disable_irq(unsigned int queue);
|
||||
|
||||
/* request_ and release_queue() must be called from non-IRQ context */
|
||||
int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
|
||||
unsigned int nearly_empty_watermark,
|
||||
unsigned int nearly_full_watermark);
|
||||
void qmgr_release_queue(unsigned int queue);
|
||||
|
||||
|
||||
static inline void qmgr_put_entry(unsigned int queue, u32 val)
|
||||
{
|
||||
extern struct qmgr_regs __iomem *qmgr_regs;
|
||||
__raw_writel(val, &qmgr_regs->acc[queue][0]);
|
||||
}
|
||||
|
||||
static inline u32 qmgr_get_entry(unsigned int queue)
|
||||
{
|
||||
extern struct qmgr_regs __iomem *qmgr_regs;
|
||||
return __raw_readl(&qmgr_regs->acc[queue][0]);
|
||||
}
|
||||
|
||||
static inline int qmgr_get_stat1(unsigned int queue)
|
||||
{
|
||||
extern struct qmgr_regs __iomem *qmgr_regs;
|
||||
return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
|
||||
>> ((queue & 7) << 2)) & 0xF;
|
||||
}
|
||||
|
||||
static inline int qmgr_get_stat2(unsigned int queue)
|
||||
{
|
||||
extern struct qmgr_regs __iomem *qmgr_regs;
|
||||
return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
|
||||
>> ((queue & 0xF) << 1)) & 0x3;
|
||||
}
|
||||
|
||||
static inline int qmgr_stat_empty(unsigned int queue)
|
||||
{
|
||||
return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY);
|
||||
}
|
||||
|
||||
static inline int qmgr_stat_nearly_empty(unsigned int queue)
|
||||
{
|
||||
return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY);
|
||||
}
|
||||
|
||||
static inline int qmgr_stat_nearly_full(unsigned int queue)
|
||||
{
|
||||
return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL);
|
||||
}
|
||||
|
||||
static inline int qmgr_stat_full(unsigned int queue)
|
||||
{
|
||||
return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_FULL);
|
||||
}
|
||||
|
||||
static inline int qmgr_stat_underflow(unsigned int queue)
|
||||
{
|
||||
return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW);
|
||||
}
|
||||
|
||||
static inline int qmgr_stat_overflow(unsigned int queue)
|
||||
{
|
||||
return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW);
|
||||
}
|
||||
|
||||
#endif
|
@ -13,7 +13,7 @@
|
||||
#ifndef _ARCH_UNCOMPRESS_H_
|
||||
#define _ARCH_UNCOMPRESS_H_
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include "ixp4xx-regs.h"
|
||||
#include <asm/mach-types.h>
|
||||
#include <linux/serial_reg.h>
|
||||
|
||||
|
@ -12,6 +12,19 @@
|
||||
|
||||
#ifndef __ASM_ARCH_PXA3XX_REGS_H
|
||||
#define __ASM_ARCH_PXA3XX_REGS_H
|
||||
/*
|
||||
* Service Power Management Unit (MPMU)
|
||||
*/
|
||||
#define PMCR __REG(0x40F50000) /* Power Manager Control Register */
|
||||
#define PSR __REG(0x40F50004) /* Power Manager S2 Status Register */
|
||||
#define PSPR __REG(0x40F50008) /* Power Manager Scratch Pad Register */
|
||||
#define PCFR __REG(0x40F5000C) /* Power Manager General Configuration Register */
|
||||
#define PWER __REG(0x40F50010) /* Power Manager Wake-up Enable Register */
|
||||
#define PWSR __REG(0x40F50014) /* Power Manager Wake-up Status Register */
|
||||
#define PECR __REG(0x40F50018) /* Power Manager EXT_WAKEUP[1:0] Control Register */
|
||||
#define DCDCSR __REG(0x40F50080) /* DC-DC Controller Status Register */
|
||||
#define PVCR __REG(0x40F50100) /* Power Manager Voltage Change Control Register */
|
||||
#define PCMD(x) __REG(0x40F50110 + ((x) << 2))
|
||||
|
||||
/*
|
||||
* Slave Power Managment Unit
|
||||
|
171
include/asm-arm/arch-realview/board-eb.h
Normal file
171
include/asm-arm/arch-realview/board-eb.h
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* include/asm-arm/arch-realview/board-eb.h
|
||||
*
|
||||
* Copyright (C) 2007 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_BOARD_EB_H
|
||||
#define __ASM_ARCH_BOARD_EB_H
|
||||
|
||||
#include <asm/arch/platform.h>
|
||||
|
||||
/*
|
||||
* RealView EB + ARM11MPCore peripheral addresses
|
||||
*/
|
||||
#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
|
||||
#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */
|
||||
#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
|
||||
#define REALVIEW_EB11MP_TWD_BASE 0x10100700
|
||||
#define REALVIEW_EB11MP_TWD_SIZE 0x00000100
|
||||
#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
|
||||
#define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */
|
||||
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
|
||||
#else
|
||||
#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */
|
||||
#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
|
||||
#define REALVIEW_EB11MP_TWD_BASE 0x1F000700
|
||||
#define REALVIEW_EB11MP_TWD_SIZE 0x00000100
|
||||
#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
|
||||
#define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */
|
||||
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
|
||||
#endif
|
||||
|
||||
#define IRQ_EB_GIC_START 32
|
||||
|
||||
/*
|
||||
* RealView EB interrupt sources
|
||||
*/
|
||||
#define IRQ_EB_WDOG (IRQ_EB_GIC_START + 0) /* Watchdog timer */
|
||||
#define IRQ_EB_SOFT (IRQ_EB_GIC_START + 1) /* Software interrupt */
|
||||
#define IRQ_EB_COMMRx (IRQ_EB_GIC_START + 2) /* Debug Comm Rx interrupt */
|
||||
#define IRQ_EB_COMMTx (IRQ_EB_GIC_START + 3) /* Debug Comm Tx interrupt */
|
||||
#define IRQ_EB_TIMER0_1 (IRQ_EB_GIC_START + 4) /* Timer 0 and 1 */
|
||||
#define IRQ_EB_TIMER2_3 (IRQ_EB_GIC_START + 5) /* Timer 2 and 3 */
|
||||
#define IRQ_EB_GPIO0 (IRQ_EB_GIC_START + 6) /* GPIO 0 */
|
||||
#define IRQ_EB_GPIO1 (IRQ_EB_GIC_START + 7) /* GPIO 1 */
|
||||
#define IRQ_EB_GPIO2 (IRQ_EB_GIC_START + 8) /* GPIO 2 */
|
||||
/* 9 reserved */
|
||||
#define IRQ_EB_RTC (IRQ_EB_GIC_START + 10) /* Real Time Clock */
|
||||
#define IRQ_EB_SSP (IRQ_EB_GIC_START + 11) /* Synchronous Serial Port */
|
||||
#define IRQ_EB_UART0 (IRQ_EB_GIC_START + 12) /* UART 0 on development chip */
|
||||
#define IRQ_EB_UART1 (IRQ_EB_GIC_START + 13) /* UART 1 on development chip */
|
||||
#define IRQ_EB_UART2 (IRQ_EB_GIC_START + 14) /* UART 2 on development chip */
|
||||
#define IRQ_EB_UART3 (IRQ_EB_GIC_START + 15) /* UART 3 on development chip */
|
||||
#define IRQ_EB_SCI (IRQ_EB_GIC_START + 16) /* Smart Card Interface */
|
||||
#define IRQ_EB_MMCI0A (IRQ_EB_GIC_START + 17) /* Multimedia Card 0A */
|
||||
#define IRQ_EB_MMCI0B (IRQ_EB_GIC_START + 18) /* Multimedia Card 0B */
|
||||
#define IRQ_EB_AACI (IRQ_EB_GIC_START + 19) /* Audio Codec */
|
||||
#define IRQ_EB_KMI0 (IRQ_EB_GIC_START + 20) /* Keyboard/Mouse port 0 */
|
||||
#define IRQ_EB_KMI1 (IRQ_EB_GIC_START + 21) /* Keyboard/Mouse port 1 */
|
||||
#define IRQ_EB_CHARLCD (IRQ_EB_GIC_START + 22) /* Character LCD */
|
||||
#define IRQ_EB_CLCD (IRQ_EB_GIC_START + 23) /* CLCD controller */
|
||||
#define IRQ_EB_DMA (IRQ_EB_GIC_START + 24) /* DMA controller */
|
||||
#define IRQ_EB_PWRFAIL (IRQ_EB_GIC_START + 25) /* Power failure */
|
||||
#define IRQ_EB_PISMO (IRQ_EB_GIC_START + 26) /* PISMO interface */
|
||||
#define IRQ_EB_DoC (IRQ_EB_GIC_START + 27) /* Disk on Chip memory controller */
|
||||
#define IRQ_EB_ETH (IRQ_EB_GIC_START + 28) /* Ethernet controller */
|
||||
#define IRQ_EB_USB (IRQ_EB_GIC_START + 29) /* USB controller */
|
||||
#define IRQ_EB_TSPEN (IRQ_EB_GIC_START + 30) /* Touchscreen pen */
|
||||
#define IRQ_EB_TSKPAD (IRQ_EB_GIC_START + 31) /* Touchscreen keypad */
|
||||
|
||||
/*
|
||||
* RealView EB + ARM11MPCore interrupt sources (primary GIC on the core tile)
|
||||
*/
|
||||
#define IRQ_EB11MP_AACI (IRQ_EB_GIC_START + 0)
|
||||
#define IRQ_EB11MP_TIMER0_1 (IRQ_EB_GIC_START + 1)
|
||||
#define IRQ_EB11MP_TIMER2_3 (IRQ_EB_GIC_START + 2)
|
||||
#define IRQ_EB11MP_USB (IRQ_EB_GIC_START + 3)
|
||||
#define IRQ_EB11MP_UART0 (IRQ_EB_GIC_START + 4)
|
||||
#define IRQ_EB11MP_UART1 (IRQ_EB_GIC_START + 5)
|
||||
#define IRQ_EB11MP_RTC (IRQ_EB_GIC_START + 6)
|
||||
#define IRQ_EB11MP_KMI0 (IRQ_EB_GIC_START + 7)
|
||||
#define IRQ_EB11MP_KMI1 (IRQ_EB_GIC_START + 8)
|
||||
#define IRQ_EB11MP_ETH (IRQ_EB_GIC_START + 9)
|
||||
#define IRQ_EB11MP_EB_IRQ1 (IRQ_EB_GIC_START + 10) /* main GIC */
|
||||
#define IRQ_EB11MP_EB_IRQ2 (IRQ_EB_GIC_START + 11) /* tile GIC */
|
||||
#define IRQ_EB11MP_EB_FIQ1 (IRQ_EB_GIC_START + 12) /* main GIC */
|
||||
#define IRQ_EB11MP_EB_FIQ2 (IRQ_EB_GIC_START + 13) /* tile GIC */
|
||||
#define IRQ_EB11MP_MMCI0A (IRQ_EB_GIC_START + 14)
|
||||
#define IRQ_EB11MP_MMCI0B (IRQ_EB_GIC_START + 15)
|
||||
|
||||
#define IRQ_EB11MP_PMU_CPU0 (IRQ_EB_GIC_START + 17)
|
||||
#define IRQ_EB11MP_PMU_CPU1 (IRQ_EB_GIC_START + 18)
|
||||
#define IRQ_EB11MP_PMU_CPU2 (IRQ_EB_GIC_START + 19)
|
||||
#define IRQ_EB11MP_PMU_CPU3 (IRQ_EB_GIC_START + 20)
|
||||
#define IRQ_EB11MP_PMU_SCU0 (IRQ_EB_GIC_START + 21)
|
||||
#define IRQ_EB11MP_PMU_SCU1 (IRQ_EB_GIC_START + 22)
|
||||
#define IRQ_EB11MP_PMU_SCU2 (IRQ_EB_GIC_START + 23)
|
||||
#define IRQ_EB11MP_PMU_SCU3 (IRQ_EB_GIC_START + 24)
|
||||
#define IRQ_EB11MP_PMU_SCU4 (IRQ_EB_GIC_START + 25)
|
||||
#define IRQ_EB11MP_PMU_SCU5 (IRQ_EB_GIC_START + 26)
|
||||
#define IRQ_EB11MP_PMU_SCU6 (IRQ_EB_GIC_START + 27)
|
||||
#define IRQ_EB11MP_PMU_SCU7 (IRQ_EB_GIC_START + 28)
|
||||
|
||||
#define IRQ_EB11MP_L220_EVENT (IRQ_EB_GIC_START + 29)
|
||||
#define IRQ_EB11MP_L220_SLAVE (IRQ_EB_GIC_START + 30)
|
||||
#define IRQ_EB11MP_L220_DECODE (IRQ_EB_GIC_START + 31)
|
||||
|
||||
#define IRQ_EB11MP_UART2 -1
|
||||
#define IRQ_EB11MP_UART3 -1
|
||||
#define IRQ_EB11MP_CLCD -1
|
||||
#define IRQ_EB11MP_DMA -1
|
||||
#define IRQ_EB11MP_WDOG -1
|
||||
#define IRQ_EB11MP_GPIO0 -1
|
||||
#define IRQ_EB11MP_GPIO1 -1
|
||||
#define IRQ_EB11MP_GPIO2 -1
|
||||
#define IRQ_EB11MP_SCI -1
|
||||
#define IRQ_EB11MP_SSP -1
|
||||
|
||||
#define NR_GIC_EB11MP 2
|
||||
|
||||
/*
|
||||
* Only define NR_IRQS if less than NR_IRQS_EB
|
||||
*/
|
||||
#define NR_IRQS_EB (IRQ_EB_GIC_START + 96)
|
||||
|
||||
#if defined(CONFIG_MACH_REALVIEW_EB) \
|
||||
&& (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
|
||||
#undef NR_IRQS
|
||||
#define NR_IRQS NR_IRQS_EB
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_REALVIEW_EB_ARM11MP) \
|
||||
&& (!defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_EB11MP))
|
||||
#undef MAX_GIC_NR
|
||||
#define MAX_GIC_NR NR_GIC_EB11MP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Core tile identification (REALVIEW_SYS_PROCID)
|
||||
*/
|
||||
#define REALVIEW_EB_PROC_MASK 0xFF000000
|
||||
#define REALVIEW_EB_PROC_ARM7TDMI 0x00000000
|
||||
#define REALVIEW_EB_PROC_ARM9 0x02000000
|
||||
#define REALVIEW_EB_PROC_ARM11 0x04000000
|
||||
#define REALVIEW_EB_PROC_ARM11MP 0x06000000
|
||||
|
||||
#define check_eb_proc(proc_type) \
|
||||
((readl(__io_address(REALVIEW_SYS_PROCID)) & REALVIEW_EB_PROC_MASK) \
|
||||
== proc_type)
|
||||
|
||||
#ifdef CONFIG_REALVIEW_EB_ARM11MP
|
||||
#define core_tile_eb11mp() check_eb_proc(REALVIEW_EB_PROC_ARM11MP)
|
||||
#else
|
||||
#define core_tile_eb11mp() 0
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_ARCH_BOARD_EB_H */
|
@ -14,7 +14,8 @@
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =IO_ADDRESS(REALVIEW_GIC_CPU_BASE)
|
||||
ldr \base, =gic_cpu_base_addr
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
|
@ -23,7 +23,6 @@
|
||||
#define __ASM_ARCH_HARDWARE_H
|
||||
|
||||
#include <asm/sizes.h>
|
||||
#include <asm/arch/platform.h>
|
||||
|
||||
/* macro to get at IO space when running virtually */
|
||||
#define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
|
||||
|
@ -19,103 +19,18 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <asm/arch/platform.h>
|
||||
#ifndef __ASM_ARCH_IRQS_H
|
||||
#define __ASM_ARCH_IRQS_H
|
||||
|
||||
#define IRQ_LOCALTIMER 29
|
||||
#define IRQ_LOCALWDOG 30
|
||||
#include <asm/arch/board-eb.h>
|
||||
|
||||
#define IRQ_LOCALTIMER 29
|
||||
#define IRQ_LOCALWDOG 30
|
||||
|
||||
/*
|
||||
* IRQ interrupts definitions are the same the INT definitions
|
||||
* held within platform.h
|
||||
*/
|
||||
#define IRQ_GIC_START 32
|
||||
#define IRQ_WDOGINT (IRQ_GIC_START + INT_WDOGINT)
|
||||
#define IRQ_SOFTINT (IRQ_GIC_START + INT_SOFTINT)
|
||||
#define IRQ_COMMRx (IRQ_GIC_START + INT_COMMRx)
|
||||
#define IRQ_COMMTx (IRQ_GIC_START + INT_COMMTx)
|
||||
#define IRQ_TIMERINT0_1 (IRQ_GIC_START + INT_TIMERINT0_1)
|
||||
#define IRQ_TIMERINT2_3 (IRQ_GIC_START + INT_TIMERINT2_3)
|
||||
#define IRQ_GPIOINT0 (IRQ_GIC_START + INT_GPIOINT0)
|
||||
#define IRQ_GPIOINT1 (IRQ_GIC_START + INT_GPIOINT1)
|
||||
#define IRQ_GPIOINT2 (IRQ_GIC_START + INT_GPIOINT2)
|
||||
#define IRQ_GPIOINT3 (IRQ_GIC_START + INT_GPIOINT3)
|
||||
#define IRQ_RTCINT (IRQ_GIC_START + INT_RTCINT)
|
||||
#define IRQ_SSPINT (IRQ_GIC_START + INT_SSPINT)
|
||||
#define IRQ_UARTINT0 (IRQ_GIC_START + INT_UARTINT0)
|
||||
#define IRQ_UARTINT1 (IRQ_GIC_START + INT_UARTINT1)
|
||||
#define IRQ_UARTINT2 (IRQ_GIC_START + INT_UARTINT2)
|
||||
#define IRQ_UART3 (IRQ_GIC_START + INT_UARTINT3)
|
||||
#define IRQ_SCIINT (IRQ_GIC_START + INT_SCIINT)
|
||||
#define IRQ_CLCDINT (IRQ_GIC_START + INT_CLCDINT)
|
||||
#define IRQ_DMAINT (IRQ_GIC_START + INT_DMAINT)
|
||||
#define IRQ_PWRFAILINT (IRQ_GIC_START + INT_PWRFAILINT)
|
||||
#define IRQ_MBXINT (IRQ_GIC_START + INT_MBXINT)
|
||||
#define IRQ_GNDINT (IRQ_GIC_START + INT_GNDINT)
|
||||
#define IRQ_MMCI0B (IRQ_GIC_START + INT_MMCI0B)
|
||||
#define IRQ_MMCI1B (IRQ_GIC_START + INT_MMCI1B)
|
||||
#define IRQ_KMI0 (IRQ_GIC_START + INT_KMI0)
|
||||
#define IRQ_KMI1 (IRQ_GIC_START + INT_KMI1)
|
||||
#define IRQ_SCI3 (IRQ_GIC_START + INT_SCI3)
|
||||
#define IRQ_CLCD (IRQ_GIC_START + INT_CLCD)
|
||||
#define IRQ_TOUCH (IRQ_GIC_START + INT_TOUCH)
|
||||
#define IRQ_KEYPAD (IRQ_GIC_START + INT_KEYPAD)
|
||||
#define IRQ_DoC (IRQ_GIC_START + INT_DoC)
|
||||
#define IRQ_MMCI0A (IRQ_GIC_START + INT_MMCI0A)
|
||||
#define IRQ_MMCI1A (IRQ_GIC_START + INT_MMCI1A)
|
||||
#define IRQ_AACI (IRQ_GIC_START + INT_AACI)
|
||||
#define IRQ_ETH (IRQ_GIC_START + INT_ETH)
|
||||
#define IRQ_USB (IRQ_GIC_START + INT_USB)
|
||||
#define IRQ_PMU_CPU0 (IRQ_GIC_START + INT_PMU_CPU0)
|
||||
#define IRQ_PMU_CPU1 (IRQ_GIC_START + INT_PMU_CPU1)
|
||||
#define IRQ_PMU_CPU2 (IRQ_GIC_START + INT_PMU_CPU2)
|
||||
#define IRQ_PMU_CPU3 (IRQ_GIC_START + INT_PMU_CPU3)
|
||||
#define IRQ_PMU_SCU0 (IRQ_GIC_START + INT_PMU_SCU0)
|
||||
#define IRQ_PMU_SCU1 (IRQ_GIC_START + INT_PMU_SCU1)
|
||||
#define IRQ_PMU_SCU2 (IRQ_GIC_START + INT_PMU_SCU2)
|
||||
#define IRQ_PMU_SCU3 (IRQ_GIC_START + INT_PMU_SCU3)
|
||||
#define IRQ_PMU_SCU4 (IRQ_GIC_START + INT_PMU_SCU4)
|
||||
#define IRQ_PMU_SCU5 (IRQ_GIC_START + INT_PMU_SCU5)
|
||||
#define IRQ_PMU_SCU6 (IRQ_GIC_START + INT_PMU_SCU6)
|
||||
#define IRQ_PMU_SCU7 (IRQ_GIC_START + INT_PMU_SCU7)
|
||||
|
||||
#define IRQ_EB_IRQ1 (IRQ_GIC_START + INT_EB_IRQ1)
|
||||
#define IRQ_EB_IRQ2 (IRQ_GIC_START + INT_EB_IRQ2)
|
||||
#ifndef NR_IRQS
|
||||
#error "NR_IRQS not defined by the board-specific files"
|
||||
#endif
|
||||
|
||||
#define IRQMASK_WDOGINT INTMASK_WDOGINT
|
||||
#define IRQMASK_SOFTINT INTMASK_SOFTINT
|
||||
#define IRQMASK_COMMRx INTMASK_COMMRx
|
||||
#define IRQMASK_COMMTx INTMASK_COMMTx
|
||||
#define IRQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1
|
||||
#define IRQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3
|
||||
#define IRQMASK_GPIOINT0 INTMASK_GPIOINT0
|
||||
#define IRQMASK_GPIOINT1 INTMASK_GPIOINT1
|
||||
#define IRQMASK_GPIOINT2 INTMASK_GPIOINT2
|
||||
#define IRQMASK_GPIOINT3 INTMASK_GPIOINT3
|
||||
#define IRQMASK_RTCINT INTMASK_RTCINT
|
||||
#define IRQMASK_SSPINT INTMASK_SSPINT
|
||||
#define IRQMASK_UARTINT0 INTMASK_UARTINT0
|
||||
#define IRQMASK_UARTINT1 INTMASK_UARTINT1
|
||||
#define IRQMASK_UARTINT2 INTMASK_UARTINT2
|
||||
#define IRQMASK_SCIINT INTMASK_SCIINT
|
||||
#define IRQMASK_CLCDINT INTMASK_CLCDINT
|
||||
#define IRQMASK_DMAINT INTMASK_DMAINT
|
||||
#define IRQMASK_PWRFAILINT INTMASK_PWRFAILINT
|
||||
#define IRQMASK_MBXINT INTMASK_MBXINT
|
||||
#define IRQMASK_GNDINT INTMASK_GNDINT
|
||||
#define IRQMASK_MMCI0B INTMASK_MMCI0B
|
||||
#define IRQMASK_MMCI1B INTMASK_MMCI1B
|
||||
#define IRQMASK_KMI0 INTMASK_KMI0
|
||||
#define IRQMASK_KMI1 INTMASK_KMI1
|
||||
#define IRQMASK_SCI3 INTMASK_SCI3
|
||||
#define IRQMASK_UART3 INTMASK_UART3
|
||||
#define IRQMASK_CLCD INTMASK_CLCD
|
||||
#define IRQMASK_TOUCH INTMASK_TOUCH
|
||||
#define IRQMASK_KEYPAD INTMASK_KEYPAD
|
||||
#define IRQMASK_DoC INTMASK_DoC
|
||||
#define IRQMASK_MMCI0A INTMASK_MMCI0A
|
||||
#define IRQMASK_MMCI1A INTMASK_MMCI1A
|
||||
#define IRQMASK_AACI INTMASK_AACI
|
||||
#define IRQMASK_ETH INTMASK_ETH
|
||||
#define IRQMASK_USB INTMASK_USB
|
||||
|
||||
#define NR_IRQS (IRQ_GIC_START + 96)
|
||||
#endif
|
||||
|
@ -18,8 +18,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __address_h
|
||||
#define __address_h 1
|
||||
#ifndef __ASM_ARCH_PLATFORM_H
|
||||
#define __ASM_ARCH_PLATFORM_H
|
||||
|
||||
/*
|
||||
* Memory definitions
|
||||
@ -81,11 +81,12 @@
|
||||
#define REALVIEW_SYS_24MHz_OFFSET 0x5C
|
||||
#define REALVIEW_SYS_MISC_OFFSET 0x60
|
||||
#define REALVIEW_SYS_IOSEL_OFFSET 0x70
|
||||
#define REALVIEW_SYS_TEST_OSC0_OFFSET 0x80
|
||||
#define REALVIEW_SYS_TEST_OSC1_OFFSET 0x84
|
||||
#define REALVIEW_SYS_TEST_OSC2_OFFSET 0x88
|
||||
#define REALVIEW_SYS_TEST_OSC3_OFFSET 0x8C
|
||||
#define REALVIEW_SYS_TEST_OSC4_OFFSET 0x90
|
||||
#define REALVIEW_SYS_PROCID_OFFSET 0x84
|
||||
#define REALVIEW_SYS_TEST_OSC0_OFFSET 0xC0
|
||||
#define REALVIEW_SYS_TEST_OSC1_OFFSET 0xC4
|
||||
#define REALVIEW_SYS_TEST_OSC2_OFFSET 0xC8
|
||||
#define REALVIEW_SYS_TEST_OSC3_OFFSET 0xCC
|
||||
#define REALVIEW_SYS_TEST_OSC4_OFFSET 0xD0
|
||||
|
||||
#define REALVIEW_SYS_BASE 0x10000000
|
||||
#define REALVIEW_SYS_ID (REALVIEW_SYS_BASE + REALVIEW_SYS_ID_OFFSET)
|
||||
@ -114,6 +115,7 @@
|
||||
#define REALVIEW_SYS_24MHz (REALVIEW_SYS_BASE + REALVIEW_SYS_24MHz_OFFSET)
|
||||
#define REALVIEW_SYS_MISC (REALVIEW_SYS_BASE + REALVIEW_SYS_MISC_OFFSET)
|
||||
#define REALVIEW_SYS_IOSEL (REALVIEW_SYS_BASE + REALVIEW_SYS_IOSEL_OFFSET)
|
||||
#define REALVIEW_SYS_PROCID (REALVIEW_SYS_BASE + REALVIEW_SYS_PROCID_OFFSET)
|
||||
#define REALVIEW_SYS_TEST_OSC0 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC0_OFFSET)
|
||||
#define REALVIEW_SYS_TEST_OSC1 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC1_OFFSET)
|
||||
#define REALVIEW_SYS_TEST_OSC2 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC2_OFFSET)
|
||||
@ -203,30 +205,8 @@
|
||||
/* Reserved 0x1001A000 - 0x1001FFFF */
|
||||
#define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */
|
||||
#define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */
|
||||
#ifndef CONFIG_REALVIEW_MPCORE
|
||||
#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
|
||||
#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
|
||||
#else
|
||||
#ifdef CONFIG_REALVIEW_MPCORE_REVB
|
||||
#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */
|
||||
#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
|
||||
#define REALVIEW_TWD_BASE 0x10100700
|
||||
#define REALVIEW_TWD_SIZE 0x00000100
|
||||
#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
|
||||
#define REALVIEW_MPCORE_L220_BASE 0x10102000 /* L220 registers */
|
||||
#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
|
||||
#else
|
||||
#define REALVIEW_MPCORE_SCU_BASE 0x1F000000 /* SCU registers */
|
||||
#define REALVIEW_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
|
||||
#define REALVIEW_TWD_BASE 0x1F000700
|
||||
#define REALVIEW_TWD_SIZE 0x00000100
|
||||
#define REALVIEW_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
|
||||
#define REALVIEW_MPCORE_L220_BASE 0x1F002000 /* L220 registers */
|
||||
#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
|
||||
#endif
|
||||
#define REALVIEW_GIC1_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
|
||||
#define REALVIEW_GIC1_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
|
||||
#endif
|
||||
#define REALVIEW_SMC_BASE 0x10080000 /* SMC */
|
||||
/* Reserved 0x10090000 - 0x100EFFFF */
|
||||
|
||||
@ -283,134 +263,6 @@
|
||||
#define REALVIEW_INTREG_OFFSET 0x8 /* Interrupt control */
|
||||
#define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Interrupts - bit assignment (primary)
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef CONFIG_REALVIEW_MPCORE
|
||||
#define INT_WDOGINT 0 /* Watchdog timer */
|
||||
#define INT_SOFTINT 1 /* Software interrupt */
|
||||
#define INT_COMMRx 2 /* Debug Comm Rx interrupt */
|
||||
#define INT_COMMTx 3 /* Debug Comm Tx interrupt */
|
||||
#define INT_TIMERINT0_1 4 /* Timer 0 and 1 */
|
||||
#define INT_TIMERINT2_3 5 /* Timer 2 and 3 */
|
||||
#define INT_GPIOINT0 6 /* GPIO 0 */
|
||||
#define INT_GPIOINT1 7 /* GPIO 1 */
|
||||
#define INT_GPIOINT2 8 /* GPIO 2 */
|
||||
/* 9 reserved */
|
||||
#define INT_RTCINT 10 /* Real Time Clock */
|
||||
#define INT_SSPINT 11 /* Synchronous Serial Port */
|
||||
#define INT_UARTINT0 12 /* UART 0 on development chip */
|
||||
#define INT_UARTINT1 13 /* UART 1 on development chip */
|
||||
#define INT_UARTINT2 14 /* UART 2 on development chip */
|
||||
#define INT_UARTINT3 15 /* UART 3 on development chip */
|
||||
#define INT_SCIINT 16 /* Smart Card Interface */
|
||||
#define INT_MMCI0A 17 /* Multimedia Card 0A */
|
||||
#define INT_MMCI0B 18 /* Multimedia Card 0B */
|
||||
#define INT_AACI 19 /* Audio Codec */
|
||||
#define INT_KMI0 20 /* Keyboard/Mouse port 0 */
|
||||
#define INT_KMI1 21 /* Keyboard/Mouse port 1 */
|
||||
#define INT_CHARLCD 22 /* Character LCD */
|
||||
#define INT_CLCDINT 23 /* CLCD controller */
|
||||
#define INT_DMAINT 24 /* DMA controller */
|
||||
#define INT_PWRFAILINT 25 /* Power failure */
|
||||
#define INT_PISMO 26
|
||||
#define INT_DoC 27 /* Disk on Chip memory controller */
|
||||
#define INT_ETH 28 /* Ethernet controller */
|
||||
#define INT_USB 29 /* USB controller */
|
||||
#define INT_TSPENINT 30 /* Touchscreen pen */
|
||||
#define INT_TSKPADINT 31 /* Touchscreen keypad */
|
||||
|
||||
#else
|
||||
|
||||
#define MAX_GIC_NR 2
|
||||
|
||||
#define INT_AACI 0
|
||||
#define INT_TIMERINT0_1 1
|
||||
#define INT_TIMERINT2_3 2
|
||||
#define INT_USB 3
|
||||
#define INT_UARTINT0 4
|
||||
#define INT_UARTINT1 5
|
||||
#define INT_RTCINT 6
|
||||
#define INT_KMI0 7
|
||||
#define INT_KMI1 8
|
||||
#define INT_ETH 9
|
||||
#define INT_EB_IRQ1 10 /* main GIC */
|
||||
#define INT_EB_IRQ2 11 /* tile GIC */
|
||||
#define INT_EB_FIQ1 12 /* main GIC */
|
||||
#define INT_EB_FIQ2 13 /* tile GIC */
|
||||
#define INT_MMCI0A 14
|
||||
#define INT_MMCI0B 15
|
||||
|
||||
#define INT_PMU_CPU0 17
|
||||
#define INT_PMU_CPU1 18
|
||||
#define INT_PMU_CPU2 19
|
||||
#define INT_PMU_CPU3 20
|
||||
#define INT_PMU_SCU0 21
|
||||
#define INT_PMU_SCU1 22
|
||||
#define INT_PMU_SCU2 23
|
||||
#define INT_PMU_SCU3 24
|
||||
#define INT_PMU_SCU4 25
|
||||
#define INT_PMU_SCU5 26
|
||||
#define INT_PMU_SCU6 27
|
||||
#define INT_PMU_SCU7 28
|
||||
|
||||
#define INT_L220_EVENT 29
|
||||
#define INT_L220_SLAVE 30
|
||||
#define INT_L220_DECODE 31
|
||||
|
||||
#define INT_UARTINT2 -1
|
||||
#define INT_UARTINT3 -1
|
||||
#define INT_CLCDINT -1
|
||||
#define INT_DMAINT -1
|
||||
#define INT_WDOGINT -1
|
||||
#define INT_GPIOINT0 -1
|
||||
#define INT_GPIOINT1 -1
|
||||
#define INT_GPIOINT2 -1
|
||||
#define INT_SCIINT -1
|
||||
#define INT_SSPINT -1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interrupt bit positions
|
||||
*
|
||||
*/
|
||||
#define INTMASK_WDOGINT (1 << INT_WDOGINT)
|
||||
#define INTMASK_SOFTINT (1 << INT_SOFTINT)
|
||||
#define INTMASK_COMMRx (1 << INT_COMMRx)
|
||||
#define INTMASK_COMMTx (1 << INT_COMMTx)
|
||||
#define INTMASK_TIMERINT0_1 (1 << INT_TIMERINT0_1)
|
||||
#define INTMASK_TIMERINT2_3 (1 << INT_TIMERINT2_3)
|
||||
#define INTMASK_GPIOINT0 (1 << INT_GPIOINT0)
|
||||
#define INTMASK_GPIOINT1 (1 << INT_GPIOINT1)
|
||||
#define INTMASK_GPIOINT2 (1 << INT_GPIOINT2)
|
||||
#define INTMASK_RTCINT (1 << INT_RTCINT)
|
||||
#define INTMASK_SSPINT (1 << INT_SSPINT)
|
||||
#define INTMASK_UARTINT0 (1 << INT_UARTINT0)
|
||||
#define INTMASK_UARTINT1 (1 << INT_UARTINT1)
|
||||
#define INTMASK_UARTINT2 (1 << INT_UARTINT2)
|
||||
#define INTMASK_UARTINT3 (1 << INT_UARTINT3)
|
||||
#define INTMASK_SCIINT (1 << INT_SCIINT)
|
||||
#define INTMASK_MMCI0A (1 << INT_MMCI0A)
|
||||
#define INTMASK_MMCI0B (1 << INT_MMCI0B)
|
||||
#define INTMASK_AACI (1 << INT_AACI)
|
||||
#define INTMASK_KMI0 (1 << INT_KMI0)
|
||||
#define INTMASK_KMI1 (1 << INT_KMI1)
|
||||
#define INTMASK_CHARLCD (1 << INT_CHARLCD)
|
||||
#define INTMASK_CLCDINT (1 << INT_CLCDINT)
|
||||
#define INTMASK_DMAINT (1 << INT_DMAINT)
|
||||
#define INTMASK_PWRFAILINT (1 << INT_PWRFAILINT)
|
||||
#define INTMASK_PISMO (1 << INT_PISMO)
|
||||
#define INTMASK_DoC (1 << INT_DoC)
|
||||
#define INTMASK_ETH (1 << INT_ETH)
|
||||
#define INTMASK_USB (1 << INT_USB)
|
||||
#define INTMASK_TSPENINT (1 << INT_TSPENINT)
|
||||
#define INTMASK_TSKPADINT (1 << INT_TSKPADINT)
|
||||
|
||||
#define MAXIRQNUM 31
|
||||
#define MAXFIQNUM 31
|
||||
#define MAXSWINUM 31
|
||||
|
||||
/*
|
||||
* Application Flash
|
||||
*
|
||||
@ -463,6 +315,4 @@
|
||||
#define REALVIEW_CSR_BASE 0x10000000
|
||||
#define REALVIEW_CSR_SIZE 0x10000000
|
||||
|
||||
#endif
|
||||
|
||||
/* END */
|
||||
#endif /* __ASM_ARCH_PLATFORM_H */
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef __ASMARM_ARCH_SCU_H
|
||||
#define __ASMARM_ARCH_SCU_H
|
||||
|
||||
#include <asm/arch/platform.h>
|
||||
#include <asm/arch/board-eb.h>
|
||||
|
||||
#define SCU_BASE REALVIEW_MPCORE_SCU_BASE
|
||||
#define SCU_BASE REALVIEW_EB11MP_SCU_BASE
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,8 @@
|
||||
*/
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include <asm/arch/platform.h>
|
||||
|
||||
#define AMBA_UART_DR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x00))
|
||||
#define AMBA_UART_LCRH (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x2c))
|
||||
#define AMBA_UART_CR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x30))
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef __ASM_HARDWARE_TWD_H
|
||||
#define __ASM_HARDWARE_TWD_H
|
||||
|
||||
#define TWD_TIMER_LOAD 0x00
|
||||
#define TWD_TIMER_LOAD 0x00
|
||||
#define TWD_TIMER_COUNTER 0x04
|
||||
#define TWD_TIMER_CONTROL 0x08
|
||||
#define TWD_TIMER_INTSTAT 0x0C
|
||||
@ -13,4 +13,9 @@
|
||||
#define TWD_WDOG_RESETSTAT 0x30
|
||||
#define TWD_WDOG_DISABLE 0x34
|
||||
|
||||
#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
|
||||
#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
|
||||
#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
|
||||
#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
#define KEXEC_BOOT_PARAMS_SIZE 1536
|
||||
|
||||
#define KEXEC_ARM_ATAGS_OFFSET 0x1000
|
||||
#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct kimage;
|
||||
|
@ -60,6 +60,11 @@ extern void smp_cross_call(cpumask_t callmap);
|
||||
*/
|
||||
extern void smp_send_timer(void);
|
||||
|
||||
/*
|
||||
* Broadcast a clock event to other CPUs.
|
||||
*/
|
||||
extern void smp_timer_broadcast(cpumask_t mask);
|
||||
|
||||
/*
|
||||
* Boot a secondary CPU, and assign it the specified idle task.
|
||||
* This also gives us the initial stack to use for this CPU.
|
||||
@ -96,11 +101,12 @@ extern void platform_cpu_die(unsigned int cpu);
|
||||
extern int platform_cpu_kill(unsigned int cpu);
|
||||
extern void platform_cpu_enable(unsigned int cpu);
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
/*
|
||||
* Setup a local timer interrupt for a CPU.
|
||||
* Local timer interrupt handling function (can be IPI'ed).
|
||||
*/
|
||||
extern void local_timer_setup(unsigned int cpu);
|
||||
extern void local_timer_interrupt(void);
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
|
||||
/*
|
||||
* Stop a local timer interrupt.
|
||||
@ -114,16 +120,17 @@ extern int local_timer_ack(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void local_timer_setup(unsigned int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void local_timer_stop(unsigned int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup a local timer interrupt for a CPU.
|
||||
*/
|
||||
extern void local_timer_setup(unsigned int cpu);
|
||||
|
||||
/*
|
||||
* show local interrupt info
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user