You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (44 commits) [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 [ARM] 4736/1: Export atags to userspace and allow kexec to use customised atags [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 ...
This commit is contained in:
+16
-2
@@ -35,6 +35,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
|
||||
@@ -187,6 +192,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.
|
||||
|
||||
@@ -623,7 +630,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
|
||||
@@ -656,7 +663,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
|
||||
@@ -912,6 +919,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;
|
||||
}
|
||||
|
||||
|
||||
+649
-333
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
|
||||
|
||||
@@ -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);
|
||||
@@ -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:
|
||||
|
||||
+3
-30
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+32
-7
@@ -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;
|
||||
|
||||
@@ -253,6 +253,36 @@ config AT91_TIMER_HZ
|
||||
system clock (of at least several MHz), rounding is less of a
|
||||
problem so it can be safer to use a decimal values like 100.
|
||||
|
||||
choice
|
||||
prompt "Select a UART for early kernel messages"
|
||||
|
||||
config AT91_EARLY_DBGU
|
||||
bool "DBGU"
|
||||
|
||||
config AT91_EARLY_USART0
|
||||
bool "USART0"
|
||||
|
||||
config AT91_EARLY_USART1
|
||||
bool "USART1"
|
||||
|
||||
config AT91_EARLY_USART2
|
||||
bool "USART2"
|
||||
depends on ! ARCH_AT91X40
|
||||
|
||||
config AT91_EARLY_USART3
|
||||
bool "USART3"
|
||||
depends on (ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9260)
|
||||
|
||||
config AT91_EARLY_USART4
|
||||
bool "USART4"
|
||||
depends on ARCH_AT91SAM9260
|
||||
|
||||
config AT91_EARLY_USART5
|
||||
bool "USART5"
|
||||
depends on ARCH_AT91SAM9260
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -47,6 +47,9 @@ extern void at91_irq_resume(void);
|
||||
#define AT91RM9200_BGA 4 /* AT91RM9200 BGA package has 4 banks */
|
||||
|
||||
struct at91_gpio_bank {
|
||||
unsigned chipbase; /* bank's first GPIO number */
|
||||
void __iomem *regbase; /* base of register bank */
|
||||
struct at91_gpio_bank *next; /* bank sharing same IRQ/clock/... */
|
||||
unsigned short id; /* peripheral ID */
|
||||
unsigned long offset; /* offset from system peripheral base */
|
||||
struct clk *clock; /* associated clock */
|
||||
|
||||
+60
-29
@@ -33,12 +33,10 @@ static int gpio_banks;
|
||||
|
||||
static inline void __iomem *pin_to_controller(unsigned pin)
|
||||
{
|
||||
void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
|
||||
|
||||
pin -= PIN_BASE;
|
||||
pin /= 32;
|
||||
if (likely(pin < gpio_banks))
|
||||
return sys_base + gpio[pin].offset;
|
||||
return gpio[pin].regbase;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -294,11 +292,11 @@ void at91_gpio_suspend(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gpio_banks; i++) {
|
||||
u32 pio = gpio[i].offset;
|
||||
void __iomem *pio = gpio[i].regbase;
|
||||
|
||||
backups[i] = at91_sys_read(pio + PIO_IMR);
|
||||
at91_sys_write(pio + PIO_IDR, backups[i]);
|
||||
at91_sys_write(pio + PIO_IER, wakeups[i]);
|
||||
backups[i] = __raw_readl(pio + PIO_IMR);
|
||||
__raw_writel(backups[i], pio + PIO_IDR);
|
||||
__raw_writel(wakeups[i], pio + PIO_IER);
|
||||
|
||||
if (!wakeups[i])
|
||||
clk_disable(gpio[i].clock);
|
||||
@@ -315,13 +313,13 @@ void at91_gpio_resume(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gpio_banks; i++) {
|
||||
u32 pio = gpio[i].offset;
|
||||
void __iomem *pio = gpio[i].regbase;
|
||||
|
||||
if (!wakeups[i])
|
||||
clk_enable(gpio[i].clock);
|
||||
|
||||
at91_sys_write(pio + PIO_IDR, wakeups[i]);
|
||||
at91_sys_write(pio + PIO_IER, backups[i]);
|
||||
__raw_writel(wakeups[i], pio + PIO_IDR);
|
||||
__raw_writel(backups[i], pio + PIO_IER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +359,13 @@ static void gpio_irq_unmask(unsigned pin)
|
||||
|
||||
static int gpio_irq_type(unsigned pin, unsigned type)
|
||||
{
|
||||
return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
|
||||
switch (type) {
|
||||
case IRQ_TYPE_NONE:
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irqchip = {
|
||||
@@ -376,20 +380,30 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned pin;
|
||||
struct irq_desc *gpio;
|
||||
struct at91_gpio_bank *bank;
|
||||
void __iomem *pio;
|
||||
u32 isr;
|
||||
|
||||
pio = get_irq_chip_data(irq);
|
||||
bank = get_irq_chip_data(irq);
|
||||
pio = bank->regbase;
|
||||
|
||||
/* temporarily mask (level sensitive) parent IRQ */
|
||||
desc->chip->ack(irq);
|
||||
for (;;) {
|
||||
/* reading ISR acks the pending (edge triggered) GPIO interrupt */
|
||||
/* Reading ISR acks pending (edge triggered) GPIO interrupts.
|
||||
* When there none are pending, we're finished unless we need
|
||||
* to process multiple banks (like ID_PIOCDE on sam9263).
|
||||
*/
|
||||
isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
|
||||
if (!isr)
|
||||
break;
|
||||
if (!isr) {
|
||||
if (!bank->next)
|
||||
break;
|
||||
bank = bank->next;
|
||||
pio = bank->regbase;
|
||||
continue;
|
||||
}
|
||||
|
||||
pin = (unsigned) get_irq_data(irq);
|
||||
pin = bank->chipbase;
|
||||
gpio = &irq_desc[pin];
|
||||
|
||||
while (isr) {
|
||||
@@ -481,24 +495,21 @@ postcore_initcall(at91_gpio_debugfs_init);
|
||||
*/
|
||||
void __init at91_gpio_irq_setup(void)
|
||||
{
|
||||
unsigned pioc, pin;
|
||||
unsigned pioc, pin;
|
||||
struct at91_gpio_bank *this, *prev;
|
||||
|
||||
for (pioc = 0, pin = PIN_BASE;
|
||||
pioc < gpio_banks;
|
||||
pioc++) {
|
||||
void __iomem *controller;
|
||||
unsigned id = gpio[pioc].id;
|
||||
for (pioc = 0, pin = PIN_BASE, this = gpio, prev = NULL;
|
||||
pioc++ < gpio_banks;
|
||||
prev = this, this++) {
|
||||
unsigned id = this->id;
|
||||
unsigned i;
|
||||
|
||||
clk_enable(gpio[pioc].clock); /* enable PIO controller's clock */
|
||||
/* enable PIO controller's clock */
|
||||
clk_enable(this->clock);
|
||||
|
||||
controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
|
||||
__raw_writel(~0, controller + PIO_IDR);
|
||||
__raw_writel(~0, this->regbase + PIO_IDR);
|
||||
|
||||
set_irq_data(id, (void *) pin);
|
||||
set_irq_chip_data(id, controller);
|
||||
|
||||
for (i = 0; i < 32; i++, pin++) {
|
||||
for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
|
||||
/*
|
||||
* Can use the "simple" and not "edge" handler since it's
|
||||
* shorter, and the AIC handles interrupts sanely.
|
||||
@@ -508,6 +519,14 @@ void __init at91_gpio_irq_setup(void)
|
||||
set_irq_flags(pin, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* The toplevel handler handles one bank of GPIOs, except
|
||||
* AT91SAM9263_ID_PIOCDE handles three... PIOC is first in
|
||||
* the list, so we only set up that handler.
|
||||
*/
|
||||
if (prev && prev->next == this)
|
||||
continue;
|
||||
|
||||
set_irq_chip_data(id, this);
|
||||
set_irq_chained_handler(id, gpio_irq_handler);
|
||||
}
|
||||
pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
|
||||
@@ -518,8 +537,20 @@ void __init at91_gpio_irq_setup(void)
|
||||
*/
|
||||
void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
|
||||
{
|
||||
unsigned i;
|
||||
struct at91_gpio_bank *last;
|
||||
|
||||
BUG_ON(nr_banks > MAX_GPIO_BANKS);
|
||||
|
||||
gpio = data;
|
||||
gpio_banks = nr_banks;
|
||||
|
||||
for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) {
|
||||
data->chipbase = PIN_BASE + i * 32;
|
||||
data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS;
|
||||
|
||||
/* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
|
||||
if (last && last->id == data->id)
|
||||
last->next = data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 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 = "IXP4XX-GPIO-LED",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(dsmg600_led_resources),
|
||||
.resource = dsmg600_led_resources,
|
||||
.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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user