summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-04-29 17:07:03 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-29 17:07:03 -0700
commite0a515bc6a2188f02916e976f419a8640312e32a (patch)
treedd8f4f64cffe37725000c7a80d4b2b973c69f65a /arch
parent991cef7be26ce78fe2bac72bedaf89e002cc2712 (diff)
parent6fb8f3acbe833586eb32598d1f844eb9f77c4fba (diff)
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [PATCH] powerpc: update cell_defconfig [PATCH] spufs: Disable local interrupts for SPE hash_page calls. [PATCH] powerpc: Add cputable entry for POWER6 [PATCH] ppc32 CPM_UART: Fixed odd address translations [PATCH] ppc32: Update board-specific code of the CPM UART users [PATCH] ppc32 CPM_UART: Convert to use platform devices [PATCH] ppc32: odd fixes and improvements in ppc_sys [PATCH] powerpc: Wire up *at syscalls [PATCH] ppc32: add 440GX erratum 440_43 workaround [PATCH] powerpc: Use check_legacy_ioport() on ppc32 too. [PATCH] powerpc64: Fix loading of modules without a .toc section [PATCH] sound/ppc: snd_pmac_toonie_init should be __init powerpc/pseries: Tell firmware our capabilities on new machines [PATCH] powerpc: Fix pagetable bloat for hugepages
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/configs/cell_defconfig40
-rw-r--r--arch/powerpc/kernel/cputable.c16
-rw-r--r--arch/powerpc/kernel/module_64.c16
-rw-r--r--arch/powerpc/kernel/prom_init.c112
-rw-r--r--arch/powerpc/kernel/setup-common.c8
-rw-r--r--arch/powerpc/kernel/setup_64.c8
-rw-r--r--arch/powerpc/kernel/systbl.S13
-rw-r--r--arch/powerpc/mm/hugetlbpage.c295
-rw-r--r--arch/powerpc/mm/init_64.c7
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c10
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c13
-rw-r--r--arch/ppc/platforms/4xx/ocotea.c2
-rw-r--r--arch/ppc/platforms/mpc8272ads_setup.c114
-rw-r--r--arch/ppc/platforms/mpc866ads_setup.c140
-rw-r--r--arch/ppc/platforms/mpc885ads_setup.c131
-rw-r--r--arch/ppc/platforms/pq2ads.c31
-rw-r--r--arch/ppc/syslib/ibm440gx_common.c13
-rw-r--r--arch/ppc/syslib/ibm440gx_common.h4
-rw-r--r--arch/ppc/syslib/mpc8xx_devices.c25
-rw-r--r--arch/ppc/syslib/ppc_sys.c4
-rw-r--r--arch/ppc/syslib/pq2_sys.c8
21 files changed, 926 insertions, 84 deletions
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index fe22e54ab2b..dbe421dc3c1 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -55,6 +56,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +71,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +82,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -93,6 +90,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -126,6 +124,7 @@ CONFIG_RTAS_FLASH=y
CONFIG_MMIO_NVRAM=y
CONFIG_CELL_IIC=y
# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
@@ -167,7 +166,6 @@ CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
@@ -184,7 +182,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -226,6 +223,7 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -242,6 +240,7 @@ CONFIG_IPV6=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -632,6 +631,7 @@ CONFIG_SERIAL_NONSTANDARD=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -717,7 +717,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -736,9 +735,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -766,10 +763,6 @@ CONFIG_I2C_ALGOBIT=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -818,6 +811,19 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=y
@@ -834,6 +840,11 @@ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -889,7 +900,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 39e348a3ade..3f7182db9ed 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -57,6 +57,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
+ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
@@ -263,6 +265,20 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power5+",
},
+ { /* Power6 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003e0000,
+ .cpu_name = "POWER6",
+ .cpu_features = CPU_FTRS_POWER6,
+ .cpu_user_features = COMMON_USER_POWER6,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_power4,
+ .oprofile_cpu_type = "ppc64/power6",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power6",
+ },
{ /* Cell Broadband Engine */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00700000,
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 928b8581fcb..ba34001fca8 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -191,11 +191,19 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
(void *)hdr
+ sechdrs[sechdrs[i].sh_link].sh_offset);
}
- if (!me->arch.stubs_section || !me->arch.toc_section) {
- printk("%s: doesn't contain .toc or .stubs.\n", me->name);
+
+ if (!me->arch.stubs_section) {
+ printk("%s: doesn't contain .stubs.\n", me->name);
return -ENOEXEC;
}
+ /* If we don't have a .toc, just use .stubs. We need to set r2
+ to some reasonable value in case the module calls out to
+ other functions via a stub, or if a function pointer escapes
+ the module by some means. */
+ if (!me->arch.toc_section)
+ me->arch.toc_section = me->arch.stubs_section;
+
/* Override the stubs size */
sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
return 0;
@@ -342,7 +350,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_PPC64_TOC16:
- /* Subtact TOC pointer */
+ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me);
if (value + 0x8000 > 0xffff) {
printk("%s: bad TOC16 relocation (%lu)\n",
@@ -355,7 +363,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_PPC64_TOC16_DS:
- /* Subtact TOC pointer */
+ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me);
if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
printk("%s: bad TOC16_DS relocation (%lu)\n",
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 7e4d54821a0..078fb553354 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -636,10 +636,96 @@ static void __init early_cmdline_parse(void)
#ifdef CONFIG_PPC_PSERIES
/*
- * To tell the firmware what our capabilities are, we have to pass
- * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
- * that contain structures that contain the actual values.
+ * There are two methods for telling firmware what our capabilities are.
+ * Newer machines have an "ibm,client-architecture-support" method on the
+ * root node. For older machines, we have to call the "process-elf-header"
+ * method in the /packages/elf-loader node, passing it a fake 32-bit
+ * ELF header containing a couple of PT_NOTE sections that contain
+ * structures that contain various information.
*/
+
+/*
+ * New method - extensible architecture description vector.
+ *
+ * Because the description vector contains a mix of byte and word
+ * values, we declare it as an unsigned char array, and use this
+ * macro to put word values in.
+ */
+#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
+ ((x) >> 8) & 0xff, (x) & 0xff
+
+/* Option vector bits - generic bits in byte 1 */
+#define OV_IGNORE 0x80 /* ignore this vector */
+#define OV_CESSATION_POLICY 0x40 /* halt if unsupported option present*/
+
+/* Option vector 1: processor architectures supported */
+#define OV1_PPC_2_00 0x80 /* set if we support PowerPC 2.00 */
+#define OV1_PPC_2_01 0x40 /* set if we support PowerPC 2.01 */
+#define OV1_PPC_2_02 0x20 /* set if we support PowerPC 2.02 */
+#define OV1_PPC_2_03 0x10 /* set if we support PowerPC 2.03 */
+#define OV1_PPC_2_04 0x08 /* set if we support PowerPC 2.04 */
+#define OV1_PPC_2_05 0x04 /* set if we support PowerPC 2.05 */
+
+/* Option vector 2: Open Firmware options supported */
+#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */
+
+/* Option vector 3: processor options supported */
+#define OV3_FP 0x80 /* floating point */
+#define OV3_VMX 0x40 /* VMX/Altivec */
+
+/* Option vector 5: PAPR/OF options supported */
+#define OV5_LPAR 0x80 /* logical partitioning supported */
+#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */
+/* ibm,dynamic-reconfiguration-memory property supported */
+#define OV5_DRCONF_MEMORY 0x20
+#define OV5_LARGE_PAGES 0x10 /* large pages supported */
+
+/*
+ * The architecture vector has an array of PVR mask/value pairs,
+ * followed by # option vectors - 1, followed by the option vectors.
+ */
+static unsigned char ibm_architecture_vec[] = {
+ W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
+ W(0xffff0000), W(0x003e0000), /* POWER6 */
+ W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
+ 5 - 1, /* 5 option vectors */
+
+ /* option vector 1: processor architectures supported */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
+ OV1_PPC_2_04 | OV1_PPC_2_05,
+
+ /* option vector 2: Open Firmware options supported */
+ 34 - 1, /* length */
+ OV2_REAL_MODE,
+ 0, 0,
+ W(0xffffffff), /* real_base */
+ W(0xffffffff), /* real_size */
+ W(0xffffffff), /* virt_base */
+ W(0xffffffff), /* virt_size */
+ W(0xffffffff), /* load_base */
+ W(64), /* 128MB min RMA */
+ W(0xffffffff), /* full client load */
+ 0, /* min RMA percentage of total RAM */
+ 48, /* max log_2(hash table size) */
+
+ /* option vector 3: processor options supported */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV3_FP | OV3_VMX,
+
+ /* option vector 4: IBM PAPR implementation */
+ 2 - 1, /* length */
+ 0, /* don't halt */
+
+ /* option vector 5: PAPR/OF options */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
+};
+
+/* Old method - ELF header with PT_NOTE sections */
static struct fake_elf {
Elf32_Ehdr elfhdr;
Elf32_Phdr phdr[2];
@@ -728,8 +814,26 @@ static struct fake_elf {
static void __init prom_send_capabilities(void)
{
- ihandle elfloader;
+ ihandle elfloader, root;
+ prom_arg_t ret;
+
+ root = call_prom("open", 1, 1, ADDR("/"));
+ if (root != 0) {
+ /* try calling the ibm,client-architecture-support method */
+ if (call_prom_ret("call-method", 3, 2, &ret,
+ ADDR("ibm,client-architecture-support"),
+ ADDR(ibm_architecture_vec)) == 0) {
+ /* the call exists... */
+ if (ret)
+ prom_printf("WARNING: ibm,client-architecture"
+ "-support call FAILED!\n");
+ call_prom("close", 1, 0, root);
+ return;
+ }
+ call_prom("close", 1, 0, root);
+ }
+ /* no ibm,client-architecture-support call, try the old way */
elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
if (elfloader == 0) {
prom_printf("couldn't open /packages/elf-loader\n");
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 1d93e73a700..684ab1d49c6 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -516,3 +516,11 @@ void probe_machine(void)
printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
}
+
+int check_legacy_ioport(unsigned long base_port)
+{
+ if (ppc_md.check_legacy_ioport == NULL)
+ return 0;
+ return ppc_md.check_legacy_ioport(base_port);
+}
+EXPORT_SYMBOL(check_legacy_ioport);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 13e91c4d70a..4467c49903b 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -594,14 +594,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
printk("[terminate]%04x %s\n", src, msg);
}
-int check_legacy_ioport(unsigned long base_port)
-{
- if (ppc_md.check_legacy_ioport == NULL)
- return 0;
- return ppc_md.check_legacy_ioport(base_port);
-}
-EXPORT_SYMBOL(check_legacy_ioport);
-
void cpu_die(void)
{
if (ppc_md.cpu_die)
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 0b98eea73c5..cf56a1d499f 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -325,6 +325,19 @@ SYSCALL(unshare)
SYSCALL(splice)
SYSCALL(tee)
SYSCALL(vmsplice)
+COMPAT_SYS(openat)
+SYSCALL(mkdirat)
+SYSCALL(mknodat)
+SYSCALL(fchownat)
+COMPAT_SYS(futimesat)
+SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64)
+SYSCALL(unlinkat)
+SYSCALL(renameat)
+SYSCALL(linkat)
+SYSCALL(symlinkat)
+SYSCALL(readlinkat)
+SYSCALL(fchmodat)
+SYSCALL(faccessat)
/*
* please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 7370f9f33e2..266b8b2ceac 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -30,13 +30,66 @@
#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
+#ifdef CONFIG_PPC_64K_PAGES
+#define HUGEPTE_INDEX_SIZE (PMD_SHIFT-HPAGE_SHIFT)
+#else
+#define HUGEPTE_INDEX_SIZE (PUD_SHIFT-HPAGE_SHIFT)
+#endif
+#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)
+#define HUGEPTE_TABLE_SIZE (sizeof(pte_t) << HUGEPTE_INDEX_SIZE)
+
+#define HUGEPD_SHIFT (HPAGE_SHIFT + HUGEPTE_INDEX_SIZE)
+#define HUGEPD_SIZE (1UL << HUGEPD_SHIFT)
+#define HUGEPD_MASK (~(HUGEPD_SIZE-1))
+
+#define huge_pgtable_cache (pgtable_cache[HUGEPTE_CACHE_NUM])
+
+/* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad()
+ * will choke on pointers to hugepte tables, which is handy for
+ * catching screwups early. */
+#define HUGEPD_OK 0x1
+
+typedef struct { unsigned long pd; } hugepd_t;
+
+#define hugepd_none(hpd) ((hpd).pd == 0)
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+ BUG_ON(!(hpd.pd & HUGEPD_OK));
+ return (pte_t *)(hpd.pd & ~HUGEPD_OK);
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr)
+{
+ unsigned long idx = ((addr >> HPAGE_SHIFT) & (PTRS_PER_HUGEPTE-1));
+ pte_t *dir = hugepd_page(*hpdp);
+
+ return dir + idx;
+}
+
+static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
+ unsigned long address)
+{
+ pte_t *new = kmem_cache_alloc(huge_pgtable_cache,
+ GFP_KERNEL|__GFP_REPEAT);
+
+ if (! new)
+ return -ENOMEM;
+
+ spin_lock(&mm->page_table_lock);
+ if (!hugepd_none(*hpdp))
+ kmem_cache_free(huge_pgtable_cache, new);
+ else
+ hpdp->pd = (unsigned long)new | HUGEPD_OK;
+ spin_unlock(&mm->page_table_lock);
+ return 0;
+}
+
/* Modelled after find_linux_pte() */
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pg;
pud_t *pu;
- pmd_t *pm;
- pte_t *pt;
BUG_ON(! in_hugepage_area(mm->context, addr));
@@ -46,26 +99,14 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
if (!pgd_none(*pg)) {
pu = pud_offset(pg, addr);
if (!pud_none(*pu)) {
- pm = pmd_offset(pu, addr);
#ifdef CONFIG_PPC_64K_PAGES
- /* Currently, we use the normal PTE offset within full
- * size PTE pages, thus our huge PTEs are scattered in
- * the PTE page and we do waste some. We may change
- * that in the future, but the current mecanism keeps
- * things much simpler
- */
- if (!pmd_none(*pm)) {
- /* Note: pte_offset_* are all equivalent on
- * ppc64 as we don't have HIGHMEM
- */
- pt = pte_offset_kernel(pm, addr);
- return pt;
- }
-#else /* CONFIG_PPC_64K_PAGES */
- /* On 4k pages, we put huge PTEs in the PMD page */
- pt = (pte_t *)pm;
- return pt;
-#endif /* CONFIG_PPC_64K_PAGES */
+ pmd_t *pm;
+ pm = pmd_offset(pu, addr);
+ if (!pmd_none(*pm))
+ return hugepte_offset((hugepd_t *)pm, addr);
+#else
+ return hugepte_offset((hugepd_t *)pu, addr);
+#endif
}
}
@@ -76,8 +117,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pg;
pud_t *pu;
- pmd_t *pm;
- pte_t *pt;
+ hugepd_t *hpdp = NULL;
BUG_ON(! in_hugepage_area(mm->context, addr));
@@ -87,23 +127,182 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
pu = pud_alloc(mm, pg, addr);
if (pu) {
+#ifdef CONFIG_PPC_64K_PAGES
+ pmd_t *pm;
pm = pmd_alloc(mm, pu, addr);
- if (pm) {
+ if (pm)
+ hpdp = (hugepd_t *)pm;
+#else
+ hpdp = (hugepd_t *)pu;
+#endif
+ }
+
+ if (! hpdp)
+ return NULL;
+
+ if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr))
+ return NULL;
+
+ return hugepte_offset(hpdp, addr);
+}
+
+static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp)
+{
+ pte_t *hugepte = hugepd_page(*hpdp);
+
+ hpdp->pd = 0;
+ tlb->need_flush = 1;
+ pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
+ HUGEPTE_TABLE_SIZE-1));
+}
+
#ifdef CONFIG_PPC_64K_PAGES
- /* See comment in huge_pte_offset. Note that if we ever
- * want to put the page size in the PMD, we would have
- * to open code our own pte_alloc* function in order
- * to populate and set the size atomically
- */
- pt = pte_alloc_map(mm, pm, addr);
-#else /* CONFIG_PPC_64K_PAGES */
- pt = (pte_t *)pm;
-#endif /* CONFIG_PPC_64K_PAGES */
- return pt;
- }
+static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pmd_t *pmd;
+ unsigned long next;
+ unsigned long start;
+
+ start = addr;
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_none(*pmd))
+ continue;
+ free_hugepte_range(tlb, (hugepd_t *)pmd);
+ } while (pmd++, addr = next, addr != end);
+
+ start &= PUD_MASK;
+ if (start < floor)
+ return;
+ if (ceiling) {
+ ceiling &= PUD_MASK;
+ if (!ceiling)
+ return;
}
+ if (end - 1 > ceiling - 1)
+ return;
- return NULL;
+ pmd = pmd_offset(pud, start);
+ pud_clear(pud);
+ pmd_free_tlb(tlb, pmd);
+}
+#endif
+
+static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pud_t *pud;
+ unsigned long next;
+ unsigned long start;
+
+ start = addr;
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+#ifdef CONFIG_PPC_64K_PAGES
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+#else
+ if (pud_none(*pud))
+ continue;
+ free_hugepte_range(tlb, (hugepd_t *)pud);
+#endif
+ } while (pud++, addr = next, addr != end);
+
+ start &= PGDIR_MASK;
+ if (start < floor)
+ return;
+ if (ceiling) {
+ ceiling &= PGDIR_MASK;
+ if (!ceiling)
+ return;
+ }
+ if (end - 1 > ceiling - 1)
+ return;
+
+ pud = pud_offset(pgd, start);
+ pgd_clear(pgd);
+ pud_free_tlb(tlb, pud);
+}
+
+/*
+ * This function frees user-level page tables of a process.
+ *
+ * Must be called with pagetable lock held.
+ */
+void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pgd_t *pgd;
+ unsigned long next;
+ unsigned long start;
+
+ /*
+ * Comments below take from the normal free_pgd_range(). They
+ * apply here too. The tests against HUGEPD_MASK below are
+ * essential, because we *don't* test for this at the bottom
+ * level. Without them we'll attempt to free a hugepte table
+ * when we unmap just part of it, even if there are other
+ * active mappings using it.
+ *
+ * The next few lines have given us lots of grief...
+ *
+ * Why are we testing HUGEPD* at this top level? Because
+ * often there will be no work to do at all, and we'd prefer
+ * not to go all the way down to the bottom just to discover
+ * that.
+ *
+ * Why all these "- 1"s? Because 0 represents both the bottom
+ * of the address space and the top of it (using -1 for the
+ * top wouldn't help much: the masks would do the wrong thing).
+ * The rule is that addr 0 and floor 0 refer to the bottom of
+ * the address space, but end 0 and ceiling 0 refer to the top
+ * Comparisons need to use "end - 1" and "ceiling - 1" (though
+ * that end 0 case should be mythical).
+ *
+ * Wherever addr is brought up or ceiling brought down, we
+ * must be careful to reject "the opposite 0" before it
+ * confuses the subsequent tests. But what about where end is
+ * brought down by HUGEPD_SIZE below? no, end can't go down to
+ * 0 there.
+ *
+ * Whereas we round start (addr) and ceiling down, by different
+ * masks at different levels, in order to test whether a table
+ * now has no other vmas using it, so can be freed, we don't
+ * bother to round floor or end up - the tests don't need that.
+ */
+
+ addr &= HUGEPD_MASK;
+ if (addr < floor) {
+ addr += HUGEPD_SIZE;
+ if (!addr)
+ return;
+ }
+ if (ceiling) {
+ ceiling &= HUGEPD_MASK;
+ if (!ceiling)
+ return;
+ }
+ if (end - 1 > ceiling - 1)
+ end -= HUGEPD_SIZE;
+ if (addr > end - 1)
+ return;
+
+ start = addr;
+ pgd = pgd_offset((*tlb)->mm, addr);
+ do {
+ BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr));
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ hugetlb_free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+ } while (pgd++, addr = next, addr != end);
}
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
@@ -841,3 +1040,27 @@ repeat:
out:
return err;
}
+
+static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+{
+ memset(addr, 0, kmem_cache_size(cache));
+}
+
+static int __init hugetlbpage_init(void)
+{
+ if (!cpu_has_feature(CPU_FTR_16M_PAGE))
+ return -ENODEV;
+
+ huge_pgtable_cache = kmem_cache_create("hugepte_cache",
+ HUGEPTE_TABLE_SIZE,
+ HUGEPTE_TABLE_SIZE,
+ SLAB_HWCACHE_ALIGN |
+ SLAB_MUST_HWCACHE_ALIGN,
+ zero_ctor, NULL);
+ if (! huge_pgtable_cache)
+ panic("hugetlbpage_init(): could not create hugepte cache\n");
+
+ return 0;
+}
+
+module_init(hugetlbpage_init);
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index babebd15bdc..9e30f968c18 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -162,7 +162,14 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
};
#endif /* CONFIG_PPC_64K_PAGES */
+#ifdef CONFIG_HUGETLB_PAGE
+/* Hugepages need one extra cache, initialized in hugetlbpage.c. We
+ * can't put into the tables above, because HPAGE_SHIFT is not compile
+ * time constant. */
+kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
+#else
kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
+#endif
void pgtable_cache_init(void)
{
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 269dda4fd0b..ef47a6239d4 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -306,19 +306,19 @@ spu_request_irqs(struct spu *spu)
snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
ret = request_irq(irq_base + spu->isrc,
- spu_irq_class_0, 0, spu->irq_c0, spu);
+ spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu);
if (ret)
goto out;
snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_1, 0, spu->irq_c1, spu);
+ spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu);
if (ret)
goto out1;
snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_2, 0, spu->irq_c2, spu);
+ spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu);
if (ret)
goto out2;
goto out;
@@ -487,10 +487,14 @@ int spu_irq_class_1_bottom(struct spu *spu)
ea = spu->dar;
dsisr = spu->dsisr;
if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
+ u64 flags;
+
access = (_PAGE_PRESENT | _PAGE_USER);
access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+ local_irq_save(flags);
if (hash_page(ea, access, 0x300) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ local_irq_restore(flags);
}
if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
if ((ret = spu_handle_mm_fault(spu)) != 0)
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index b283380a2a1..95b36430aa0 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -319,6 +319,19 @@ void *spu_syscall_table[] = {
[__NR_splice] sys_splice,
[__NR_tee] sys_tee,
[__NR_vmsplice] sys_vmsplice,
+ [__NR_openat] sys_openat,
+ [__NR_mkdirat] sys_mkdirat,
+ [__NR_mknodat] sys_mknodat,
+ [__NR_fchownat] sys_fchownat,
+ [__NR_futimesat] sys_futimesat,
+ [__NR_newfstatat] sys_newfstatat,
+ [__NR_unlinkat] sys_unlinkat,
+ [__NR_renameat] sys_renameat,
+ [__NR_linkat] sys_linkat,
+ [__NR_symlinkat] sys_symlinkat,
+ [__NR_readlinkat] sys_readlinkat,
+ [__NR_fchmodat] sys_fchmodat,
+ [__NR_faccessat] sys_faccessat,
};
long spu_sys_callback(struct spu_syscall_block *s)
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index f841972f1fa..554776d4b8a 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -331,7 +331,7 @@ static void __init ocotea_init(void)
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
{
- ibm44x_platform_init(r3, r4, r5, r6, r7);
+ ibm440gx_platform_init(r3, r4, r5, r6, r7);
ppc_md.setup_arch = ocotea_setup_arch;
ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index bc9b94f77e3..e62b75707f7 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -26,11 +26,35 @@
#include <asm/irq.h>
#include <asm/ppc_sys.h>
#include <asm/ppcboot.h>
+#include <linux/fs_uart_pd.h>
#include "pq2ads_pd.h"
static void init_fcc1_ioports(void);
static void init_fcc2_ioports(void);
+static void init_scc1_uart_ioports(void);
+static void init_scc4_uart_ioports(void);
+
+static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
+ [fsid_scc1_uart] = {
+ .init_ioports = init_scc1_uart_ioports,
+ .fs_no = fsid_scc1_uart,
+ .brg = 1,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_scc4_uart] = {
+ .init_ioports = init_scc4_uart_ioports,
+ .fs_no = fsid_scc4_uart,
+ .brg = 4,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+};
static struct fs_mii_bus_info mii_bus_info = {
.method = fsmii_bitbang,
@@ -201,6 +225,55 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
}
}
+static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc8272_uart_pdata);
+ int id = fs_uart_id_scc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc8272_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
+static void init_scc1_uart_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+
+ /* SCC1 is only on port D */
+ setbits32(&immap->im_ioport.iop_ppard,0x00000003);
+ clrbits32(&immap->im_ioport.iop_psord,0x00000001);
+ setbits32(&immap->im_ioport.iop_psord,0x00000002);
+ clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
+ setbits32(&immap->im_ioport.iop_pdird,0x00000002);
+
+ /* Wire BRG1 to SCC1 */
+ clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
+
+ iounmap(immap);
+}
+
+static void init_scc4_uart_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+
+ setbits32(&immap->im_ioport.iop_ppard,0x00000600);
+ clrbits32(&immap->im_ioport.iop_psord,0x00000600);
+ clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
+ setbits32(&immap->im_ioport.iop_pdird,0x00000400);
+
+ /* Wire BRG4 to SCC4 */
+ clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
+ setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
+
+ iounmap(immap);
+}
+
static int mpc8272ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@@ -209,6 +282,10 @@ static int mpc8272ads_platform_notify(struct device *dev)
.rtn = mpc8272ads_fixup_enet_pdata
},
{
+ .bus_id = "fsl-cpm-scc:uart",
+ .rtn = mpc
+ },
+ {
.bus_id = NULL
}
};
@@ -230,7 +307,44 @@ int __init mpc8272ads_init(void)
ppc_sys_device_enable(MPC82xx_CPM_FCC1);
ppc_sys_device_enable(MPC82xx_CPM_FCC2);
+ /* to be ready for console, let's attach pdata here */
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
+ ppc_sys_device_enable(MPC82xx_CPM_SCC1);
+
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
+ ppc_sys_device_enable(MPC82xx_CPM_SCC4);
+#endif
+
+
return 0;
}
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SCC1 and by 1 assumed SCC4
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SCC4 here*/
+ pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
+ pinfo = &mpc8272<F12>_uart_pdata[1];
+ } else { /*over SCC1*/
+ pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
+ pinfo = &mpc8272_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
arch_initcall(mpc8272ads_init);
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index ac8fcc68afe..6ce3b842def 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -37,6 +38,11 @@
extern unsigned char __res[];
+static void setup_fec1_ioports(void);
+static void setup_scc1_ioports(void);
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
+
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
@@ -79,6 +85,28 @@ static struct fs_platform_info mpc8xx_scc_pdata = {
.phy_irq = -1,
.bus_info = &scc_mii_bus_info,
+
+};
+
+static struct fs_uart_platform_info mpc866_uart_pdata[] = {
+ [fsid_smc1_uart] = {
+ .brg = 1,
+ .fs_no = fsid_smc1_uart,
+ .init_ioports = setup_smc1_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_smc2_uart] = {
+ .brg = 2,
+ .fs_no = fsid_smc2_uart,
+ .init_ioports = setup_smc2_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
};
void __init board_init(void)
@@ -92,9 +120,12 @@ void __init board_init(void)
printk(KERN_CRIT "Could not remap BCSR1\n");
return;
}
+
#ifdef CONFIG_SERIAL_CPM_SMC1
cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
clrbits32(bcsr_io,(0x80000000 >> 7));
+ cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,(0x80000000 >> 7));
@@ -108,6 +139,8 @@ void __init board_init(void)
cp->cp_simode &= ~(0xe0000000 >> 1);
cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
clrbits32(bcsr_io,(0x80000000 >> 13));
+ cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
clrbits32(bcsr_io,(0x80000000 >> 13));
cp->cp_pbpar &= ~(0x00000c00);
@@ -232,6 +265,74 @@ static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
+static void setup_smc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x000000c0;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+
+ clrbits32(bcsr_io,BCSR1_RS232EN_1);
+ iounmap(bcsr_io);
+
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+
+}
+
+static void setup_smc2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x00000c00;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+
+ clrbits32(bcsr_io,BCSR1_RS232EN_2);
+
+ iounmap(bcsr_io);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+ setbits16(&immap->im_ioport.iop_papar, iobits);
+ clrbits16(&immap->im_ioport.iop_padir, iobits);
+ clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+
+}
+
+static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc866_uart_pdata);
+
+ int id = fs_uart_id_smc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc866_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
static int mpc866ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@@ -244,6 +345,10 @@ static int mpc866ads_platform_notify(struct device *dev)
.rtn = mpc866ads_fixup_scc_enet_pdata,
},
{
+ .bus_id = "fsl-cpm-smc:uart",
+ .rtn = mpc866ads_fixup_uart_pdata
+ },
+ {
.bus_id = NULL
}
};
@@ -267,7 +372,42 @@ int __init mpc866ads_init(void)
#endif
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+/* Since either of the uarts could be used as console, they need to ready */
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMCer
+ ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
+
return 0;
}
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SMC2 here*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+ pinfo = &mpc866_uart_pdata[1];
+ } else { /*over SMC1*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+ pinfo = &mpc866_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
arch_initcall(mpc866ads_init);
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index 50a99e5f7c6..4b88679cd31 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -35,9 +36,32 @@
#include <asm/ppc_sys.h>
extern unsigned char __res[];
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
static void __init mpc885ads_scc_phy_init(char);
+static struct fs_uart_platform_info mpc885_uart_pdata[] = {
+ [fsid_smc1_uart] = {
+ .brg = 1,
+ .fs_no = fsid_smc1_uart,
+ .init_ioports = setup_smc1_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_smc2_uart] = {
+ .brg = 2,
+ .fs_no = fsid_smc2_uart,
+ .init_ioports = setup_smc2_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+};
+
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
@@ -116,6 +140,8 @@ void __init board_init(void)
#ifdef CONFIG_SERIAL_CPM_SMC1
cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
clrbits32(bcsr_io, BCSR1_RS232EN_1);
+ cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,BCSR1_RS232EN_1);
cp->cp_smc[0].smc_smcmr = 0;
@@ -126,6 +152,8 @@ void __init board_init(void)
cp->cp_simode &= ~(0xe0000000 >> 1);
cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
clrbits32(bcsr_io,BCSR1_RS232EN_2);
+ cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,BCSR1_RS232EN_2);
cp->cp_smc[1].smc_smcmr = 0;
@@ -343,6 +371,70 @@ static void mpc885ads_scc_phy_init(char phy_addr)
out_be32(&fecp->fec_mii_speed, 0);
}
+static void setup_smc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x000000c0;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+ clrbits32(bcsr_io,BCSR1_RS232EN_1);
+ iounmap(bcsr_io);
+
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+}
+
+static void setup_smc2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x00000c00;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+ clrbits32(bcsr_io,BCSR1_RS232EN_2);
+ iounmap(bcsr_io);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+ setbits16(&immap->im_ioport.iop_papar, iobits);
+ clrbits16(&immap->im_ioport.iop_padir, iobits);
+ clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+}
+
+static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc885_uart_pdata);
+
+ int id = fs_uart_id_smc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc885_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
+
static int mpc885ads_platform_notify(struct device *dev)
{
@@ -356,12 +448,17 @@ static int mpc885ads_platform_notify(struct device *dev)
.rtn = mpc885ads_fixup_scc_enet_pdata,
},
{
+ .bus_id = "fsl-cpm-smc:uart",
+ .rtn = mpc885ads_fixup_uart_pdata
+ },
+ {
.bus_id = NULL
}
};
platform_notify_map(dev_map,dev);
+ return 0;
}
int __init mpc885ads_init(void)
@@ -383,7 +480,41 @@ int __init mpc885ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_FEC2);
#endif
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
return 0;
}
arch_initcall(mpc885ads_init);
+
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SMC2 here*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+ pinfo = &mpc885_uart_pdata[1];
+ } else { /*over SMC1*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+ pinfo = &mpc885_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
index 3365fd788a7..7fc2e02f524 100644
--- a/arch/ppc/platforms/pq2ads.c
+++ b/arch/ppc/platforms/pq2ads.c
@@ -14,11 +14,40 @@
#include <linux/init.h>
+#include <asm/io.h>
#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/immap_cpm2.h>
void __init
m82xx_board_setup(void)
{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+ u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+
/* Enable the 2nd UART port */
- *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+ clrbits32(bcsr, BCSR1_RS232_EN2);
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+ clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+ clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+ iounmap(bcsr);
+ iounmap(immap);
}
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
index a7dd55f1c63..f6cc1688852 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -2,7 +2,7 @@
* PPC440GX system library
*
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003, 2004 Zultys Technologies
+ * Copyright (c) 2003 - 2006 Zultys Technologies
*
* 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
@@ -282,3 +282,14 @@ int ibm440gx_show_cpuinfo(struct seq_file *m){
return 0;
}
+void __init ibm440gx_platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6,
+ unsigned long r7)
+{
+ /* Erratum 440_43 workaround, disable L1 cache parity checking */
+ if (!strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") ||
+ !strcmp(cur_cpu_spec->cpu_name, "440GX Rev. F"))
+ mtspr(SPRN_CCR1, mfspr(SPRN_CCR1) | CCR1_DPC);
+
+ ibm44x_platform_init(r3, r4, r5, r6, r7);
+}
diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h
index a2ab9fab8e3..a03ec6022e8 100644
--- a/arch/ppc/syslib/ibm440gx_common.h
+++ b/arch/ppc/syslib/ibm440gx_common.h
@@ -29,6 +29,10 @@
void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk,
unsigned int ser_clk) __init;
+/* common 440GX platform init */
+void ibm440gx_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7) __init;
+
/* Enable L2 cache */
void ibm440gx_l2c_enable(void) __init;
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
index bd41ed83beb..6f536383866 100644
--- a/arch/ppc/syslib/mpc8xx_devices.c
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -170,12 +170,18 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC8xx_CPM_SMC1] = {
.name = "fsl-cpm-smc",
.id = 1,
- .num_resources = 2,
+ .num_resources = 3,
.resource = (struct resource[]) {
{
.name = "regs",
- .start = 0xa82,
- .end = 0xa91,
+ .start = 0xa80,
+ .end = 0xa8f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3e80,
+ .end = 0x3ebf,
.flags = IORESOURCE_MEM,
},
{
@@ -189,15 +195,22 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC8xx_CPM_SMC2] = {
.name = "fsl-cpm-smc",
.id = 2,
- .num_resources = 2,
+ .num_resources = 3,
.resource = (struct resource[]) {
{
.name = "regs",
- .start = 0xa92,
- .end = 0xaa1,
+ .start = 0xa90,
+ .end = 0xa9f,
.flags = IORESOURCE_MEM,
},
{
+ .name = "pram",
+ .start = 0x3f80,
+ .end = 0x3fbf,
+ .flags = IORESOURCE_MEM,
+
+ },
+ {
.name = "interrupt",
.start = MPC8xx_INT_SMC2,
.end = MPC8xx_INT_SMC2,
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 7662c4e6e7d..2d48018b71d 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -109,9 +109,11 @@ ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr)
int i;
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];
- if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) {
+ if (((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) &&
+ ((r->flags & PPC_SYS_IORESOURCE_FIXUPPED) != PPC_SYS_IORESOURCE_FIXUPPED)) {
r->start += paddr;
r->end += paddr;
+ r->flags |= PPC_SYS_IORESOURCE_FIXUPPED;
}
}
}
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c
index 75e64f1c144..433b0fa203e 100644
--- a/arch/ppc/syslib/pq2_sys.c
+++ b/arch/ppc/syslib/pq2_sys.c
@@ -113,13 +113,13 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8248",
.mask = 0x0000ff00,
.value = 0x00000c00,
- .num_devices = 11,
+ .num_devices = 12,
.device_list = (enum ppc_sys_devices[])
{
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
- MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SMC1,
- MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
- MPC82xx_CPM_USB, MPC82xx_SEC1,
+ MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
+ MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
+ MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
},
},
{