diff options
Diffstat (limited to 'arch/arm/plat-versatile')
| -rw-r--r-- | arch/arm/plat-versatile/Kconfig | 14 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/Makefile | 6 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/fpga-irq.c | 158 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/headsmp.S | 6 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/include/plat/fpga-irq.h | 11 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/include/plat/platsmp.h | 14 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/leds.c | 103 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/platsmp.c | 25 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/sched-clock.c | 6 |
9 files changed, 30 insertions, 313 deletions
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index 81ee7cc3445..fce41e93b6a 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -1,20 +1,10 @@ if PLAT_VERSATILE -config PLAT_VERSATILE_CLCD +config PLAT_VERSATILE_CLOCK bool -config PLAT_VERSATILE_FPGA_IRQ +config PLAT_VERSATILE_CLCD bool - select IRQ_DOMAIN - -config PLAT_VERSATILE_FPGA_IRQ_NR - int - default 4 - depends on PLAT_VERSATILE_FPGA_IRQ - -config PLAT_VERSATILE_LEDS - def_bool y if LEDS_CLASS - depends on ARCH_REALVIEW || ARCH_VERSATILE config PLAT_VERSATILE_SCHED_CLOCK def_bool y diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index a5cb1945bdc..2e0c472958a 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,6 +1,6 @@ -obj-y := clock.o +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include + +obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o -obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o -obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c deleted file mode 100644 index 6e70d03824a..00000000000 --- a/arch/arm/plat-versatile/fpga-irq.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Support for Versatile FPGA-based IRQ controllers - */ -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/irqdomain.h> -#include <linux/module.h> - -#include <asm/exception.h> -#include <asm/mach/irq.h> -#include <plat/fpga-irq.h> - -#define IRQ_STATUS 0x00 -#define IRQ_RAW_STATUS 0x04 -#define IRQ_ENABLE_SET 0x08 -#define IRQ_ENABLE_CLEAR 0x0c - -/** - * struct fpga_irq_data - irq data container for the FPGA IRQ controller - * @base: memory offset in virtual memory - * @irq_start: first IRQ number handled by this instance - * @chip: chip container for this instance - * @domain: IRQ domain for this instance - * @valid: mask for valid IRQs on this controller - * @used_irqs: number of active IRQs on this controller - */ -struct fpga_irq_data { - void __iomem *base; - unsigned int irq_start; - struct irq_chip chip; - u32 valid; - struct irq_domain *domain; - u8 used_irqs; -}; - -/* we cannot allocate memory when the controllers are initially registered */ -static struct fpga_irq_data fpga_irq_devices[CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR]; -static int fpga_irq_id; - -static void fpga_irq_mask(struct irq_data *d) -{ - struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); - u32 mask = 1 << d->hwirq; - - writel(mask, f->base + IRQ_ENABLE_CLEAR); -} - -static void fpga_irq_unmask(struct irq_data *d) -{ - struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); - u32 mask = 1 << d->hwirq; - - writel(mask, f->base + IRQ_ENABLE_SET); -} - -static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc) -{ - struct fpga_irq_data *f = irq_desc_get_handler_data(desc); - u32 status = readl(f->base + IRQ_STATUS); - - if (status == 0) { - do_bad_IRQ(irq, desc); - return; - } - - do { - irq = ffs(status) - 1; - status &= ~(1 << irq); - generic_handle_irq(irq_find_mapping(f->domain, irq)); - } while (status); -} - -/* - * Handle each interrupt in a single FPGA IRQ controller. Returns non-zero - * if we've handled at least one interrupt. This does a single read of the - * status register and handles all interrupts in order from LSB first. - */ -static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs) -{ - int handled = 0; - int irq; - u32 status; - - while ((status = readl(f->base + IRQ_STATUS))) { - irq = ffs(status) - 1; - handle_IRQ(irq_find_mapping(f->domain, irq), regs); - handled = 1; - } - - return handled; -} - -/* - * Keep iterating over all registered FPGA IRQ controllers until there are - * no pending interrupts. - */ -asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs) -{ - int i, handled; - - do { - for (i = 0, handled = 0; i < fpga_irq_id; ++i) - handled |= handle_one_fpga(&fpga_irq_devices[i], regs); - } while (handled); -} - -static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) -{ - struct fpga_irq_data *f = d->host_data; - - /* Skip invalid IRQs, only register handlers for the real ones */ - if (!(f->valid & (1 << hwirq))) - return -ENOTSUPP; - irq_set_chip_data(irq, f); - irq_set_chip_and_handler(irq, &f->chip, - handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - f->used_irqs++; - return 0; -} - -static struct irq_domain_ops fpga_irqdomain_ops = { - .map = fpga_irqdomain_map, - .xlate = irq_domain_xlate_onetwocell, -}; - -void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start, - int parent_irq, u32 valid, struct device_node *node) -{ - struct fpga_irq_data *f; - - if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) { - printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__); - return; - } - - f = &fpga_irq_devices[fpga_irq_id]; - f->base = base; - f->irq_start = irq_start; - f->chip.name = name; - f->chip.irq_ack = fpga_irq_mask; - f->chip.irq_mask = fpga_irq_mask; - f->chip.irq_unmask = fpga_irq_unmask; - f->valid = valid; - - if (parent_irq != -1) { - irq_set_handler_data(parent_irq, f); - irq_set_chained_handler(parent_irq, fpga_irq_handle); - } - - f->domain = irq_domain_add_legacy(node, fls(valid), f->irq_start, 0, - &fpga_irqdomain_ops, f); - pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n", - fpga_irq_id, name, base, f->used_irqs); - - fpga_irq_id++; -} diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S index dd703ef09b8..40f27e52de7 100644 --- a/arch/arm/plat-versatile/headsmp.S +++ b/arch/arm/plat-versatile/headsmp.S @@ -10,8 +10,7 @@ */ #include <linux/linkage.h> #include <linux/init.h> - - __INIT +#include <asm/assembler.h> /* * Realview/Versatile Express specific entry point for secondary CPUs. @@ -19,8 +18,9 @@ * until we're ready for them to initialise. */ ENTRY(versatile_secondary_startup) + ARM_BE8(setend be) mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 + bic r0, #0xff000000 adr r4, 1f ldmia r4, {r5, r6} sub r4, r4, r5 diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h deleted file mode 100644 index 91bcfb67551..00000000000 --- a/arch/arm/plat-versatile/include/plat/fpga-irq.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef PLAT_FPGA_IRQ_H -#define PLAT_FPGA_IRQ_H - -struct device_node; -struct pt_regs; - -void fpga_handle_irq(struct pt_regs *regs); -void fpga_irq_init(void __iomem *, const char *, int, int, u32, - struct device_node *node); - -#endif diff --git a/arch/arm/plat-versatile/include/plat/platsmp.h b/arch/arm/plat-versatile/include/plat/platsmp.h new file mode 100644 index 00000000000..50fb830192e --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/platsmp.h @@ -0,0 +1,14 @@ +/* + * linux/arch/arm/plat-versatile/include/plat/platsmp.h + * + * Copyright (C) 2011 ARM Ltd. + * All Rights Reserved + * + * 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. + */ + +extern void versatile_secondary_startup(void); +extern void versatile_secondary_init(unsigned int cpu); +extern int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle); diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c deleted file mode 100644 index 3169fa555ea..00000000000 --- a/arch/arm/plat-versatile/leds.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Driver for the 8 user LEDs found on the RealViews and Versatiles - * Based on DaVinci's DM365 board code - * - * License terms: GNU General Public License (GPL) version 2 - * Author: Linus Walleij <triad@df.lth.se> - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/leds.h> - -#include <mach/hardware.h> -#include <mach/platform.h> - -#ifdef VERSATILE_SYS_BASE -#define LEDREG (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) -#endif - -#ifdef REALVIEW_SYS_BASE -#define LEDREG (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET) -#endif - -struct versatile_led { - struct led_classdev cdev; - u8 mask; -}; - -/* - * The triggers lines up below will only be used if the - * LED triggers are compiled in. - */ -static const struct { - const char *name; - const char *trigger; -} versatile_leds[] = { - { "versatile:0", "heartbeat", }, - { "versatile:1", "mmc0", }, - { "versatile:2", }, - { "versatile:3", }, - { "versatile:4", }, - { "versatile:5", }, - { "versatile:6", }, - { "versatile:7", }, -}; - -static void versatile_led_set(struct led_classdev *cdev, - enum led_brightness b) -{ - struct versatile_led *led = container_of(cdev, - struct versatile_led, cdev); - u32 reg = readl(LEDREG); - - if (b != LED_OFF) - reg |= led->mask; - else - reg &= ~led->mask; - writel(reg, LEDREG); -} - -static enum led_brightness versatile_led_get(struct led_classdev *cdev) -{ - struct versatile_led *led = container_of(cdev, - struct versatile_led, cdev); - u32 reg = readl(LEDREG); - - return (reg & led->mask) ? LED_FULL : LED_OFF; -} - -static int __init versatile_leds_init(void) -{ - int i; - - /* All ON */ - writel(0xff, LEDREG); - for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) { - struct versatile_led *led; - - led = kzalloc(sizeof(*led), GFP_KERNEL); - if (!led) - break; - - led->cdev.name = versatile_leds[i].name; - led->cdev.brightness_set = versatile_led_set; - led->cdev.brightness_get = versatile_led_get; - led->cdev.default_trigger = versatile_leds[i].trigger; - led->mask = BIT(i); - - if (led_classdev_register(NULL, &led->cdev) < 0) { - kfree(led); - break; - } - } - - return 0; -} - -/* - * Since we may have triggers on any subsystem, defer registration - * until after subsystem_init. - */ -fs_initcall(versatile_leds_init); diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 49c7db48c7f..53feb90c840 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -17,39 +17,24 @@ #include <asm/cacheflush.h> #include <asm/smp_plat.h> -#include <asm/hardware/gic.h> - -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int __cpuinitdata pen_release = -1; /* * Write pen_release in a way that is guaranteed to be visible to all * observers, irrespective of whether they're taking part in coherency * or not. This is necessary for the hotplug code to work reliably. */ -static void __cpuinit write_pen_release(int val) +static void write_pen_release(int val) { pen_release = val; smp_wmb(); - __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); - outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); + sync_cache_w(&pen_release); } static DEFINE_SPINLOCK(boot_lock); -void __cpuinit platform_secondary_init(unsigned int cpu) +void versatile_secondary_init(unsigned int cpu) { /* - * if any interrupts are already enabled for the primary - * core (e.g. timer irq), then they will not have been enabled - * for us: do so - */ - gic_secondary_init(0); - - /* * let the primary processor know we're out of the * pen, then head off into the C entry point */ @@ -62,7 +47,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; @@ -85,7 +70,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 1); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c index b33b74c8723..c966ae90f4a 100644 --- a/arch/arm/plat-versatile/sched-clock.c +++ b/arch/arm/plat-versatile/sched-clock.c @@ -20,13 +20,13 @@ */ #include <linux/kernel.h> #include <linux/io.h> +#include <linux/sched_clock.h> -#include <asm/sched_clock.h> #include <plat/sched_clock.h> static void __iomem *ctr; -static u32 notrace versatile_read_sched_clock(void) +static u64 notrace versatile_read_sched_clock(void) { if (ctr) return readl(ctr); @@ -37,5 +37,5 @@ static u32 notrace versatile_read_sched_clock(void) void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) { ctr = reg; - setup_sched_clock(versatile_read_sched_clock, 32, rate); + sched_clock_register(versatile_read_sched_clock, 32, rate); } |
