diff options
Diffstat (limited to 'arch/arm')
61 files changed, 418 insertions, 344 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1655c0734d7..9673bbad16f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1283,7 +1283,7 @@ config ARM_ERRATA_743622 depends on CPU_V7 help This option enables the workaround for the 743622 Cortex-A9 - (r2p0..r2p2) erratum. Under very rare conditions, a faulty + (r2p*) erratum. Under very rare conditions, a faulty optimisation in the Cortex-A9 Store Buffer may lead to data corruption. This workaround sets a specific bit in the diagnostic register of the Cortex-A9 which disables the Store Buffer diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore index ce1c5ff746e..3c79f85975a 100644 --- a/arch/arm/boot/.gitignore +++ b/arch/arm/boot/.gitignore @@ -3,3 +3,4 @@ zImage xipImage bootpImage uImage +*.dtb diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index b5a5be2536c..90114faa9f3 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -134,7 +134,7 @@ int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type); u64 armpmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, - int idx, int overflow); + int idx); int armpmu_event_set_period(struct perf_event *event, struct hw_perf_event *hwc, diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 43b740d0e37..f16d7652f34 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -62,9 +62,6 @@ obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o CFLAGS_swp_emulate.o := -Wa,-march=armv7-a obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o -obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o -AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 - obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 4dd0edab6a6..1651d495074 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -242,6 +242,7 @@ static void ecard_init_pgtables(struct mm_struct *mm) memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); + vma.vm_flags = VM_EXEC; vma.vm_mm = mm; flush_tlb_range(&vma, IO_START, IO_START + IO_SIZE); diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 5bb91bf3d47..b2abfa18f13 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -180,7 +180,7 @@ armpmu_event_set_period(struct perf_event *event, u64 armpmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, - int idx, int overflow) + int idx) { struct arm_pmu *armpmu = to_arm_pmu(event->pmu); u64 delta, prev_raw_count, new_raw_count; @@ -193,13 +193,7 @@ again: new_raw_count) != prev_raw_count) goto again; - new_raw_count &= armpmu->max_period; - prev_raw_count &= armpmu->max_period; - - if (overflow) - delta = armpmu->max_period - prev_raw_count + new_raw_count + 1; - else - delta = new_raw_count - prev_raw_count; + delta = (new_raw_count - prev_raw_count) & armpmu->max_period; local64_add(delta, &event->count); local64_sub(delta, &hwc->period_left); @@ -216,7 +210,7 @@ armpmu_read(struct perf_event *event) if (hwc->idx < 0) return; - armpmu_event_update(event, hwc, hwc->idx, 0); + armpmu_event_update(event, hwc, hwc->idx); } static void @@ -232,7 +226,7 @@ armpmu_stop(struct perf_event *event, int flags) if (!(hwc->state & PERF_HES_STOPPED)) { armpmu->disable(hwc, hwc->idx); barrier(); /* why? */ - armpmu_event_update(event, hwc, hwc->idx, 0); + armpmu_event_update(event, hwc, hwc->idx); hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; } } @@ -518,7 +512,13 @@ __hw_perf_event_init(struct perf_event *event) hwc->config_base |= (unsigned long)mapping; if (!hwc->sample_period) { - hwc->sample_period = armpmu->max_period; + /* + * For non-sampling runs, limit the sample_period to half + * of the counter width. That way, the new counter value + * is far less likely to overtake the previous one unless + * you have some serious IRQ latency issues. + */ + hwc->sample_period = armpmu->max_period >> 1; hwc->last_period = hwc->sample_period; local64_set(&hwc->period_left, hwc->sample_period); } @@ -680,6 +680,28 @@ static void __init cpu_pmu_init(struct arm_pmu *armpmu) } /* + * PMU hardware loses all context when a CPU goes offline. + * When a CPU is hotplugged back in, since some hardware registers are + * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading + * junk values out of them. + */ +static int __cpuinit pmu_cpu_notify(struct notifier_block *b, + unsigned long action, void *hcpu) +{ + if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) + return NOTIFY_DONE; + + if (cpu_pmu && cpu_pmu->reset) + cpu_pmu->reset(NULL); + + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata pmu_cpu_notifier = { + .notifier_call = pmu_cpu_notify, +}; + +/* * CPU PMU identification and registration. */ static int __init @@ -730,6 +752,7 @@ init_hw_perf_events(void) pr_info("enabled with %s PMU driver, %d counters available\n", cpu_pmu->name, cpu_pmu->num_events); cpu_pmu_init(cpu_pmu); + register_cpu_notifier(&pmu_cpu_notifier); armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); } else { pr_info("no hardware support available\n"); diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index 533be9930ec..b78af0cc6ef 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -467,23 +467,6 @@ armv6pmu_enable_event(struct hw_perf_event *hwc, raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } -static int counter_is_active(unsigned long pmcr, int idx) -{ - unsigned long mask = 0; - if (idx == ARMV6_CYCLE_COUNTER) - mask = ARMV6_PMCR_CCOUNT_IEN; - else if (idx == ARMV6_COUNTER0) - mask = ARMV6_PMCR_COUNT0_IEN; - else if (idx == ARMV6_COUNTER1) - mask = ARMV6_PMCR_COUNT1_IEN; - - if (mask) - return pmcr & mask; - - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return 0; -} - static irqreturn_t armv6pmu_handle_irq(int irq_num, void *dev) @@ -513,7 +496,8 @@ armv6pmu_handle_irq(int irq_num, struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; - if (!counter_is_active(pmcr, idx)) + /* Ignore if we don't have an event. */ + if (!event) continue; /* @@ -524,7 +508,7 @@ armv6pmu_handle_irq(int irq_num, continue; hwc = &event->hw; - armpmu_event_update(event, hwc, idx, 1); + armpmu_event_update(event, hwc, idx); data.period = event->hw.last_period; if (!armpmu_event_set_period(event, hwc, idx)) continue; diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 6933244c68f..4d7095af2ab 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -809,6 +809,11 @@ static inline int armv7_pmnc_disable_intens(int idx) counter = ARMV7_IDX_TO_COUNTER(idx); asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter))); + isb(); + /* Clear the overflow flag in case an interrupt is pending. */ + asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (BIT(counter))); + isb(); + return idx; } @@ -955,6 +960,10 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; + /* Ignore if we don't have an event. */ + if (!event) + continue; + /* * We have a single interrupt for all counters. Check that * each counter has overflowed before we process it. @@ -963,7 +972,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) continue; hwc = &event->hw; - armpmu_event_update(event, hwc, idx, 1); + armpmu_event_update(event, hwc, idx); data.period = event->hw.last_period; if (!armpmu_event_set_period(event, hwc, idx)) continue; diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 3b99d826982..71a21e6712f 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c @@ -255,11 +255,14 @@ xscale1pmu_handle_irq(int irq_num, void *dev) struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; + if (!event) + continue; + if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx)) continue; hwc = &event->hw; - armpmu_event_update(event, hwc, idx, 1); + armpmu_event_update(event, hwc, idx); data.period = event->hw.last_period; if (!armpmu_event_set_period(event, hwc, idx)) continue; @@ -592,11 +595,14 @@ xscale2pmu_handle_irq(int irq_num, void *dev) struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; - if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx)) + if (!event) + continue; + + if (!xscale2_pmnc_counter_has_overflowed(of_flags, idx)) continue; hwc = &event->hw; - armpmu_event_update(event, hwc, idx, 1); + armpmu_event_update(event, hwc, idx); data.period = event->hw.last_period; if (!armpmu_event_set_period(event, hwc, idx)) continue; @@ -663,7 +669,7 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx) static void xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) { - unsigned long flags, ien, evtsel; + unsigned long flags, ien, evtsel, of_flags; struct pmu_hw_events *events = cpu_pmu->get_hw_events(); ien = xscale2pmu_read_int_enable(); @@ -672,26 +678,31 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) switch (idx) { case XSCALE_CYCLE_COUNTER: ien &= ~XSCALE2_CCOUNT_INT_EN; + of_flags = XSCALE2_CCOUNT_OVERFLOW; break; case XSCALE_COUNTER0: ien &= ~XSCALE2_COUNT0_INT_EN; evtsel &= ~XSCALE2_COUNT0_EVT_MASK; evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT; + of_flags = XSCALE2_COUNT0_OVERFLOW; break; case XSCALE_COUNTER1: ien &= ~XSCALE2_COUNT1_INT_EN; evtsel &= ~XSCALE2_COUNT1_EVT_MASK; evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT; + of_flags = XSCALE2_COUNT1_OVERFLOW; break; case XSCALE_COUNTER2: ien &= ~XSCALE2_COUNT2_INT_EN; evtsel &= ~XSCALE2_COUNT2_EVT_MASK; evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT; + of_flags = XSCALE2_COUNT2_OVERFLOW; break; case XSCALE_COUNTER3: ien &= ~XSCALE2_COUNT3_INT_EN; evtsel &= ~XSCALE2_COUNT3_EVT_MASK; evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT; + of_flags = XSCALE2_COUNT3_OVERFLOW; break; default: WARN_ONCE(1, "invalid counter number (%d)\n", idx); @@ -701,6 +712,7 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) raw_spin_lock_irqsave(&events->pmu_lock, flags); xscale2pmu_write_event_select(evtsel); xscale2pmu_write_int_enable(ien); + xscale2pmu_write_overflow_flags(of_flags); raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index b7582dd10dc..96e2adcd5a8 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -38,10 +38,6 @@ #if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE) static u64 hdmac_dmamask = DMA_BIT_MASK(32); -static struct at_dma_platform_data atdma_pdata = { - .nr_channels = 8, -}; - static struct resource hdmac_resources[] = { [0] = { .start = AT91SAM9G45_BASE_DMA, @@ -56,12 +52,11 @@ static struct resource hdmac_resources[] = { }; static struct platform_device at_hdmac_device = { - .name = "at_hdmac", + .name = "at91sam9g45_dma", .id = -1, .dev = { .dma_mask = &hdmac_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &atdma_pdata, }, .resource = hdmac_resources, .num_resources = ARRAY_SIZE(hdmac_resources), @@ -69,9 +64,15 @@ static struct platform_device at_hdmac_device = { void __init at91_add_device_hdmac(void) { - dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask); - dma_cap_set(DMA_SLAVE, atdma_pdata.cap_mask); - platform_device_register(&at_hdmac_device); +#if defined(CONFIG_OF) + struct device_node *of_node = + of_find_node_by_name(NULL, "dma-controller"); + + if (of_node) + of_node_put(of_node); + else +#endif + platform_device_register(&at_hdmac_device); } #else void __init at91_add_device_hdmac(void) {} diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 61908dce978..9be71c11d0f 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -33,10 +33,6 @@ #if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE) static u64 hdmac_dmamask = DMA_BIT_MASK(32); -static struct at_dma_platform_data atdma_pdata = { - .nr_channels = 2, -}; - static struct resource hdmac_resources[] = { [0] = { .start = AT91SAM9RL_BASE_DMA, @@ -51,12 +47,11 @@ static struct resource hdmac_resources[] = { }; static struct platform_device at_hdmac_device = { - .name = "at_hdmac", + .name = "at91sam9rl_dma", .id = -1, .dev = { .dma_mask = &hdmac_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &atdma_pdata, }, .resource = hdmac_resources, .num_resources = ARRAY_SIZE(hdmac_resources), @@ -64,7 +59,6 @@ static struct platform_device at_hdmac_device = { void __init at91_add_device_hdmac(void) { - dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask); platform_device_register(&at_hdmac_device); } #else diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index 574209d9e24..0dc51f9462d 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -8,6 +8,9 @@ obj- := obj-$(CONFIG_EP93XX_DMA) += dma.o +obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o +AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 + obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c index 681e939407d..2d45947a303 100644 --- a/arch/arm/mach-ep93xx/adssphere.c +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -20,6 +20,7 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include "soc.h" static struct ep93xx_eth_data __initdata adssphere_eth_data = { .phy_id = 1, diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index ca4de710509..c95dbce2468 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -25,6 +25,7 @@ #include <asm/div64.h> +#include "soc.h" struct clk { struct clk *parent; diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 903edb02fe4..8d258958871 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -46,6 +46,7 @@ #include <asm/hardware/vic.h> +#include "soc.h" /************************************************************************* * Static I/O mappings that are needed for all EP93xx platforms @@ -204,7 +205,6 @@ void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) spin_unlock_irqrestore(&syscon_swlock, flags); } -EXPORT_SYMBOL(ep93xx_syscon_swlocked_write); void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) { @@ -221,7 +221,6 @@ void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) spin_unlock_irqrestore(&syscon_swlock, flags); } -EXPORT_SYMBOL(ep93xx_devcfg_set_clear); /** * ep93xx_chip_revision() - returns the EP93xx chip revision @@ -648,9 +647,19 @@ static struct platform_device ep93xx_fb_device = { .resource = ep93xx_fb_resource, }; +/* The backlight use a single register in the framebuffer's register space */ +#define EP93XX_RASTER_REG_BRIGHTNESS 0x20 + +static struct resource ep93xx_bl_resources[] = { + DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE + + EP93XX_RASTER_REG_BRIGHTNESS, 0x04), +}; + static struct platform_device ep93xx_bl_device = { .name = "ep93xx-bl", .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_bl_resources), + .resource = ep93xx_bl_resources, }; /** @@ -783,23 +792,12 @@ void __init ep93xx_register_i2s(void) #define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ EP93XX_SYSCON_I2SCLKDIV_SPOL) -int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config) +int ep93xx_i2s_acquire(void) { unsigned val; - /* Sanity check */ - if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK) - return -EINVAL; - if (i2s_config & ~EP93XX_I2SCLKDIV_MASK) - return -EINVAL; - - /* Must have only one of I2SONSSP/I2SONAC97 set */ - if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) == - (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97)) - return -EINVAL; - - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); - ep93xx_devcfg_set_bits(i2s_pins); + ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97, + EP93XX_SYSCON_DEVCFG_I2S_MASK); /* * This is potentially racy with the clock api for i2s_mclk, sclk and @@ -809,7 +807,7 @@ int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config) */ val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); val &= ~EP93XX_I2SCLKDIV_MASK; - val |= i2s_config; + val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL; ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); return 0; @@ -856,11 +854,32 @@ void __init ep93xx_register_ac97(void) platform_device_register(&ep93xx_pcm_device); } +/************************************************************************* + * EP93xx Watchdog + *************************************************************************/ +static struct resource ep93xx_wdt_resources[] = { + DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08), +}; + +static struct platform_device ep93xx_wdt_device = { + .name = "ep93xx-wdt", + .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_wdt_resources), + .resource = ep93xx_wdt_resources, +}; + void __init ep93xx_init_devices(void) { /* Disallow access to MaverickCrunch initially */ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); + /* Default all ports to GPIO */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | + EP93XX_SYSCON_DEVCFG_GONK | + EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); + /* Get the GPIO working early, other devices need it */ platform_device_register(&ep93xx_gpio_device); @@ -871,6 +890,7 @@ void __init ep93xx_init_devices(void) platform_device_register(&ep93xx_rtc_device); platform_device_register(&ep93xx_ohci_device); platform_device_register(&ep93xx_leds); + platform_device_register(&ep93xx_wdt_device); } |