[PATCH 3/16] add base support for Celleb platform

Ishizaki Kou kou.ishizaki at toshiba.co.jp
Wed Nov 15 20:31:36 EST 2006


This patch adds base support for Celleb platform.

Signed-off-by: Kou Ishizaki <kou.ishizaki at toshiba.co.jp>
---

Index: linux-2.6.19/arch/powerpc/Kconfig
diff -u linux-2.6.19/arch/powerpc/Kconfig:1.1.1.2 linux-2.6.19/arch/powerpc/Kconfig:1.3
--- linux-2.6.19/arch/powerpc/Kconfig:1.1.1.2	Tue Oct 24 13:35:52 2006
+++ linux-2.6.19/arch/powerpc/Kconfig	Mon Nov  6 22:04:23 2006
@@ -456,6 +456,14 @@
 	select PPC_UDBG_16550
 	select UDBG_RTAS_CONSOLE
 
+config PPC_CELLEB
+	bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
+	depends on PPC_MULTIPLATFORM && PPC64
+	select PPC_CELL
+	select PPC_RTAS
+	select SPU_NEED_SHADOW_INT_MASK
+	select HAS_TXX9_SERIAL
+
 config UDBG_RTAS_CONSOLE
 	bool "RTAS based debug console"
 	depends on PPC_RTAS
Index: linux-2.6.19/arch/powerpc/Kconfig.debug
diff -u linux-2.6.19/arch/powerpc/Kconfig.debug:1.1.1.1 linux-2.6.19/arch/powerpc/Kconfig.debug:1.2
--- linux-2.6.19/arch/powerpc/Kconfig.debug:1.1.1.1	Fri Oct  6 10:40:02 2006
+++ linux-2.6.19/arch/powerpc/Kconfig.debug	Fri Oct  6 12:26:34 2006
@@ -176,6 +176,12 @@
 	  Select this to enable early debugging for legacy iSeries. You need
 	  to hit "Ctrl-x Ctrl-x" to see the messages on the console.
 
+config PPC_EARLY_DEBUG_BEAT
+	bool "Beat HV Console"
+	depends on PPC_CELLEB
+	help
+	  Select this to enable early debugging for Celleb with Beat.
+
 endchoice
 
 endmenu
Index: linux-2.6.19/arch/powerpc/boot/Makefile
diff -u linux-2.6.19/arch/powerpc/boot/Makefile:1.1.1.3 linux-2.6.19/arch/powerpc/boot/Makefile:1.2
--- linux-2.6.19/arch/powerpc/boot/Makefile:1.1.1.3	Wed Nov  1 19:21:09 2006
+++ linux-2.6.19/arch/powerpc/boot/Makefile	Tue Nov  7 20:56:06 2006
@@ -154,6 +154,7 @@
 image-$(CONFIG_PPC_PSERIES)		+= zImage.pseries
 image-$(CONFIG_PPC_MAPLE)		+= zImage.pseries
 image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
+image-$(CONFIG_PPC_CELLEB)		+= zImage.pseries
 image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
 image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
 image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
Index: linux-2.6.19/arch/powerpc/kernel/udbg.c
diff -u linux-2.6.19/arch/powerpc/kernel/udbg.c:1.1.1.1 linux-2.6.19/arch/powerpc/kernel/udbg.c:1.2
--- linux-2.6.19/arch/powerpc/kernel/udbg.c:1.1.1.1	Fri Oct  6 10:40:04 2006
+++ linux-2.6.19/arch/powerpc/kernel/udbg.c	Fri Oct  6 12:26:35 2006
@@ -45,6 +45,8 @@
 #elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
 	/* For iSeries - hit Ctrl-x Ctrl-x to see the output */
 	udbg_init_iseries();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
+	udbg_init_debug_beat();
 #endif
 }
 
Index: linux-2.6.19/arch/powerpc/platforms/Makefile
diff -u linux-2.6.19/arch/powerpc/platforms/Makefile:1.1.1.1 linux-2.6.19/arch/powerpc/platforms/Makefile:1.2
--- linux-2.6.19/arch/powerpc/platforms/Makefile:1.1.1.1	Fri Oct  6 10:40:06 2006
+++ linux-2.6.19/arch/powerpc/platforms/Makefile	Fri Oct  6 12:26:35 2006
@@ -16,3 +16,4 @@
 obj-$(CONFIG_PPC_PASEMI)		+= pasemi/
 obj-$(CONFIG_PPC_CELL)		+= cell/
 obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
+obj-$(CONFIG_PPC_CELLEB)	+= celleb/
Index: linux-2.6.19/include/asm-powerpc/firmware.h
diff -u linux-2.6.19/include/asm-powerpc/firmware.h:1.1.1.2 linux-2.6.19/include/asm-powerpc/firmware.h:1.4
--- linux-2.6.19/include/asm-powerpc/firmware.h:1.1.1.2	Wed Nov  1 19:24:26 2006
+++ linux-2.6.19/include/asm-powerpc/firmware.h	Tue Nov  7 18:50:54 2006
@@ -58,7 +58,12 @@
 	FW_FEATURE_PSERIES_ALWAYS = 0,
 	FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
 	FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+	FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR,
+	FW_FEATURE_CELLEB_ALWAYS = FW_FEATURE_LPAR,
 	FW_FEATURE_POSSIBLE =
