Commit 9ef9dc69 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 2c8296f8 0d899e1b
......@@ -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;
}
......
This diff is collapsed.
......@@ -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
......
#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);
#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;
......
......@@ -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 */
......
......@@ -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 */
controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
__raw_writel(~0, controller + PIO_IDR);
/* enable PIO controller's clock */
clk_enable(this->clock);
set_irq_data(id, (void *) pin);
set_irq_chip_data(id, controller);
__raw_writel(~0, this->regbase + PIO_IDR);
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