summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-07 12:05:21 +0200
committerIngo Molnar <mingo@elte.hu>2009-04-07 12:05:25 +0200
commit6c009ecef8cca28c7c09eb16d0802e37915a76e1 (patch)
tree11c773f780186fdb9fbc9c80a73fb7c8426b1fba /arch
parent98c2aaf8be5baf7193be37fb28bce8e7327158bc (diff)
parentd508afb437daee7cf07da085b635c44a4ebf9b38 (diff)
Merge branch 'linus' into perfcounters/core
Merge reason: need the upstream facility added by: 7f1e2ca: hrtimer: fix rq->lock inversion (again) Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-davinci/include/mach/nand.h80
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa3xx_nand.h3
-rw-r--r--arch/blackfin/kernel/process.c2
-rw-r--r--arch/frv/mm/tlb-miss.S1
-rw-r--r--arch/mips/include/asm/txx9/ndfmc.h30
-rw-r--r--arch/mips/include/asm/txx9/rbtx4939.h9
-rw-r--r--arch/mips/include/asm/txx9/tx4938.h1
-rw-r--r--arch/mips/include/asm/txx9/tx4939.h2
-rw-r--r--arch/mips/txx9/generic/setup.c21
-rw-r--r--arch/mips/txx9/generic/setup_tx4938.c21
-rw-r--r--arch/mips/txx9/generic/setup_tx4939.c17
-rw-r--r--arch/mips/txx9/rbtx4938/setup.c2
-rw-r--r--arch/mips/txx9/rbtx4939/setup.c161
-rw-r--r--arch/powerpc/boot/dts/tqm8548-bigflash.dts7
-rw-r--r--arch/powerpc/boot/dts/tqm8548.dts7
-rw-r--r--arch/powerpc/sysdev/fsl_lbc.c2
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/include/asm/apic.h3
-rw-r--r--arch/x86/include/asm/io_apic.h11
-rw-r--r--arch/x86/kernel/apic/apic.c70
-rw-r--r--arch/x86/kernel/apic/io_apic.c140
21 files changed, 526 insertions, 66 deletions
diff --git a/arch/arm/mach-davinci/include/mach/nand.h b/arch/arm/mach-davinci/include/mach/nand.h
new file mode 100644
index 000000000000..aa482841270b
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/nand.h
@@ -0,0 +1,80 @@
+/*
+ * mach-davinci/nand.h
+ *
+ * Copyright © 2006 Texas Instruments.
+ *
+ * Ported to 2.6.23 Copyright © 2008 by
+ * Sander Huijsen <Shuijsen@optelecom-nkf.com>
+ * Troy Kisky <troy.kisky@boundarydevices.com>
+ * Dirk Behme <Dirk.Behme@gmail.com>
+ *
+ * --------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ARCH_ARM_DAVINCI_NAND_H
+#define __ARCH_ARM_DAVINCI_NAND_H
+
+#include <linux/mtd/nand.h>
+
+#define NRCSR_OFFSET 0x00
+#define AWCCR_OFFSET 0x04
+#define A1CR_OFFSET 0x10
+#define NANDFCR_OFFSET 0x60
+#define NANDFSR_OFFSET 0x64
+#define NANDF1ECC_OFFSET 0x70
+
+/* 4-bit ECC syndrome registers */
+#define NAND_4BIT_ECC_LOAD_OFFSET 0xbc
+#define NAND_4BIT_ECC1_OFFSET 0xc0
+#define NAND_4BIT_ECC2_OFFSET 0xc4
+#define NAND_4BIT_ECC3_OFFSET 0xc8
+#define NAND_4BIT_ECC4_OFFSET 0xcc
+#define NAND_ERR_ADD1_OFFSET 0xd0
+#define NAND_ERR_ADD2_OFFSET 0xd4
+#define NAND_ERR_ERRVAL1_OFFSET 0xd8
+#define NAND_ERR_ERRVAL2_OFFSET 0xdc
+
+/* NOTE: boards don't need to use these address bits
+ * for ALE/CLE unless they support booting from NAND.
+ * They're used unless platform data overrides them.
+ */
+#define MASK_ALE 0x08
+#define MASK_CLE 0x10
+
+struct davinci_nand_pdata { /* platform_data */
+ uint32_t mask_ale;
+ uint32_t mask_cle;
+
+ /* for packages using two chipselects */
+ uint32_t mask_chipsel;
+
+ /* board's default static partition info */
+ struct mtd_partition *parts;
+ unsigned nr_parts;
+
+ /* none == NAND_ECC_NONE (strongly *not* advised!!)
+ * soft == NAND_ECC_SOFT
+ * 1-bit == NAND_ECC_HW
+ * 4-bit == NAND_ECC_HW_SYNDROME (not on all chips)
+ */
+ nand_ecc_modes_t ecc_mode;
+
+ /* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
+ unsigned options;
+};
+
+#endif /* __ARCH_ARM_DAVINCI_NAND_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx_nand.h b/arch/arm/mach-pxa/include/mach/pxa3xx_nand.h
index eb35fca9aea5..3478eae32d8a 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx_nand.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx_nand.h
@@ -49,6 +49,9 @@ struct pxa3xx_nand_platform_data {
*/
int enable_arbiter;
+ /* allow platform code to keep OBM/bootloader defined NFC config */
+ int keep_config;
+
const struct mtd_partition *parts;
unsigned int nr_parts;
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index f49427293ca1..e040e03335ea 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -337,7 +337,7 @@ int _access_ok(unsigned long addr, unsigned long size)
if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
return 1;
-#ifdef CONFIG_ROMFS_MTD_FS
+#ifdef CONFIG_ROMFS_ON_MTD
/* For XIP, allow user space to use pointers within the ROMFS. */
if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end)
return 1;
diff --git a/arch/frv/mm/tlb-miss.S b/arch/frv/mm/tlb-miss.S
index 07643482cad2..7f392bc651a3 100644
--- a/arch/frv/mm/tlb-miss.S
+++ b/arch/frv/mm/tlb-miss.S
@@ -13,7 +13,6 @@
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/highmem.h>
#include <asm/spr-regs.h>
.section .text.tlbmiss
diff --git a/arch/mips/include/asm/txx9/ndfmc.h b/arch/mips/include/asm/txx9/ndfmc.h
new file mode 100644
index 000000000000..fa67f3df78fc
--- /dev/null
+++ b/arch/mips/include/asm/txx9/ndfmc.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ *
+ * (C) Copyright TOSHIBA CORPORATION 2007
+ */
+#ifndef __ASM_TXX9_NDFMC_H
+#define __ASM_TXX9_NDFMC_H
+
+#define NDFMC_PLAT_FLAG_USE_BSPRT 0x01
+#define NDFMC_PLAT_FLAG_NO_RSTR 0x02
+#define NDFMC_PLAT_FLAG_HOLDADD 0x04
+#define NDFMC_PLAT_FLAG_DUMMYWRITE 0x08
+
+struct txx9ndfmc_platform_data {
+ unsigned int shift;
+ unsigned int gbus_clock;
+ unsigned int hold; /* hold time in nanosecond */
+ unsigned int spw; /* strobe pulse width in nanosecond */
+ unsigned int flags;
+ unsigned char ch_mask; /* available channel bitmask */
+ unsigned char wp_mask; /* write-protect bitmask */
+ unsigned char wide_mask; /* 16bit-nand bitmask */
+};
+
+void txx9_ndfmc_init(unsigned long baseaddr,
+ const struct txx9ndfmc_platform_data *plat_data);
+
+#endif /* __ASM_TXX9_NDFMC_H */
diff --git a/arch/mips/include/asm/txx9/rbtx4939.h b/arch/mips/include/asm/txx9/rbtx4939.h
index 1acf428c0b4f..e517899794a8 100644
--- a/arch/mips/include/asm/txx9/rbtx4939.h
+++ b/arch/mips/include/asm/txx9/rbtx4939.h
@@ -130,4 +130,13 @@
void rbtx4939_prom_init(void);
void rbtx4939_irq_setup(void);
+struct mtd_partition;
+struct map_info;
+struct rbtx4939_flash_data {
+ unsigned int width;
+ unsigned int nr_parts;
+ struct mtd_partition *parts;
+ void (*map_init)(struct map_info *map);
+};
+
#endif /* __ASM_TXX9_RBTX4939_H */
diff --git a/arch/mips/include/asm/txx9/tx4938.h b/arch/mips/include/asm/txx9/tx4938.h
index 0b068154054c..cd8bc2021755 100644
--- a/arch/mips/include/asm/txx9/tx4938.h
+++ b/arch/mips/include/asm/txx9/tx4938.h
@@ -291,6 +291,7 @@ int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot);
void tx4938_setup_pcierr_irq(void);
void tx4938_irq_init(void);
void tx4938_mtd_init(int ch);
+void tx4938_ndfmc_init(unsigned int hold, unsigned int spw);
struct tx4938ide_platform_info {
/*
diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h
index 964ef7ede268..f02c50b3abfb 100644
--- a/arch/mips/include/asm/txx9/tx4939.h
+++ b/arch/mips/include/asm/txx9/tx4939.h
@@ -542,5 +542,7 @@ int tx4939_irq(void);
void tx4939_mtd_init(int ch);
void tx4939_ata_init(void);
void tx4939_rtc_init(void);
+void tx4939_ndfmc_init(unsigned int hold, unsigned int spw,
+ unsigned char ch_mask, unsigned char wide_mask);
#endif /* __ASM_TXX9_TX4939_H */
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index a13a08b8c9ec..8a266c6a3f58 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -32,6 +32,7 @@
#include <asm/txx9/generic.h>
#include <asm/txx9/pci.h>
#include <asm/txx9tmr.h>
+#include <asm/txx9/ndfmc.h>
#ifdef CONFIG_CPU_TX49XX
#include <asm/txx9/tx4938.h>
#endif
@@ -691,6 +692,26 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr,
#endif
}
+void __init txx9_ndfmc_init(unsigned long baseaddr,
+ const struct txx9ndfmc_platform_data *pdata)
+{
+#if defined(CONFIG_MTD_NAND_TXX9NDFMC) || \
+ defined(CONFIG_MTD_NAND_TXX9NDFMC_MODULE)
+ struct resource res = {
+ .start = baseaddr,
+ .end = baseaddr + 0x1000 - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ struct platform_device *pdev = platform_device_alloc("txx9ndfmc", -1);
+
+ if (!pdev ||
+ platform_device_add_resources(pdev, &res, 1) ||
+ platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+ platform_device_add(pdev))
+ platform_device_put(pdev);
+#endif
+}
+
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
static DEFINE_SPINLOCK(txx9_iocled_lock);
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c
index 25819ff1c350..f0844f891f0b 100644
--- a/arch/mips/txx9/generic/setup_tx4938.c
+++ b/arch/mips/txx9/generic/setup_tx4938.c
@@ -23,6 +23,7 @@
#include <asm/txx9tmr.h>
#include <asm/txx9pio.h>
#include <asm/txx9/generic.h>
+#include <asm/txx9/ndfmc.h>
#include <asm/txx9/tx4938.h>
static void __init tx4938_wdr_init(void)
@@ -382,6 +383,26 @@ void __init tx4938_ata_init(unsigned int irq, unsigned int shift, int tune)
platform_device_put(pdev);
}
+void __init tx4938_ndfmc_init(unsigned int hold, unsigned int spw)
+{
+ struct txx9ndfmc_platform_data plat_data = {
+ .shift = 1,
+ .gbus_clock = txx9_gbus_clock,
+ .hold = hold,
+ .spw = spw,
+ .ch_mask = 1,
+ };
+ unsigned long baseaddr = TX4938_NDFMC_REG & 0xfffffffffULL;
+
+#ifdef __BIG_ENDIAN
+ baseaddr += 4;
+#endif
+ if ((__raw_readq(&tx4938_ccfgptr->pcfg) &
+ (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL)) ==
+ TX4938_PCFG_NDF_SEL)
+ txx9_ndfmc_init(baseaddr, &plat_data);
+}
+
static void __init tx4938_stop_unused_modules(void)
{
__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
index 55440967b3a8..7a25b573e9b0 100644
--- a/arch/mips/txx9/generic/setup_tx4939.c
+++ b/arch/mips/txx9/generic/setup_tx4939.c
@@ -27,6 +27,7 @@
#include <asm/txx9irq.h>
#include <asm/txx9tmr.h>
#include <asm/txx9/generic.h>
+#include <asm/txx9/ndfmc.h>
#include <asm/txx9/tx4939.h>
static void __init tx4939_wdr_init(void)
@@ -457,6 +458,22 @@ void __init tx4939_rtc_init(void)
platform_device_register(&rtc_dev);
}
+void __init tx4939_ndfmc_init(unsigned int hold, unsigned int spw,
+ unsigned char ch_mask, unsigned char wide_mask)
+{
+ struct txx9ndfmc_platform_data plat_data = {
+ .shift = 1,
+ .gbus_clock = txx9_gbus_clock,
+ .hold = hold,
+ .spw = spw,
+ .flags = NDFMC_PLAT_FLAG_NO_RSTR | NDFMC_PLAT_FLAG_HOLDADD |
+ NDFMC_PLAT_FLAG_DUMMYWRITE,
+ .ch_mask = ch_mask,
+ .wide_mask = wide_mask,
+ };
+ txx9_ndfmc_init(TX4939_NDFMC_REG & 0xfffffffffULL, &plat_data);
+}
+
static void __init tx4939_stop_unused_modules(void)
{
__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c
index 547ff2920bf0..65d13df8878a 100644
--- a/arch/mips/txx9/rbtx4938/setup.c
+++ b/arch/mips/txx9/rbtx4938/setup.c
@@ -352,6 +352,8 @@ static void __init rbtx4938_device_init(void)
rbtx4938_ne_init();
tx4938_wdt_init();
rbtx4938_mtd_init();
+ /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
+ tx4938_ndfmc_init(10, 35);
tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1);
txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL);
}
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c
index 656603b85b71..011e1e332f47 100644
--- a/arch/mips/txx9/rbtx4939/setup.c
+++ b/arch/mips/txx9/rbtx4939/setup.c
@@ -16,6 +16,9 @@
#include <linux/leds.h>
#include <linux/interrupt.h>
#include <linux/smc91x.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/map.h>
#include <asm/reboot.h>
#include <asm/txx9/generic.h>
#include <asm/txx9/pci.h>
@@ -282,6 +285,159 @@ static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val)
__rbtx4939_7segled_putc(pos, val);
}
+#if defined(CONFIG_MTD_RBTX4939) || defined(CONFIG_MTD_RBTX4939_MODULE)
+/* special mapping for boot rom */
+static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs)
+{
+ u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+ unsigned char shift;
+
+ if (bdipsw & 8) {
+ /* BOOT Mode: USER ROM1 / USER ROM2 */
+ shift = bdipsw & 3;
+ /* rotate A[23:22] */
+ return (ofs & ~0xc00000) | ((((ofs >> 22) + shift) & 3) << 22);
+ }
+#ifdef __BIG_ENDIAN
+ if (bdipsw == 0)
+ /* BOOT Mode: Monitor ROM */
+ ofs ^= 0x400000; /* swap A[22] */
+#endif
+ return ofs;
+}
+
+static map_word rbtx4939_flash_read16(struct map_info *map, unsigned long ofs)
+{
+ map_word r;
+
+ ofs = rbtx4939_flash_fixup_ofs(ofs);
+ r.x[0] = __raw_readw(map->virt + ofs);
+ return r;
+}
+
+static void rbtx4939_flash_write16(struct map_info *map, const map_word datum,
+ unsigned long ofs)
+{
+ ofs = rbtx4939_flash_fixup_ofs(ofs);
+ __raw_writew(datum.x[0], map->virt + ofs);
+ mb(); /* see inline_map_write() in mtd/map.h */
+}
+
+static void rbtx4939_flash_copy_from(struct map_info *map, void *to,
+ unsigned long from, ssize_t len)
+{
+ u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+ unsigned char shift;
+ ssize_t curlen;
+
+ from += (unsigned long)map->virt;
+ if (bdipsw & 8) {
+ /* BOOT Mode: USER ROM1 / USER ROM2 */
+ shift = bdipsw & 3;
+ while (len) {
+ curlen = min_t(unsigned long, len,
+ 0x400000 - (from & (0x400000 - 1)));
+ memcpy(to,
+ (void *)((from & ~0xc00000) |
+ ((((from >> 22) + shift) & 3) << 22)),
+ curlen);
+ len -= curlen;
+ from += curlen;
+ to += curlen;
+ }
+ return;
+ }
+#ifdef __BIG_ENDIAN
+ if (bdipsw == 0) {
+ /* BOOT Mode: Monitor ROM */
+ while (len) {
+ curlen = min_t(unsigned long, len,
+ 0x400000 - (from & (0x400000 - 1)));
+ memcpy(to, (void *)(from ^ 0x400000), curlen);
+ len -= curlen;
+ from += curlen;
+ to += curlen;
+ }
+ return;
+ }
+#endif
+ memcpy(to, (void *)from, len);
+}
+
+static void rbtx4939_flash_map_init(struct map_info *map)
+{
+ map->read = rbtx4939_flash_read16;
+ map->write = rbtx4939_flash_write16;
+ map->copy_from = rbtx4939_flash_copy_from;
+}
+
+static void __init rbtx4939_mtd_init(void)
+{
+ static struct {
+ struct platform_device dev;
+ struct resource res;
+ struct rbtx4939_flash_data data;
+ } pdevs[4];
+ int i;
+ static char names[4][8];
+ static struct mtd_partition parts[4];
+ struct rbtx4939_flash_data *boot_pdata = &pdevs[0].data;
+ u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+
+ if (bdipsw & 8) {
+ /* BOOT Mode: USER ROM1 / USER ROM2 */
+ boot_pdata->nr_parts = 4;
+ for (i = 0; i < boot_pdata->nr_parts; i++) {
+ sprintf(names[i], "img%d", 4 - i);
+ parts[i].name = names[i];
+ parts[i].size = 0x400000;
+ parts[i].offset = MTDPART_OFS_NXTBLK;
+ }
+ } else if (bdipsw == 0) {
+ /* BOOT Mode: Monitor ROM */
+ boot_pdata->nr_parts = 2;
+ strcpy(names[0], "big");
+ strcpy(names[1], "little");
+ for (i = 0; i < boot_pdata->nr_parts; i++) {
+ parts[i].name = names[i];
+ parts[i].size = 0x400000;
+ parts[i].offset = MTDPART_OFS_NXTBLK;
+ }
+ } else {
+ /* BOOT Mode: ROM Emulator */
+ boot_pdata->nr_parts = 2;
+ parts[0].name = "boot";
+ parts[0].offset = 0xc00000;
+ parts[0].size = 0x400000;
+ parts[1].name = "user";
+ parts[1].offset = 0;
+ parts[1].size = 0xc00000;
+ }
+ boot_pdata->parts = parts;
+ boot_pdata->map_init = rbtx4939_flash_map_init;
+
+ for (i = 0; i < ARRAY_SIZE(pdevs); i++) {
+ struct resource *r = &pdevs[i].res;
+ struct platform_device *dev = &pdevs[i].dev;
+
+ r->start = 0x1f000000 - i * 0x1000000;
+ r->end = r->start + 0x1000000 - 1;
+ r->flags = IORESOURCE_MEM;
+ pdevs[i].data.width = 2;
+ dev->num_resources = 1;
+ dev->resource = r;
+ dev->id = i;
+ dev->name = "rbtx4939-flash";
+ dev->dev.platform_data = &pdevs[i].data;
+ platform_device_register(dev);
+ }
+}
+#else
+static void __init rbtx4939_mtd_init(void)
+{
+}
+#endif
+
static void __init rbtx4939_arch_init(void)
{
rbtx4939_pci_setup();
@@ -333,6 +489,11 @@ static void __init rbtx4939_device_init(void)
platform_device_add_data(pdev, &smc_pdata, sizeof(smc_pdata)) ||
platform_device_add(pdev))
platform_device_put(pdev);
+ rbtx4939_mtd_init();
+ /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
+ tx4939_ndfmc_init(10, 35,
+ (1 << 1) | (1 << 2),
+ (1 << 2)); /* ch1:8bit, ch2:16bit */
rbtx4939_led_setup();
tx4939_wdt_init();
tx4939_ata_init();
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 28b1a95257cd..19aa72301c83 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -397,10 +397,13 @@
upm@3,0 {
#address-cells = <0>;
#size-cells = <0>;
- compatible = "fsl,upm-nand";
+ compatible = "tqc,tqm8548-upm-nand", "fsl,upm-nand";
reg = <3 0x0 0x800>;
fsl,upm-addr-offset = <0x10>;
fsl,upm-cmd-offset = <0x08>;
+ /* Micron MT29F8G08FAB multi-chip device */
+ fsl,upm-addr-line-cs-offsets = <0x0 0x200>;
+ fsl,upm-wait-flags = <0x5>;
chip-delay = <25>; // in micro-seconds
nand@0 {
@@ -409,7 +412,7 @@
partition@0 {
label = "fs";
- reg = <0x00000000 0x01000000>;
+ reg = <0x00000000 0x10000000>;
};
};
};
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index 826fb622cd3c..49145a04fc6c 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -397,10 +397,13 @@
upm@3,0 {
#address-cells = <0>;
#size-cells = <0>;
- compatible = "fsl,upm-nand";
+ compatible = "tqc,tqm8548-upm-nand", "fsl,upm-nand";
reg = <3 0x0 0x800>;
fsl,upm-addr-offset = <0x10>;
fsl,upm-cmd-offset = <0x08>;
+ /* Micron MT29F8G08FAB multi-chip device */
+ fsl,upm-addr-line-cs-offsets = <0x0 0x200>;
+ fsl,upm-wait-flags = <0x5>;
chip-delay = <25>; // in micro-seconds
nand@0 {
@@ -409,7 +412,7 @@
partition@0 {
label = "fs";
- reg = <0x00000000 0x01000000>;
+ reg = <0x00000000 0x10000000>;
};
};
};
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index 0494ee55920f..dceb8d1a843d 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -150,7 +150,7 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
spin_lock_irqsave(&fsl_lbc_lock, flags);
- out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+ out_be32(&fsl_lbc_regs->mar, mar);
switch (upm->width) {
case 8:
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bcf4cae711b4..6da24fc6a09e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -253,6 +253,7 @@ config SMP
config X86_X2APIC
bool "Support x2apic"
depends on X86_LOCAL_APIC && X86_64
+ select INTR_REMAP
---help---
This enables x2apic support on CPUs that have this feature.
@@ -1882,7 +1883,6 @@ config DMAR_FLOPPY_WA
config INTR_REMAP
bool "Support for Interrupt Remapping (EXPERIMENTAL)"
depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
- select X86_X2APIC
---help---
Supports Interrupt remapping for IO-APIC and MSI devices.
To use x2apic mode in the CPU's which support x2APIC enhancements or
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index df8a300dfe6c..42f2f8377422 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -107,6 +107,9 @@ extern u32 native_safe_apic_wait_icr_idle(void);
extern void native_apic_icr_write(u32 low, u32 id);
extern u64 native_apic_icr_read(void);
+#define EIM_8BIT_APIC_ID 0
+#define EIM_32BIT_APIC_ID 1
+
#ifdef CONFIG_X86_X2APIC
/*
* Make previous memory operations globally visible before
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 373cc2bbcad2..9d826e436010 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -162,10 +162,13 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);
#ifdef CONFIG_X86_64
-extern int save_IO_APIC_setup(void);
-extern void mask_IO_APIC_setup(void);
-extern void restore_IO_APIC_setup(void);
-extern void reinit_intr_remapped_IO_APIC(int);
+extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
+extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
+extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
+extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
+extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
+extern void reinit_intr_remapped_IO_APIC(int intr_remapping,
+ struct IO_APIC_route_entry **ioapic_entries);
#endif
extern void probe_nr_irqs_gsi(void);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b0e5e712a7af..fb504f843e58 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1308,6 +1308,7 @@ void __init enable_IR_x2apic(void)
#ifdef CONFIG_INTR_REMAP
int ret;
unsigned long flags;
+ struct IO_APIC_route_entry **ioapic_entries = NULL;
if (!cpu_has_x2apic)
return;
@@ -1338,17 +1339,23 @@ void __init enable_IR_x2apic(void)
return;
}
- ret = save_IO_APIC_setup();
+ ioapic_entries = alloc_ioapic_entries();
+ if (!ioapic_entries) {
+ pr_info("Allocate ioapic_entries failed: %d\n", ret);
+ goto end;
+ }
+
+ ret = save_IO_APIC_setup(ioapic_entries);
if (ret) {
pr_info("Saving IO-APIC state failed: %d\n", ret);
goto end;
}
local_irq_save(flags);
- mask_IO_APIC_setup();
+ mask_IO_APIC_setup(ioapic_entries);
mask_8259A();
- ret = enable_intr_remapping(1);
+ ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
if (ret && x2apic_preenabled) {
local_irq_restore(flags);
@@ -1368,9 +1375,9 @@ end_restore:
/*
* IR enabling failed
*/
- restore_IO_APIC_setup();
+ restore_IO_APIC_setup(ioapic_entries);
else
- reinit_intr_remapped_IO_APIC(x2apic_preenabled);
+ reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
unmask_8259A();
local_irq_restore(flags);
@@ -1383,6 +1390,8 @@ end:
pr_info("Enabled Interrupt-remapping\n");
} else
pr_err("Failed to enable Interrupt-remapping and x2apic\n");
+ if (ioapic_entries)
+ free_ioapic_entries(ioapic_entries);
#else
if (!cpu_has_x2apic)
return;
@@ -1958,6 +1967,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
local_irq_save(flags);
disable_local_APIC();
+#ifdef CONFIG_INTR_REMAP
+ if (intr_remapping_enabled)
+ disable_intr_remapping();
+#endif
local_irq_restore(flags);
return 0;
}
@@ -1968,15 +1981,41 @@ static int lapic_resume(struct sys_device *dev)
unsigned long flags;
int maxlvt;
+#ifdef CONFIG_INTR_REMAP
+ int ret;
+ struct IO_APIC_route_entry **ioapic_entries = NULL;
+
if (!apic_pm_state.active)
return 0;
- maxlvt = lapic_get_maxlvt();
-
local_irq_save(flags);
+ if (x2apic) {
+ ioapic_entries = alloc_ioapic_entries();
+ if (!ioapic_entries) {
+ WARN(1, "Alloc ioapic_entries in lapic resume failed.");
+ return -ENOMEM;
+ }
+
+ ret = save_IO_APIC_setup(ioapic_entries);
+ if (ret) {
+ WARN(1, "Saving IO-APIC state failed: %d\n", ret);
+ free_ioapic_entries(ioapic_entries);
+ return ret;
+ }
+
+ mask_IO_APIC_setup(ioapic_entries);
+ mask_8259A();
+ enable_x2apic();
+ }
+#else
+ if (!apic_pm_state.active)
+ return 0;
+ local_irq_save(flags);
if (x2apic)
enable_x2apic();
+#endif
+
else {
/*
* Make sure the APICBASE points to the right address
@@ -1990,6 +2029,7 @@ static int lapic_resume(struct sys_device *dev)
wrmsr(MSR_IA32_APICBASE, l, h);
}
+ maxlvt = lapic_get_maxlvt();
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
apic_write(APIC_ID, apic_pm_state.apic_id);
apic_write(APIC_DFR, apic_pm_state.apic_dfr);
@@ -2013,8 +2053,20 @@ static int lapic_resume(struct sys_device *dev)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
+#ifdef CONFIG_INTR_REMAP
+ if (intr_remapping_enabled)
+ reenable_intr_remapping(EIM_32BIT_APIC_ID);
+
+ if (x2apic) {
+ unmask_8259A();
+ restore_IO_APIC_setup(ioapic_entries);
+ free_ioapic_entries(ioapic_entries);
+ }
+#endif
+
local_irq_restore(flags);
+
return 0;
}
@@ -2052,7 +2104,9 @@ static int __init init_lapic_sysfs(void)
error = sysdev_register(&device_lapic);
return error;
}
-device_initcall(init_lapic_sysfs);
+
+/* local apic needs to resume before other devices access its registers. */
+core_initcall(init_lapic_sysfs);
#else /* CONFIG_PM */
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 1bb5c6cee3eb..767fe7e46d68 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -851,63 +851,74 @@ __setup("pirq=", ioapic_pirq_setup);
#endif /* CONFIG_X86_32 */
#ifdef CONFIG_INTR_REMAP
-/* I/O APIC RTE contents at the OS boot up */
-static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
+struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+{
+ int apic;
+ struct IO_APIC_route_entry **ioapic_entries;
+
+ ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
+ GFP_ATOMIC);
+ if (!ioapic_entries)
+ return 0;
+
+ for (apic = 0; apic < nr_ioapics; apic++) {
+ ioapic_entries[apic] =
+ kzalloc(sizeof(struct IO_APIC_route_entry) *
+ nr_ioapic_registers[apic], GFP_ATOMIC);
+ if (!ioapic_entries[apic])
+ goto nomem;
+ }
+
+ return ioapic_entries;
+
+nomem:
+ while (--apic >= 0)
+ kfree(ioapic_entries[apic]);
+ kfree(ioapic_entries);
+
+ return 0;
+}
/*
* Saves all the IO-APIC RTE's
*/
-int save_IO_APIC_setup(void)
+int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
{
- union IO_APIC_reg_01 reg_01;
- unsigned long flags;
int apic, pin;
- /*
- * The number of IO-APIC IRQ registers (== #pins):
- */
- for (apic = 0; apic < nr_ioapics; apic++) {
- spin_lock_irqsave(&ioapic_lock, flags);
- reg_01.raw = io_apic_read(apic, 1);
- spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[apic] = reg_01.bits.entries+1;
- }
+ if (!ioapic_entries)
+ return -ENOMEM;
for (apic = 0; apic < nr_ioapics; apic++) {
- early_ioapic_entries[apic] =
- kzalloc(sizeof(struct IO_APIC_route_entry) *
- nr_ioapic_registers[apic], GFP_KERNEL);
- if (!early_ioapic_entries[apic])
- goto nomem;
- }
+ if (!ioapic_entries[apic])
+ return -ENOMEM;
- for (apic = 0; apic < nr_ioapics; apic++)
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
- early_ioapic_entries[apic][pin] =
+ ioapic_entries[apic][pin] =
ioapic_read_entry(apic, pin);
+ }
return 0;
-
-nomem:
- while (apic >= 0)
- kfree(early_ioapic_entries[apic--]);
- memset(early_ioapic_entries, 0,
- ARRAY_SIZE(early_ioapic_entries));
-
- return -ENOMEM;
}
-void mask_IO_APIC_setup(void)
+/*
+ * Mask all IO APIC entries.
+ */
+void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
{
int apic, pin;
+ if (!ioapic_entries)
+ return;
+
for (apic = 0; apic < nr_ioapics; apic++) {
- if (!early_ioapic_entries[apic])
+ if (!ioapic_entries[apic])
break;
+
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
- entry = early_ioapic_entries[apic][pin];
+ entry = ioapic_entries[apic][pin];
if (!entry.mask) {
entry.mask = 1;
ioapic_write_entry(apic, pin, entry);
@@ -916,22 +927,30 @@ void mask_IO_APIC_setup(void)
}
}
-void restore_IO_APIC_setup(void)
+/*
+ * Restore IO APIC entries which was saved in ioapic_entries.
+ */
+int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
{
int apic, pin;
+ if (!ioapic_entries)
+ return -ENOMEM;
+
for (apic = 0; apic < nr_ioapics; apic++) {
- if (!early_ioapic_entries[apic])
- break;
+ if (!ioapic_entries[apic])
+ return -ENOMEM;
+
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
ioapic_write_entry(apic, pin,
- early_ioapic_entries[apic][pin]);
- kfree(early_ioapic_entries[apic]);
- early_ioapic_entries[apic] = NULL;
+ ioapic_entries[apic][pin]);
}
+ return 0;
}
-void reinit_intr_remapped_IO_APIC(int intr_remapping)
+void reinit_intr_remapped_IO_APIC(int intr_remapping,
+ struct IO_APIC_route_entry **ioapic_entries)
+
{
/*
* for now plain restore of previous settings.
@@ -940,7 +959,17 @@ void reinit_intr_remapped_IO_APIC(int intr_remapping)
* table entries. for now, do a plain restore, and wait for
* the setup_IO_APIC_irqs() to do proper initialization.
*/
- restore_IO_APIC_setup();
+ restore_IO_APIC_setup(ioapic_entries);
+}
+
+void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
+{
+ int apic;
+
+ for (apic = 0; apic < nr_ioapics; apic++)
+ kfree(ioapic_entries[apic]);
+
+ kfree(ioapic_entries);
}
#endif
@@ -2495,7 +2524,7 @@ static void irq_complete_move(struct irq_desc **descp)
static inline void irq_complete_move(struct irq_desc **descp) {}
#endif
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_X86_X2APIC
static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
{
int apic, pin;
@@ -2540,7 +2569,6 @@ static void ack_x2apic_edge(unsigned int irq)
{
ack_x2APIC_irq();
}
-
#endif
static void ack_apic_edge(unsigned int irq)
@@ -2651,6 +2679,26 @@ static void ack_apic_level(unsigned int irq)
#endif
}
+#ifdef CONFIG_INTR_REMAP
+static void ir_ack_apic_edge(unsigned int irq)
+{
+#ifdef CONFIG_X86_X2APIC
+ if (x2apic_enabled())
+ return ack_x2apic_edge(irq);
+#endif
+ return ack_apic_edge(irq);
+}
+
+static void ir_ack_apic_level(unsigned int irq)
+{
+#ifdef CONFIG_X86_X2APIC
+ if (x2apic_enabled())
+ return ack_x2apic_level(irq);
+#endif
+ return ack_apic_level(irq);
+}
+#endif /* CONFIG_INTR_REMAP */
+
static struct irq_chip ioapic_chip __read_mostly = {
.name = "IO-APIC",
.startup = startup_ioapic_irq,
@@ -2670,8 +2718,8 @@ static struct irq_chip ir_ioapic_chip __read_mostly = {
.mask = mask_IO_APIC_irq,
.unmask = unmask_IO_APIC_irq,
#ifdef CONFIG_INTR_REMAP
- .ack = ack_x2apic_edge,
- .eoi = ack_x2apic_level,
+ .ack = ir_ack_apic_edge,
+ .eoi = ir_ack_apic_level,
#ifdef CONFIG_SMP
.set_affinity = set_ir_ioapic_affinity_irq,
#endif
@@ -3397,7 +3445,7 @@ static struct irq_chip msi_ir_chip = {
.unmask = unmask_msi_irq,
.mask = mask_msi_irq,
#ifdef CONFIG_INTR_REMAP
- .ack = ack_x2apic_edge,
+ .ack = ir_ack_apic_edge,
#ifdef CONFIG_SMP
.set_affinity = ir_set_msi_irq_affinity,
#endif