+#ifdef CONFIG_PPC_CELLEB
+		FW_FEATURE_CELLEB_POSSIBLE |
+#endif
 #ifdef CONFIG_PPC_PSERIES
 		FW_FEATURE_PSERIES_POSSIBLE |
 #endif
@@ -67,6 +72,9 @@
 #endif
 		0,
 	FW_FEATURE_ALWAYS =
+#ifdef CONFIG_PPC_CELLEB
+		FW_FEATURE_CELLEB_ALWAYS &
+#endif
 #ifdef CONFIG_PPC_PSERIES
 		FW_FEATURE_PSERIES_ALWAYS &
 #endif
Index: linux-2.6.19/include/asm-powerpc/iommu.h
diff -u linux-2.6.19/include/asm-powerpc/iommu.h:1.1.1.1 linux-2.6.19/include/asm-powerpc/iommu.h:1.2
--- linux-2.6.19/include/asm-powerpc/iommu.h:1.1.1.1	Fri Oct  6 10:43:20 2006
+++ linux-2.6.19/include/asm-powerpc/iommu.h	Fri Oct  6 12:26:36 2006
@@ -89,6 +89,7 @@
 extern void iommu_init_early_pSeries(void);
 extern void iommu_init_early_iSeries(void);
 extern void iommu_init_early_dart(void);
+extern void celleb_init_iommu(void);
 
 #ifdef CONFIG_PCI
 extern void pci_iommu_init(void);
Index: linux-2.6.19/include/asm-powerpc/mmu.h
diff -u linux-2.6.19/include/asm-powerpc/mmu.h:1.1.1.1 linux-2.6.19/include/asm-powerpc/mmu.h:1.2
--- linux-2.6.19/include/asm-powerpc/mmu.h:1.1.1.1	Fri Oct  6 10:43:20 2006
+++ linux-2.6.19/include/asm-powerpc/mmu.h	Fri Oct  6 12:26:36 2006
@@ -247,6 +247,12 @@
 extern void hpte_init_native(void);
 extern void hpte_init_lpar(void);
 extern void hpte_init_iSeries(void);
+extern void hpte_init_beat(void);
+
+extern long beat_lpar_hpte_insert(unsigned long hpte_group,
+				     unsigned long va, unsigned long prpn,
+				     unsigned long rflags,
+				     unsigned long vflags, int psize);
 
 extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 				     unsigned long va, unsigned long prpn,
Index: linux-2.6.19/include/asm-powerpc/ppc-pci.h
diff -u linux-2.6.19/include/asm-powerpc/ppc-pci.h:1.1.1.1 linux-2.6.19/include/asm-powerpc/ppc-pci.h:1.2
--- linux-2.6.19/include/asm-powerpc/ppc-pci.h:1.1.1.1	Fri Oct  6 10:43:21 2006
+++ linux-2.6.19/include/asm-powerpc/ppc-pci.h	Fri Oct  6 12:26:36 2006
@@ -23,6 +23,7 @@
 extern int global_phb_number;
 
 extern unsigned long find_and_init_phbs(void);
+extern unsigned long celleb_find_and_init_phbs(void);
 
 extern struct pci_dev *ppc64_isabridge_dev;	/* may be NULL if no ISA bus */
 
Index: linux-2.6.19/include/asm-powerpc/smp.h
diff -u linux-2.6.19/include/asm-powerpc/smp.h:1.1.1.2 linux-2.6.19/include/asm-powerpc/smp.h:1.3
--- linux-2.6.19/include/asm-powerpc/smp.h:1.1.1.2	Tue Oct 17 08:44:31 2006
+++ linux-2.6.19/include/asm-powerpc/smp.h	Tue Oct 17 13:22:53 2006
@@ -75,6 +75,7 @@
 void smp_init_iSeries(void);
 void smp_init_pSeries(void);
 void smp_init_cell(void);
+void smp_init_celleb(void);
 void smp_setup_cpu_maps(void);
 
 extern int __cpu_disable(void);
Index: linux-2.6.19/include/asm-powerpc/spu_priv1.h
diff -u linux-2.6.19/include/asm-powerpc/spu_priv1.h:1.1.1.1 linux-2.6.19/include/asm-powerpc/spu_priv1.h:1.2
--- linux-2.6.19/include/asm-powerpc/spu_priv1.h:1.1.1.1	Fri Oct  6 10:43:21 2006
+++ linux-2.6.19/include/asm-powerpc/spu_priv1.h	Fri Oct  6 12:26:36 2006
@@ -177,6 +177,7 @@
  */
 
 extern const struct spu_priv1_ops spu_priv1_mmio_ops;
+extern const struct spu_priv1_ops spu_priv1_beat_ops;
 
 #endif /* __KERNEL__ */
 #endif
Index: linux-2.6.19/include/asm-powerpc/udbg.h
diff -u linux-2.6.19/include/asm-powerpc/udbg.h:1.1.1.1 linux-2.6.19/include/asm-powerpc/udbg.h:1.2
--- linux-2.6.19/include/asm-powerpc/udbg.h:1.1.1.1	Fri Oct  6 10:43:21 2006
+++ linux-2.6.19/include/asm-powerpc/udbg.h	Fri Oct  6 12:26:36 2006
@@ -44,6 +44,7 @@
 extern void __init udbg_init_iseries(void);
 extern void __init udbg_init_rtas_panel(void);
 extern void __init udbg_init_rtas_console(void);
+extern void __init udbg_init_debug_beat(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
Index: linux-2.6.19/arch/powerpc/platforms/celleb/Makefile
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/Makefile:1.1
--- /dev/null	Thu Nov  9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/Makefile	Fri Oct  6 16:13:36 2006
@@ -0,0 +1,9 @@
+obj-$(CONFIG_PPC_CELLEB)		+= interrupt.o iommu.o setup.o \
+					   lpar.o beat.o ioif.o \
+					   celleb_pci.o celleb_epci.o
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_PPC_CELLEB)		+= smp.o
+endif
+
+spu-priv1-$(CONFIG_PPC_CELLEB)		+= spu_priv1_beat.o
+obj-$(CONFIG_SPU_BASE)			+= $(spu-priv1-y)
Index: linux-2.6.19/arch/powerpc/platforms/celleb/beat.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/beat.c:1.3
--- /dev/null	Thu Nov  9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/beat.c	Wed Oct 18 17:40:36 2006
@@ -0,0 +1,223 @@
+/*
+ * Simple routines for Celleb/Beat
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <asm/rtas.h>
+#include <asm/hvconsole.h>
+#include <asm/time.h>
+
+#include "beat.h"
+
+int64_t	beat_errno;
+
+static const char *re_det1(const char *det, unsigned char *buf, int size)
+{
+	uint64_t ch;
+
+	for(ch = 0; ch < size; ch++) {
+		buf[ch] = 0;
+	}
+	for(;;) {
+		switch(ch = *det++) {
+		case '\0':
+			return --det;
+		case '.':
+			return det;
+		case '#':
+			det++;		// skip #0
+			break;
+		default:
+			if(size-- <= 0) {
+				return NULL;
+			}
+			*buf++ = ch;
+		}
+	}
+}
+
+int64_t beat_repository_encode(int vendor_id, const char *str, uint64_t name[4])
+{ 
+	union {
+		unsigned char cbuf[8];
+		uint64_t a;
+	} buf[4];
+
+	buf[0].cbuf[0] = vendor_id << 4;
+	buf[0].cbuf[1] = 0;
+	buf[0].cbuf[2] = 0;
+	buf[0].cbuf[3] = 0;
+	if((str = re_det1(str, &buf[0].cbuf[4], 4)) == NULL) {
+		return -1;
+	}
+	if((str = re_det1(str, &buf[1].cbuf[0], 8)) == NULL) {
+		return -2;
+	}
+	if((str = re_det1(str, &buf[2].cbuf[0], 8)) == NULL) {
+		return -3;
+	}
+	if((str = re_det1(str, &buf[3].cbuf[0], 8)) == NULL) {
+		return -4; 
+	}
+	if(*str != 0) {
+		return -5;
+	} 
+	name[0] = buf[0].a;
+	name[1] = buf[1].a;
+	name[2] = buf[2].a;
+	name[3] = buf[3].a;
+	return 0;
+} 
+
+void beat_restart(char *cmd)
+{
+	beat_shutdown_logical_partition(1);
+}
+
+void beat_power_off(void)
+{
+	beat_shutdown_logical_partition(0);
+}
+
+uint64_t beat_halt_code = 0x1000000000000000UL;
+
+void beat_halt(void)
+{
+	beat_shutdown_logical_partition(beat_halt_code);
+}
+
+int beat_set_rtc_time(struct rtc_time *rtc_time)
+{
+	uint64_t tim;
+	tim = mktime(rtc_time->tm_year+1900,
+		     rtc_time->tm_mon+1, rtc_time->tm_mday,
+		     rtc_time->tm_hour, rtc_time->tm_min, rtc_time->tm_sec);
+	if (beat_rtc_write(tim))
+		return -1;
+	return 0;
+}
+
+void beat_get_rtc_time(struct rtc_time *rtc_time)
+{
+	uint64_t tim;
+
+	if (beat_rtc_read(&tim))
+		tim = 0;
+	to_tm(tim, rtc_time);
+	rtc_time->tm_year -= 1900;
+	rtc_time->tm_mon -= 1;
+}
+
+#define	BEAT_NVRAM_SIZE	4096
+#define	BEAT_NVRW_CNT	(sizeof(uint64_t) * 6)
+
+ssize_t beat_nvram_read(char *buf, size_t count, loff_t *index)
+{
+	unsigned int i;
+	unsigned long len;
+	char *p = buf;
+
+	if (*index >= BEAT_NVRAM_SIZE)
+		return -ENODEV;
+	i = *index;
+	if (i + count > BEAT_NVRAM_SIZE)
+		count = BEAT_NVRAM_SIZE - i;
+
+	for (; count != 0; count -= len) {
+		uint64_t nb[6];
+
+		len = count;
+		if (len > BEAT_NVRW_CNT)
+			len = BEAT_NVRW_CNT;
+		if (beat_eeprom_read(i, len,
+			nb+0, nb+1, nb+2, nb+3, nb+4, nb+5)) {
+			return -EIO;
+		}
+
+		memcpy(p, nb, len);
+
+		p += len;
+		i += len;
+	}
+	*index = i;
+	return p - buf;
+}
+
+ssize_t beat_nvram_write(char *buf, size_t count, loff_t *index)
+{
+	unsigned int i;
+	unsigned long len;
+	char *p = buf;
+
+	if (*index >= BEAT_NVRAM_SIZE)
+		return -ENODEV;
+	i = *index;
+	if (i + count > BEAT_NVRAM_SIZE)
+		count = BEAT_NVRAM_SIZE - i;
+
+	for (; count != 0; count -= len) {
+		uint64_t nb[6];
+
+		len = count;
+		if (len > BEAT_NVRW_CNT)
+			len = BEAT_NVRW_CNT;
+		memcpy(nb, p, len);
+		if (beat_eeprom_write(i, len,
+			nb[0], nb[1], nb[2], nb[3], nb[4], nb[5])) {
+			return -EIO;
+		}
+
+		p += len;
+		i += len;
+	}
+	*index = i;
+	return p - buf;
+}
+
+ssize_t beat_nvram_get_size(void)
+{
+	return BEAT_NVRAM_SIZE;
+}
+
+int beat_set_xdabr(unsigned long dabr)
+{
+	if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
+		return -1;
+	return 0;
+}
+
+int64_t beat_get_term_char(uint64_t vterm, uint64_t *len, uint64_t *t1, uint64_t *t2)
+{
+	return beat_get_characters_from_console(vterm, len, t1, t2);
+}
+
+int64_t beat_put_term_char(uint64_t vterm, uint64_t len, uint64_t t1, uint64_t t2)
+{
+	return beat_put_characters_to_console(vterm, len, t1, t2);
+}
+
+EXPORT_SYMBOL(beat_get_term_char);
+EXPORT_SYMBOL(beat_put_term_char);
+EXPORT_SYMBOL(beat_repository_encode);
+EXPORT_SYMBOL(beat_errno);
+EXPORT_SYMBOL(beat_halt_code);
Index: linux-2.6.19/arch/powerpc/platforms/celleb/beat.h
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/beat.h:1.2
--- /dev/null	Thu Nov  9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/beat.h	Wed Oct 18 17:40:36 2006
@@ -0,0 +1,41 @@
+/*
+ * Guest OS Interfaces.
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CELLEB_BEAT_H
+#define _CELLEB_BEAT_H
+#include "beat_sys.h"
+
+#define DABRX_KERNEL		(1UL<<1)
+#define DABRX_USER		(1UL<<0)
+
+int64_t beat_get_term_char(uint64_t,uint64_t*,uint64_t*,uint64_t*);
+int64_t beat_put_term_char(uint64_t,uint64_t,uint64_t,uint64_t);
+int64_t beat_repository_encode(int, const char *, uint64_t[4]);
+void beat_restart(char *);
+void beat_power_off(void);
+void beat_halt(void);
+int beat_set_rtc_time(struct rtc_time *);
+void beat_get_rtc_time(struct rtc_time *);
+ssize_t beat_nvram_get_size(void);
+ssize_t beat_nvram_read(char *, size_t, loff_t *);
+ssize_t beat_nvram_write(char *, size_t, loff_t *);
+int beat_set_xdabr(unsigned long);
+
+#endif /* _CELLEB_BEAT_H */
Index: linux-2.6.19/arch/powerpc/platforms/celleb/lpar.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/lpar.c:1.3
--- /dev/null	Thu Nov  9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/lpar.c	Mon Nov  6 22:04:23 2006
@@ -0,0 +1,429 @@
+/*
+ * "Cell Reference Set" LPAR support.
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on arch/powerpc/platforms/pseries/lpar.c:
+ * Copyright (C) 2001 Todd Inglett, IBM Corporation
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#undef DEBUG_LOW
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/console.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/abs_addr.h>
+#include <asm/mmu_context.h>
+#include <asm/iommu.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+#include <asm/prom.h>
+#include <asm/abs_addr.h>
+#include <asm/cputable.h>
+#include <asm/udbg.h>
+#include <asm/smp.h>
+
+#include "beat.h"
+
+int	celleb_vtermno;
+
+#ifdef DEBUG_LOW
+#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
+#else
+#define DBG_LOW(fmt...) do { } while(0)
+#endif
+
+static void udbg_putc_beat(char c)
+{
+	unsigned long rc;
+
+	if (c == '\n')
+		udbg_putc_beat('\r');
+
+	rc = beat_put_term_char(celleb_vtermno, 1, (uint64_t)c << 56, 0);
+}
+
+/* Buffered chars getc */
+static long inbuflen;
+static long inbuf[2];	/* must be 2 longs */
+
+static int udbg_getc_poll_beat(void)
+{
+	/* The interface is tricky because it may return up to 16 chars.
+	 * We save them statically for future calls to udbg_getc().
+	 */
+	char ch, *buf = (char *)inbuf;
+	int i;
+	long rc;
+	if (inbuflen == 0) {
+		/* get some more chars. */
+		inbuflen = 0;
+		rc = beat_get_term_char(celleb_vtermno, &inbuflen, inbuf+0, inbuf+1);
+		if (rc != 0)
+			inbuflen = 0;	/* otherwise inbuflen is garbage */
+	}
+	if (inbuflen <= 0 || inbuflen > 16) {
+		/* Catch error case as well as other oddities (corruption) */
+		inbuflen = 0;
+		return -1;
+	}
+	ch = buf[0];
+	for (i = 1; i < inbuflen; i++)	/* shuffle them down. */
+		buf[i-1] = buf[i];
+	inbuflen--;
+	return ch;
+}
+
+static int udbg_getc_beat(void)
+{
+	int ch;
+	for (;;) {
+		ch = udbg_getc_poll_beat();
+		if (ch == -1) {
+			/* This shouldn't be needed...but... */
+			volatile unsigned long delay;
+			for (delay=0; delay < 2000000; delay++)
+				;
+		} else {
+			return ch;
+		}
+	}
+}
+
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+void __init udbg_init_debug_beat(void)
+{
+	celleb_vtermno = 0;
+	udbg_putc = udbg_putc_beat;
+	udbg_getc = udbg_getc_beat;
+	udbg_getc_poll = udbg_getc_poll_beat;
+}
+
+#if 0
+/* returns 0 if couldn't find or use /chosen/stdout as console */
+void __init celleb_find_udbg_vterm(void)
+{
+	struct device_node *stdout_node;
+	u32 *termno;
+	char *name;
+	int add_console;
+
+	/* find the boot console from /chosen/stdout */
+	if (!of_chosen)
+		return;
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL)
+		return;
+	stdout_node = of_find_node_by_path(name);
+	if (!stdout_node)
+		return;
+	name = (char *)get_property(stdout_node, "name", NULL);
+	if (!name) {
+		printk(KERN_WARNING "stdout node missing 'name' property!\n");
+		goto out;
+	}
+	/* The user has requested a console so this is already set up. */
+	add_console = !strstr(cmd_line, "console=");
+
+	/* Check if it's a virtual terminal */
+	if (strncmp(name, "vty", 3) != 0)
+		goto out;
+	termno = (u32 *)get_property(stdout_node, "reg", NULL);
+	if (termno == NULL)
+		goto out;
+	celleb_vtermno = termno[0];
+
+	if (device_is_compatible(stdout_node, "hvterm1")) {
+		udbg_putc = udbg_putc_beat;
+		udbg_getc = udbg_getc_beat;
+		udbg_getc_poll = udbg_getc_poll_beat;
+		if (add_console)
+			add_preferred_console("hvc", termno[0] & 0xff, NULL);
+	}
+out:
+	of_node_put(stdout_node);
+}
+#endif
+
+static inline unsigned int beat_read_mask(unsigned hpte_group)
+{
+	unsigned long hpte_v0, hpte_v1, hpte_v2, hpte_v3, hpte_perms;
+	unsigned long rmask = 0;
+
+	beat_read_htab_entries(0, hpte_group + 0,
+		&hpte_v0, &hpte_v1, &hpte_v2, &hpte_v3, &hpte_perms);
+	if (!(hpte_v0 & HPTE_V_BOLTED))
+		rmask |= 0x8000;
+	if (!(hpte_v1 & HPTE_V_BOLTED))
+		rmask |= 0x4000;
+	if (!(hpte_v2 & HPTE_V_BOLTED))
+		rmask |= 0x2000;
+	if (!(hpte_v3 & HPTE_V_BOLTED))
+		rmask |= 0x1000;
+	beat_read_htab_entries(0, hpte_group + 4,
+		&hpte_v0, &hpte_v1, &hpte_v2, &hpte_v3, &hpte_perms);
+	if (!(hpte_v0 & HPTE_V_BOLTED))
+		rmask |= 0x0800;
+	if (!(hpte_v1 & HPTE_V_BOLTED))
+		rmask |= 0x0400;
+	if (!(hpte_v2 & HPTE_V_BOLTED))
+		rmask |= 0x0200;
+	if (!(hpte_v3 & HPTE_V_BOLTED))
+		rmask |= 0x0100;
+	hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP);
+	beat_read_htab_entries(0, hpte_group + 0,
+		&hpte_v0, &hpte_v1, &hpte_v2, &hpte_v3, &hpte_perms);
+	if (!(hpte_v0 & HPTE_V_BOLTED))
+		rmask |= 0x80;
+	if (!(hpte_v1 & HPTE_V_BOLTED))
+		rmask |= 0x40;
+	if (!(hpte_v2 & HPTE_V_BOLTED))
+		rmask |= 0x20;
+	if (!(hpte_v3 & HPTE_V_BOLTED))
+		rmask |= 0x10;
+	beat_read_htab_entries(0, hpte_group + 4,
+		&hpte_v0, &hpte_v1, &hpte_v2, &hpte_v3, &hpte_perms);
+	if (!(hpte_v0 & HPTE_V_BOLTED))
+		rmask |= 0x08;
+	if (!(hpte_v1 & HPTE_V_BOLTED))
+		rmask |= 0x04;
+	if (!(hpte_v2 & HPTE_V_BOLTED))
+		rmask |= 0x02;
+	if (!(hpte_v3 & HPTE_V_BOLTED))
+		rmask |= 0x01;
+	return rmask;
+}
+
+long beat_lpar_hpte_insert(unsigned long hpte_group,
+			   unsigned long va, unsigned long pa,
+			   unsigned long rflags, unsigned long vflags,
+			   int psize)
+{
+	unsigned long lpar_rc;
+	unsigned long slot;
+	unsigned long hpte_v, hpte_r;
+	unsigned long dummy0, dummy1;
+
+	if (!(vflags & HPTE_V_BOLTED))
+		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+			"rflags=%lx, vflags=%lx, psize=%d)\n",
+		hpte_group, va, pa, rflags, vflags, psize);
+
+	if (vflags & HPTE_V_SECONDARY) {
+		vflags &= ~HPTE_V_SECONDARY;
+		hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP);
+	}
+
+	hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
+	hpte_r = hpte_encode_r(pa, psize) | rflags;
+
+	if (!(vflags & HPTE_V_BOLTED))
+		DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+
+	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+		hpte_r &= ~_PAGE_COHERENT;
+
+	if ((lpar_rc = beat_read_mask(hpte_group)) == 0) {
+		if (!(vflags & HPTE_V_BOLTED))
+			DBG_LOW(" full\n");
+		return -1;
+	}
+
+	lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48,
+		hpte_v, hpte_r, &slot, &dummy0, &dummy1);
+
+	/*
+	 * Since we try and ioremap PHBs we don't own, the pte insert
+	 * will fail. However we must catch the failure in hash_page
+	 * or we will loop forever, so return -2 in this case.
+	 */
+	if (unlikely(lpar_rc != 0)) {
+		if (!(vflags & HPTE_V_BOLTED))
+			DBG_LOW(" lpar err %lx\n", lpar_rc);
+		return -2;
+	}
+	if (!(vflags & HPTE_V_BOLTED))
+		DBG_LOW(" -> slot: %lx\n", slot);
+
+	/* Because of iSeries, we have to pass down the secondary
+	 * bucket bit here as well
+	 */
+	return (slot ^ hpte_group) & 15;
+}
+
+static long beat_lpar_hpte_remove(unsigned long hpte_group)
+{
+	DBG_LOW("hpte_remove(group=%lx)\n", hpte_group);
+	return -1;
+}
+
+static unsigned long beat_lpar_hpte_getword0(unsigned long slot)
+{
+	unsigned long dword0, dword[4], dwordX;
+	unsigned long lpar_rc;
+
+	lpar_rc = beat_read_htab_entries(0, slot & ~3UL,
+		dword+0, dword+1, dword+2, dword+3, &dwordX);
+
+	dword0 = dword[slot&3];
+
+	BUG_ON(lpar_rc != 0);
+
+	return dword0;
+}
+
+static void beat_lpar_hptab_clear(void)
+{
+	unsigned long size_bytes = 1UL << ppc64_pft_size;
+	unsigned long hpte_count = size_bytes >> 4;
+	unsigned long dummy1, dummy2;
+	int i;
+
+	/* TODO: Use bulk call */
+	for (i = 0; i < hpte_count; i++)
+		beat_write_htab_entry(0, i, 0, 0, -1UL, -1UL, &dummy1, &dummy2);
+}
+
+/*
+ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+ * the low 3 bits of flags happen to line up.  So no transform is needed.
+ * We can probably optimize here and assume the high bits of newpp are
+ * already zero.  For now I am paranoid.
+ */
+static long beat_lpar_hpte_updatepp(unsigned long slot,
+				    unsigned long newpp,
+				    unsigned long va,
+				    int psize, int local)
+{
+	unsigned long lpar_rc;
+	unsigned long dummy0, dummy1, want_v;
+
+	want_v = hpte_encode_v(va, psize);
+
+	DBG_LOW("    update: avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
+		want_v & HPTE_V_AVPN, slot, psize, newpp);
+
+	dummy0 = beat_lpar_hpte_getword0(slot);
+	if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) {
+		DBG_LOW("not found !\n");
+		return -1;
+	}
+
+	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
+		&dummy0, &dummy1);
+
+	if (lpar_rc != 0 || dummy0 == 0) {
+		DBG_LOW("not found !\n");
+		return -1;
+	}
+
+	DBG_LOW("ok %lx %lx\n", dummy0, dummy1);
+
+	BUG_ON(lpar_rc != 0);
+
+	return 0;
+}
+
+static long beat_lpar_hpte_find(unsigned long va, int psize)
+{
+	unsigned long hash;
+	unsigned long i, j;
+	long slot;
+	unsigned long want_v, hpte_v;
+
+	hash = hpt_hash(va, mmu_psize_defs[psize].shift);
+	want_v = hpte_encode_v(va, psize);
+
+	for (j = 0; j < 2; j++) {
+		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+		for (i = 0; i < HPTES_PER_GROUP; i++) {
+			hpte_v = beat_lpar_hpte_getword0(slot);
+
+			if (HPTE_V_COMPARE(hpte_v, want_v)
+			    && (hpte_v & HPTE_V_VALID)
+			    && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
+				/* HPTE matches */
+				if (j)
+					slot = -slot;
+				return slot;
+			}
+			++slot;
+		}
+		hash = ~hash;
+	}
+
+	return -1;
+} 
+
+static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
+					  unsigned long ea,
+					  int psize)
+{
+	unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
+
+	vsid = get_kernel_vsid(ea);
+	va = (vsid << 28) | (ea & 0x0fffffff);
+
+	slot = beat_lpar_hpte_find(va, psize);
+	BUG_ON(slot == -1);
+
+	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
+		&dummy0, &dummy1);
+
+	BUG_ON(lpar_rc != 0);
+}
+
+static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+					 int psize, int local)
+{
+	unsigned long want_v;
+	unsigned long lpar_rc;
+	unsigned long dummy1, dummy2;
+
+	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+		slot, va, psize, local);
+	want_v = hpte_encode_v(va, psize);
+
+	dummy1 = beat_lpar_hpte_getword0(slot);
+
+	if ((dummy1 & ~0x7FUL) != (want_v & ~0x7FUL)) {
+		DBG_LOW("not found !\n");
+		return;
+	}
+
+	lpar_rc = beat_write_htab_entry(0, slot, 0, 0, HPTE_V_VALID, 0,
+		&dummy1, &dummy2);
+
+	BUG_ON(lpar_rc != 0);
+}
+
+void hpte_init_beat(void)
+{
+	ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate;
+	ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp;
+	ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+	ppc_md.hpte_insert	= beat_lpar_hpte_insert;
+	ppc_md.hpte_remove	= beat_lpar_hpte_remove;
+	ppc_md.hpte_clear_all	= beat_lpar_hptab_clear;
+}
Index: linux-2.6.19/arch/powerpc/platforms/celleb/setup.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/setup.c:1.3
--- /dev/null	Thu Nov  9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/setup.c	Wed Oct 18 17:40:36 2006
@@ -0,0 +1,303 @@
+/*
+ * Celleb setup code
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on arch/powerpc/platforms/cell/setup.c:
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort at cs.nmt.edu)
+ *  Modified by PPC64 Team, IBM Corp
+ *  Modified by Cell Team, IBM Deutschland Entwicklung GmbH
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#undef DEBUG
+
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/kexec.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+#include <asm/cputable.h>
+#include <asm/ppc-pci.h>
+#include <asm/irq.h>
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+#include <asm/firmware.h>
+
+#include "interrupt.h"
+#include "beat.h"
+
+#ifdef CONFIG_SERIAL_TXX9
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#endif
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+void celleb_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *model = "";
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: CHRP %s\n", model);
+	of_node_put(root);
+}
+
+static void celleb_progress(char *s, unsigned short hex)
+{
+	printk("*** %04x : %s\n", hex, s ? s : "");
+}
+
+static void __init celleb_setup_arch(void)
+{
+	ppc_md.init_IRQ       = beatic_init_IRQ;
+	ppc_md.get_irq        = beatic_get_irq;
+#ifdef CONFIG_SPU_BASE
+	spu_priv1_ops         = &spu_priv1_beat_ops;
+#endif
+
+
+#ifdef CONFIG_SMP
+	smp_init_celleb();
+#endif
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	if (ROOT_DEV == 0) {
+		printk("No ramdisk, default root is /dev/hda2\n");
+		ROOT_DEV = Root_HDA2;
+	}
+
+	/* Find and initialize PCI host bridges */
+	init_pci_config_tokens();
+	celleb_find_and_init_phbs();
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+}
+
+/*
+ * Early initialization.  Relocation is on but do not reference unbolted pages
+ */
+static void __init celleb_init_early(void)
+{
+	DBG(" -> celleb_init_early()\n");
+
+	celleb_init_iommu();
+
+	DBG(" <- celleb_init_early()\n");
+}
+
+static void beat_power_save(void)
+{
+	beat_pause(0);
+}
+
+static int __init celleb_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "Beat"))
+		return 0;
+
+	powerpc_firmware_features |= FW_FEATURE_LPAR;
+	hpte_init_beat();
+	return 1;
+}
+
+/*
+ * Cell has no legacy IO; anything calling this function has to
+ * fail or bad things will happen
+ */
+static int celleb_check_legacy_ioport(unsigned int baseport)
+{
+	return -ENODEV;
+}
+
+static int celleb_pci_probe_mode(struct pci_bus *bus){
+
+	struct device_node *node;
+	char *name;
+
+	node = (struct device_node *)bus->sysdata;
+	name = (char *)get_property(node, "name", NULL);
+
+	if(strcmp(name, "pci-pseudo") == 0){
+		return PCI_PROBE_DEVTREE;
+	}
+
+	return PCI_PROBE_NORMAL;
+}
+
+static void celleb_kexec_cpu_down(int crash, int secondary)
+{
+	extern void	beatic_deinit_IRQ(void);
+
+	beatic_deinit_IRQ();
+}
+
+#ifdef CONFIG_SERIAL_TXX9
+/* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024
+    mmio=0xfff000-0x1000,0xff2000-0x1000 */
+static int txx9_serial_bitmap = 0;
+
+static struct {
+	uint32_t offset;
+	uint32_t index;
+} txx9_spider_tab[3] = {
+	{ 0x300, 0 },	/* 0xFFF300 */
+	{ 0x400, 0 },	/* 0xFFF400 */
+	{ 0x800, 1 }	/* 0xFF2800 */
+};
+
+static int txx9_serial_init(void)
+{
+	extern int early_serial_txx9_setup(struct uart_port *port);
+	struct device_node *node;
+	uint64_t *irq_prop, *base_prop;
+	int irq_len, base_addr_len;
+	int i, maxi;
+	struct uart_port req;
+
+	node = of_find_node_by_path("/ioif1/sio");
+	if (!node)
+		return 0;
+	
+	irq_prop = (uint64_t *)get_property(node, "interrupts", &irq_len);
+	if (!irq_prop)
+		goto out;
+	irq_len /= sizeof(uint64_t);
+
+	base_prop = (uint64_t *)get_property(node, "toshiba,reg", &base_addr_len);
+	if (!base_prop)
+		goto out;
+	base_addr_len /= sizeof(uint64_t) * 2;
+
+	maxi = sizeof(txx9_spider_tab)/sizeof(txx9_spider_tab[0]);
+	if (maxi > irq_len)
+		maxi = irq_len;
+
+	for(i = 0; i < maxi; i++) {
+		if (!(txx9_serial_bitmap & (1<<i)))
+			continue;
+		if (base_addr_len <= txx9_spider_tab[i].index)
+			continue;
+		
+		memset(&req, 0, sizeof(req));
+		req.line = i;
+		req.iotype = UPIO_MEM;
+		req.mapbase = base_prop[txx9_spider_tab[i].index * 2]
+			+ txx9_spider_tab[i].offset;
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+		req.membase = ioremap(req.mapbase, 0x24);
+#endif
+		req.irq = irq_create_mapping(NULL, irq_prop[i]);
+		req.flags |= UPF_IOREMAP | UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+		req.uartclk = 83300000;
+		early_serial_txx9_setup(&req);
+	}
+
+out:
+	of_node_put(node);
+	return 0;
+}
+
+static int
+txx9_serial_config(char *ptr)
+{
+	int	i;
+
+	for (;;) {
+		switch(get_option(&ptr, &i)) {
+		default:
+			return 0;
+		case 2:
+			txx9_serial_bitmap |= 1 << i;
+			break;
+		case 1:
+			txx9_serial_bitmap |= 1 << i;
+			return 0;
+		}
+	}
+}
+__setup("txx9_serial=", txx9_serial_config);
+
+console_initcall(txx9_serial_init);
+#endif
+
+define_machine(celleb) {
+	.name			= "Cell Reference Set",
+	.probe			= celleb_probe,
+	.setup_arch		= celleb_setup_arch,
+	.init_early		= celleb_init_early,
+	.show_cpuinfo		= celleb_show_cpuinfo,
+	.pci_probe_mode 	= celleb_pci_probe_mode,
+	.restart		= beat_restart,
+	.power_off		= beat_power_off,
+	.halt			= beat_halt,
+	.get_rtc_time		= beat_get_rtc_time,
+	.set_rtc_time		= beat_set_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.check_legacy_ioport	= celleb_check_legacy_ioport,
+	.progress		= celleb_progress,
+	.power_save		= beat_power_save,
+	.nvram_size		= beat_nvram_get_size,
+	.nvram_read		= beat_nvram_read,
+	.nvram_write		= beat_nvram_write,
+	.set_dabr		= beat_set_xdabr,
+#ifdef CONFIG_KEXEC
+	.kexec_cpu_down		= celleb_kexec_cpu_down,
+	.machine_kexec		= default_machine_kexec,
+	.machine_kexec_prepare	= default_machine_kexec_prepare,
+	.machine_crash_shutdown	= default_machine_crash_shutdown,
+#endif
+};
Index: linux-2.6.19/arch/powerpc/platforms/celleb/smp.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/smp.c:1.2
--- /dev/null	Thu Nov  9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/smp.c	Tue Oct 17 13:22:53 2006
@@ -0,0 +1,143 @@
+/*
+ * SMP support for Celleb platform. (Incomplete)
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on arch/powerpc/platforms/cell/smp.c:
+ * Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+ * Plus various changes from other IBM teams...
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/paca.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/udbg.h>
+
+#include "interrupt.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/*
+ * The primary thread of each non-boot processor is recorded here before
+ * smp init.
+ */
+/* static cpumask_t of_spin_map; */
+
+/**
+ * smp_startup_cpu() - start the given cpu
+ *
+ * At boot time, there is nothing to do for primary threads which were
+ * started from Open Firmware.  For anything else, call RTAS with the
+ * appropriate start location.
+ *
+ * Returns:
+ *	0	- failure
+ *	1	- success
+ */
+static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+{
+	return 0;
+}
+
+static void smp_beatic_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		beatic_cause_IPI(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			beatic_cause_IPI(i, msg);
+		}
+	}
+}
+
+static int __init smp_beatic_probe(void)
+{
+	return cpus_weight(cpu_possible_map);
+}
+
+static void __devinit smp_beatic_setup_cpu(int cpu)
+{
+	beatic_setup_cpu(cpu);
+}
+
+static void __devinit smp_celleb_kick_cpu(int nr)
+{
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+	if (!smp_startup_cpu(nr))
+		return;
+	/*  */
+}
+
+static int smp_celleb_cpu_bootable(unsigned int nr)
+{
+	return 1;
+}
+static struct smp_ops_t bpa_beatic_smp_ops = {
+	.message_pass	= smp_beatic_message_pass,
+	.probe		= smp_beatic_probe,
+	.kick_cpu	= smp_celleb_kick_cpu,
+	.setup_cpu	= smp_beatic_setup_cpu,
+	.cpu_bootable	= smp_celleb_cpu_bootable,
+};
+
+/* This is called very early */
+void __init smp_init_celleb(void)
+{
+	DBG(" -> smp_init_celleb()\n");
+
+	smp_ops = &bpa_beatic_smp_ops;
+
+	DBG(" <- smp_init_celleb()\n");
+}



More information about the Linuxppc-dev mailing list