Sun3 serial driver fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Premature patch below to implement sunserial in a davem compatible
fashion by faking an openprom tree on sun3.  It's probably not going
to apply well as it is, but I'm hoping it'll help Thomas Bogendoerfer
out with his sun3x work.

Signed-off-by: Sam Creasey <sammy@xxxxxxxxx>

--------

diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 01dee84..0178ad0 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -462,6 +487,11 @@ config ZONE_DMA
 	bool
 	default y
 
+config OF
+	bool
+	depends on SUN3 || SUN3X
+	default y
+
 source "drivers/pci/Kconfig"
 
 source "drivers/zorro/Kconfig"
@@ -658,7 +688,7 @@ config DN_SERIAL
 
 config SERIAL_CONSOLE
 	bool "Support for serial port console"
-	depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
+	depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL || SERIAL_SUNZILOG)
 	---help---
 	  If you say Y here, it will be possible to use a serial port as the
 	  system console (the system console is the device which receives all
diff --git a/arch/m68k/sun3/Makefile b/arch/m68k/sun3/Makefile
index be1a847..1404595 100644
--- a/arch/m68k/sun3/Makefile
+++ b/arch/m68k/sun3/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Linux arch/m68k/sun3 source directory
 #
 
-obj-y	:= sun3ints.o sun3dvma.o sbus.o idprom.o
+obj-y	:= sun3ints.o sun3dvma.o sbus.o idprom.o of_prom.o of_device.o
 
 obj-$(CONFIG_SUN3) += config.o mmu_emu.o leds.o dvma.o intersil.o
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index c0fbd27..b2a259d 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -30,6 +30,7 @@
 #include <asm/irq.h>
 #include <asm/segment.h>
 #include <asm/sun3ints.h>
+#include <asm/prom.h>
 
 extern char _text, _end;
 
@@ -162,6 +163,7 @@ void __init config_sun3(void)
         m68k_memory[0].size=*(romvec->pv_sun3mem);
 
 	sun3_bootmem_alloc(memory_start, memory_end);
+	prom_build_devicetree();
 }
 
 void __init sun3_sched_init(irq_handler_t timer_routine)
diff --git a/arch/m68k/sun3/of_device.c b/arch/m68k/sun3/of_device.c
new file mode 100644
index 0000000..c55d6ba
--- /dev/null
+++ b/arch/m68k/sun3/of_device.c
@@ -0,0 +1,317 @@
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+static int node_match(struct device *dev, void *data)
+{
+	struct of_device *op = to_of_device(dev);
+	struct device_node *dp = data;
+
+	return (op->node == dp);
+}
+
+struct of_device *of_find_device_by_node(struct device_node *dp)
+{
+	struct device *dev = bus_find_device(&of_platform_bus_type, NULL,
+					     dp, node_match);
+
+	if (dev)
+		return to_of_device(dev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_node);
+
+struct bus_type of_platform_bus_type;
+EXPORT_SYMBOL(of_platform_bus_type);
+
+static inline u64 of_read_addr(const u32 *cell, int size)
+{
+	u64 r = 0;
+	while (size--)
+		r = (r << 32) | *(cell++);
+	return r;
+}
+
+static void __init get_cells(struct device_node *dp,
+			     int *addrc, int *sizec)
+{
+	if (addrc)
+		*addrc = of_n_addr_cells(dp);
+	if (sizec)
+		*sizec = of_n_size_cells(dp);
+}
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS	4
+
+struct of_bus {
+	const char	*name;
+	const char	*addr_prop_name;
+	int		(*match)(struct device_node *parent);
+	void		(*count_cells)(struct device_node *child,
+				       int *addrc, int *sizec);
+	int		(*map)(u32 *addr, const u32 *range,
+			       int na, int ns, int pna);
+	unsigned int	(*get_flags)(const u32 *addr);
+};
+
+/*
+ * Default translator (generic bus)
+ */
+
+static void of_bus_default_count_cells(struct device_node *dev,
+				       int *addrc, int *sizec)
+{
+	get_cells(dev, addrc, sizec);
+}
+
+/* Make sure the least significant 64-bits are in-range.  Even
+ * for 3 or 4 cell values it is a good enough approximation.
+ */
+static int of_out_of_range(const u32 *addr, const u32 *base,
+			   const u32 *size, int na, int ns)
+{
+	u64 a = of_read_addr(addr, na);
+	u64 b = of_read_addr(base, na);
+
+	if (a < b)
+		return 1;
+
+	b += of_read_addr(size, ns);
+	if (a >= b)
+		return 1;
+
+	return 0;
+}
+
+static int of_bus_default_map(u32 *addr, const u32 *range,
+			      int na, int ns, int pna)
+{
+	u32 result[OF_MAX_ADDR_CELLS];
+	int i;
+
+	if (ns > 2) {
+		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
+		return -EINVAL;
+	}
+
+	if (of_out_of_range(addr, range, range + na + pna, na, ns))
+		return -EINVAL;
+
+	/* Start with the parent range base.  */
+	memcpy(result, range + na, pna * 4);
+
+	/* Add in the child address offset.  */
+	for (i = 0; i < na; i++)
+		result[pna - 1 - i] +=
+			(addr[na - 1 - i] -
+			 range[na - 1 - i]);
+
+	memcpy(addr, result, pna * 4);
+
+	return 0;
+}
+
+static unsigned int of_bus_default_get_flags(const u32 *addr)
+{
+	return IORESOURCE_MEM;
+}
+
+/*
+ * Array of bus specific translators
+ */
+
+static struct of_bus of_busses[] = {
+	/* Default */
+	{
+		.name = "default",
+		.addr_prop_name = "reg",
+		.match = NULL,
+		.count_cells = of_bus_default_count_cells,
+		.map = of_bus_default_map,
+		.get_flags = of_bus_default_get_flags,
+	},
+};
+
+static struct of_bus *of_match_bus(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(of_busses); i ++)
+		if (!of_busses[i].match || of_busses[i].match(np))
+			return &of_busses[i];
+	BUG();
+	return NULL;
+}
+
+
+static int of_resource_verbose;
+
+static void __init build_device_resources(struct of_device *op,
+					  struct device *parent)
+{
+	struct of_device *p_op;
+	int nstart, nsize;
+	int index;
+	const unsigned long *pstart;
+	const unsigned long *psize;
+
+	if (!parent)
+		return;
+
+	p_op = to_of_device(parent);
+
+	pstart = of_get_property(op->node, "start", &nstart);
+	if (!pstart || nstart == 0)
+		return;
+
+	psize = of_get_property(op->node, "size", &nsize);
+	if (!psize || nsize != nstart)
+		BUG();
+
+	nstart /= sizeof(unsigned long);
+
+	for (index = 0; index < nstart; index++) {
+		struct resource *r = &op->resource[index];
+		unsigned long start = pstart[index];
+		unsigned long size = psize[index];
+
+		memset(r, 0, sizeof(*r));
+
+		if (of_resource_verbose)
+			printk("%s start[%d] -> %lx\n",
+			       op->node->full_name, index,
+			       start);
+
+		r->start = start;
+		r->end = start + size - 1;
+		/* what do we really want here? */
+		/* r->flags = IORESOURCE_MEM; */
+		r->name = op->node->name;
+	}
+}
+
+static struct of_device * __init scan_one_device(struct device_node *dp,
+						 struct device *parent)
+{
+	struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
+	int len, i;
+	int *irq;
+	if (!op)
+		return NULL;
+
+	op->node = dp;
+	irq = of_get_property(dp, "interrupts", &len);
+
+	if (irq) {
+	  op->num_irqs = len / sizeof(unsigned int);
+	  for (i = 0; i < op->num_irqs; i++)
+	    op->irqs[i] = irq[i];
+	} else {
+	  op->num_irqs = 0;
+	}
+
+	build_device_resources(op, parent);
+
+	op->dev.parent = parent;
+	op->dev.bus = &of_platform_bus_type;
+
+	if (!parent)
+		strcpy(op->dev.bus_id, "root");
+	else
+		sprintf(op->dev.bus_id, "%08x", dp->node);
+
+	if (of_device_register(op)) {
+		printk("%s: Could not register of device.\n",
+		       dp->full_name);
+		kfree(op);
+		op = NULL;
+	}
+
+	return op;
+}
+
+static void __init scan_tree(struct device_node *dp, struct device *parent)
+{
+	while (dp) {
+		struct of_device *op = scan_one_device(dp, parent);
+
+		if (op)
+			scan_tree(dp->child, &op->dev);
+	
+		dp = dp->sibling;
+	}
+}
+
+static void __init scan_of_devices(void)
+{
+	struct device_node *root = of_find_node_by_path("/");
+	struct of_device *parent;
+
+	parent = scan_one_device(root, NULL);
+	if (!parent)
+		return;
+
+	scan_tree(root->child, &parent->dev);
+}
+
+static int __init of_bus_driver_init(void)
+{
+	int err;
+	
+	err = of_bus_type_init(&of_platform_bus_type, "of");
+
+	if (!err)
+		scan_of_devices();
+
+	return err;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+static int __init of_debug(char *str)
+{
+	int val = 0;
+
+	get_option(&str, &val);
+	if (val & 1)
+		of_resource_verbose = 1;
+	return 1;
+}
+
+__setup("of_debug=", of_debug);
+
+struct of_device* of_platform_device_create(struct device_node *np,
+					    const char *bus_id,
+					    struct device *parent,
+					    struct bus_type *bus)
+{
+	struct of_device *dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->dev.parent = parent;
+	dev->dev.bus = bus;
+	dev->dev.release = of_release_dev;
+
+	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+	if (of_device_register(dev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+EXPORT_SYMBOL(of_platform_device_create);
diff --git a/arch/m68k/sun3/of_prom.c b/arch/m68k/sun3/of_prom.c
new file mode 100644
index 0000000..11b7170
--- /dev/null
+++ b/arch/m68k/sun3/of_prom.c
@@ -0,0 +1,442 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc32 by David S. Miller davem@xxxxxxxxxxxxx
+ *
+ *  Adapted for sun3 by Sam Creasey sammy@xxxxxxxxx
+ *
+ *      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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/oplib.h>
+#include <asm/sun3xprom.h>
+#include <asm/of_device.h>
+#include <asm/io.h>
+#include <asm/machines.h>
+#include <asm/idprom.h>
+
+extern struct device_node *allnodes;	/* temporary while merging */
+
+extern rwlock_t devtree_lock;	/* temporary while merging */
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->node == handle)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+	struct property *prop;
+	int len;
+
+	prop = of_find_property(np, name, &len);
+	if (!prop || len != 4)
+		return def;
+
+	return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+int of_set_property(struct device_node *dp, const char *name, void *val, int len)
+{
+#if 0
+	struct property **prevp;
+	void *new_val;
+	int err;
+
+	new_val = kmalloc(len, GFP_KERNEL);
+	if (!new_val)
+		return -ENOMEM;
+
+	memcpy(new_val, val, len);
+
+	err = -ENODEV;
+
+	write_lock(&devtree_lock);
+	prevp = &dp->properties;
+	while (*prevp) {
+		struct property *prop = *prevp;
+
+		if (!strcasecmp(prop->name, name)) {
+			void *old_val = prop->value;
+			int ret;
+
+			ret = prom_setprop(dp->node, (char *) name, val, len);
+			err = -EINVAL;
+			if (ret >= 0) {
+				prop->value = new_val;
+				prop->length = len;
+
+				if (OF_IS_DYNAMIC(prop))
+					kfree(old_val);
+
+				OF_MARK_DYNAMIC(prop);
+
+				err = 0;
+			}
+			break;
+		}
+		prevp = &(*prevp)->next;
+	}
+	write_unlock(&devtree_lock);
+
+	/* XXX Upate procfs if necessary... */
+
+	return err;
+#else
+	BUG();
+	return -EINVAL;
+#endif
+}
+EXPORT_SYMBOL(of_set_property);
+
+int of_find_in_proplist(const char *list, const char *match, int len)
+{
+	while (len > 0) {
+		int l;
+
+		if (!strcmp(list, match))
+			return 1;
+		l = strlen(list) + 1;
+		list += l;
+		len -= l;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(of_find_in_proplist);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	prom_early_allocated += size;
+
+	return ret;
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+	if (!dp)
+		return 0;
+
+	return (dp->parent == NULL);
+}
+
+void __iomem *of_ioremap(struct resource *res, unsigned long offset,
+                         unsigned long size, char *name)
+{
+	BUG();
+        return NULL;
+}
+EXPORT_SYMBOL(of_ioremap);
+
+void of_iounmap(struct resource *res, void __iomem *base, unsigned long size)
+{
+	iounmap(base);
+}
+EXPORT_SYMBOL(of_iounmap);
+
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ */
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *rprop;
+
+	rprop = of_find_property(dp, "start", NULL);
+	if (!rprop)
+		return;
+
+	sprintf(tmp_buf, "%s@%lx",
+		dp->name, *(unsigned long *)(rprop->value));
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+	char tmp_buf[64], *n;
+
+	tmp_buf[0] = '\0';
+	__build_path_component(dp, tmp_buf);
+	if (tmp_buf[0] == '\0')
+		strcpy(tmp_buf, dp->name);
+
+	n = prom_early_alloc(strlen(tmp_buf) + 1);
+	strcpy(n, tmp_buf);
+
+	return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+	int len, ourlen, plen;
+	char *n;
+
+	plen = strlen(dp->parent->full_name);
+	ourlen = strlen(dp->path_component_name);
+	len = ourlen + plen + 2;
+
+	n = prom_early_alloc(len);
+	strcpy(n, dp->parent->full_name);
+	if (!is_root_node(dp->parent)) {
+		strcpy(n + plen, "/");
+		plen++;
+	}
+	strcpy(n + plen, dp->path_component_name);
+
+	return n;
+}
+
+static unsigned int unique_id;
+
+static struct property * __init build_one_prop(char *name, void *val, int len, struct property *next)
+{
+	struct property *p;
+	
+	p = prom_early_alloc(sizeof(struct property) + 32);
+	p->unique_id = unique_id++;
+
+	p->name = (char *) (p + 1);
+	strncpy(p->name, name, 31);
+	p->length = len;
+	p->value = prom_early_alloc(len);
+	memcpy(p->value, val, len);
+	p->next = next;
+
+	return p;
+}
+
+
+static struct device_node * __init create_node(const char *name, const char *type)
+{
+	struct device_node *dp;
+
+	dp = prom_early_alloc(sizeof(*dp));
+	dp->unique_id = unique_id++;
+
+	kref_init(&dp->kref);
+
+	dp->name = name;
+	dp->type = type;
+	dp->node = (phandle)dp;
+
+	/* Build interrupts later... */
+
+	dp->properties = build_one_prop(".node", &dp->node, sizeof(phandle), NULL);
+
+	return dp;
+}
+
+static struct device_node *__init create_zs_node(unsigned long vaddr, const char *name, struct device_node *parent, struct device_node ***nextp, struct device_node ***sibp)
+{
+	struct device_node *dp;
+	int irq = 6;
+
+	dp = create_node(name, "serial");
+	if(dp) {
+		*(*nextp) = dp;
+		*nextp = &dp->allnext;
+		if(sibp) {
+			*(*sibp) = dp;
+			*sibp = &dp->sibling;
+		}
+
+		dp->parent = parent;
+		dp->path_component_name = build_path_component(dp);
+		dp->full_name = build_full_name(dp);
+		dp->properties = build_one_prop("interrupts", &irq, sizeof(int), dp->properties); 	
+		dp->properties = build_one_prop("start", &vaddr, sizeof(vaddr), dp->properties); 	
+		vaddr = PAGE_SIZE;
+		dp->properties = build_one_prop("size", &vaddr, sizeof(vaddr), dp->properties); 	
+		dp->properties = build_one_prop("mapped", &irq, sizeof(int), dp->properties); 
+	}
+
+	return dp;
+}
+
+static unsigned long __init sun3_find_pte(unsigned long pte)
+{
+#ifdef CONFIG_SUN3
+	unsigned long vaddr;
+	for(vaddr = 0xfe00000; vaddr < (0xfe00000 +
+					SUN3_PMEG_SIZE); vaddr += SUN3_PTE_SIZE) {
+		unsigned long iopte;
+		
+		iopte = sun3_get_pte(vaddr);
+		if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
+			continue;
+
+		if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) == pte) 
+			break;
+	}
+	
+        return vaddr;
+#else
+        BUG();
+        return 0;
+#endif
+}
+
+struct device_node *of_console_device;
+EXPORT_SYMBOL(of_console_device);
+
+char *of_console_path;
+EXPORT_SYMBOL(of_console_path);
+
+char *of_console_options;
+EXPORT_SYMBOL(of_console_options);
+
+extern void restore_current(void);
+
+static void __init of_console_init(void)
+{
+	char *msg = "OF stdout device is: %s\n";
+	struct device_node *dp;
+	unsigned long flags;
+	const char *type;
+	phandle node;
+	int skip, tmp, fd;
+
+	of_console_path = prom_early_alloc(256);
+
+	/* only need to support V0 prom here */
+	skip = 0;
+#if 0
+	/* TODO -- support actual detection of the values in the EEPROM
+	   so that we can make a resonable choice for display device...
+	   However, as we still haven't integrated sun3 framebuffer support,
+	   force ourselves to serial (which, lacking configuration, should
+	   default to 9600,8,n,1) */
+	switch (*romvec->pv_stdout) {
+	case PROMDEV_SCREEN:
+		type = "display";
+		break;
+		
+	case PROMDEV_TTYB:
+		skip = 1;
+		/* FALLTHRU */
+		
+	case PROMDEV_TTYA:
+		type = "serial";
+		break;
+		
+	default:
+		prom_printf("Invalid PROM_V0 stdout value %u\n",
+			    *romvec->pv_stdout);
+		prom_halt();
+	}
+#else
+	type = "serial";
+#endif
+	
+	tmp = skip;
+	for_each_node_by_type(dp, type) {
+		if (!tmp--)
+			break;
+	}
+	if (!dp) {
+		prom_printf("Cannot find PROM_V0 console node.\n");
+		prom_halt();
+	}
+	of_console_device = dp;
+	
+	strcpy(of_console_path, dp->full_name);
+	if (!strcmp(type, "serial")) {
+		strcat(of_console_path,
+		       (skip ? ":b" : ":a"));
+	}
+
+	of_console_options = strrchr(of_console_path, ':');
+	if (of_console_options) {
+		of_console_options++;
+		if (*of_console_options == '\0')
+			of_console_options = NULL;
+	}
+
+	prom_printf(msg, of_console_path);
+	printk(msg, of_console_path);
+}
+
+void __init prom_build_devicetree(void)
+{
+	struct device_node **nextp;
+	struct device_node **sibp;
+	unsigned long zs0_addr, zs1_addr;
+	struct device_node *kbd;
+
+	allnodes = create_node("/", "");
+	allnodes->path_component_name = "";
+	allnodes->full_name = "/";
+
+	nextp = &allnodes->allnext;
+
+	/* hardcode a list of devices, and directly add them based on what type
+	   of sun3 we've got.  Use a flat list below root, there's really no
+	   need for a tree here. */
+
+	/* zs -- all sun3's have these */
+	if(idprom->id_machtype & SM_SUN3X) {
+		zs0_addr = SUN3X_ZS2;
+		zs1_addr = SUN3X_ZS1;
+	} else if(idprom->id_machtype & SM_SUN3) {
+		zs0_addr = sun3_find_pte(0x20000);
+		zs1_addr = sun3_find_pte(0x0);
+	} else {
+		prom_printf("Unknown machine type: 0x%x\n", idprom->id_machtype);
+		prom_halt();
+	}
+
+	allnodes->child = create_zs_node(zs0_addr, "zs", allnodes, &nextp, NULL);
+	sibp = &allnodes->child->sibling;
+	kbd = create_zs_node(zs1_addr, "zs", allnodes, &nextp, &sibp);
+	kbd->properties = build_one_prop("keyboard", &kbd, sizeof(void *), kbd->properties); 
+
+	of_console_init();
+
+	printk("PROM: Built device tree with %u bytes of memory.\n",
+	       prom_early_allocated);
+}
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index c03072b..f7a2afe 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -1,3 +1,3 @@
 config OF_DEVICE
 	def_bool y
-	depends on OF && (SPARC || PPC_OF)
+	depends on OF && (SPARC || PPC_OF || SUN3 || SUN3X)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ed438bc..20e9a34 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -776,14 +776,14 @@ config SERIAL_UARTLITE_CONSOLE
 
 config SERIAL_SUNCORE
 	bool
-	depends on SPARC
+	depends on SPARC || SUN3 || SUN3X
 	select SERIAL_CORE
 	select SERIAL_CORE_CONSOLE
 	default y
 
 config SERIAL_SUNZILOG
 	tristate "Sun Zilog8530 serial support"
-	depends on SPARC
+	depends on SPARC || SUN3 || SUN3X
 	help
 	  This driver supports the Zilog8530 serial ports found on many Sparc
 	  systems.  Say Y or M if you want to be able to these serial ports.
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index 70a09a3..3902d86 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -61,25 +61,27 @@ sunserial_console_termios(struct console *con)
 	char parity;
 
 	dp = of_find_node_by_path("/options");
-	od = of_get_property(dp, "output-device", NULL);
-	if (!strcmp(od, "rsc")) {
-		mode = of_get_property(of_console_device,
-				       "ssp-console-modes", NULL);
-		if (!mode)
-			mode = "115200,8,n,1,-";
-	} else {
-		char c;
-
-		c = 'a';
-		if (of_console_options)
-			c = *of_console_options;
-
-		mode_prop[3] = c;
-
-		mode = of_get_property(dp, mode_prop, NULL);
-		if (!mode)
-			mode = "9600,8,n,1,-";
+	if(dp) {
+		od = of_get_property(dp, "output-device", NULL);
+		if (!strcmp(od, "rsc")) {
+			mode = of_get_property(of_console_device,
+					       "ssp-console-modes", NULL);
+			if (!mode)
+				mode = "115200,8,n,1,-";
+		} else {
+			char c;
+			
+			c = 'a';
+			if (of_console_options)
+				c = *of_console_options;
+			
+			mode_prop[3] = c;
+			
+			mode = of_get_property(dp, mode_prop, NULL);
+		}
 	}
+	if (!mode)
+		mode = "9600,8,n,1,-";
 
 	cflag = CREAD | HUPCL | CLOCAL;
 
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 283bef0..23af5b3 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1363,9 +1363,13 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
 	if (of_find_property(op->node, "keyboard", NULL))
 		keyboard_mouse = 1;
 
-	sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
-					      sizeof(struct zilog_layout),
-					      "zs");
+	if(of_find_property(op->node, "mapped", NULL))
+		sunzilog_chip_regs[inst] = (struct sunzilog_layout *)op->resource[0].start;
+	else
+		sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
+						      sizeof(struct zilog_layout),
+						      "zs");
+
 	if (!sunzilog_chip_regs[inst])
 		return -ENOMEM;
 
diff --git a/include/asm-m68k/of_device.h b/include/asm-m68k/of_device.h
new file mode 100644
index 0000000..23abb84
--- /dev/null
+++ b/include/asm-m68k/of_device.h
@@ -0,0 +1,38 @@
+#ifndef _ASM_M68K_OF_DEVICE_H
+#define _ASM_M68K_OF_DEVICE_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/mod_devicetable.h>
+#include <asm/openprom.h>
+
+/*
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties.
+ */
+struct of_device
+{
+	struct device_node		*node;
+	struct device			dev;
+	struct resource			resource[PROMREG_MAX];
+	unsigned int			irqs[PROMINTR_MAX];
+	int				num_irqs;
+
+	void				*sysdata;
+
+	int				slot;
+	int				portid;
+	int				clock_freq;
+};
+
+extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
+extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
+
+/* These are just here during the transition */
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_M68K_OF_DEVICE_H */
diff --git a/include/asm-m68k/of_platform.h b/include/asm-m68k/of_platform.h
new file mode 100644
index 0000000..a3087e5
--- /dev/null
+++ b/include/asm-m68k/of_platform.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_M68K_OF_PLATFORM_H
+#define _ASM_M68K_OF_PLATFORM_H
+/*
+ *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ *			 <benh@xxxxxxxxxxxxxxxxxxx>
+ *    Modified for Sparc by merging parts of asm-sparc/of_device.h
+ *		by Stephen Rothwell
+ *
+ *  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 is just here during the transition */
+#include <linux/of_platform.h>
+
+#define of_bus_type	of_platform_bus_type	/* for compatibility */
+
+extern struct of_device *of_platform_device_create(struct device_node *np,
+						   const char *bus_id,
+						   struct device *parent,
+						   struct bus_type *bus);
+
+#endif	/* _ASM_M68K_OF_PLATFORM_H */
diff --git a/include/asm-m68k/openprom.h b/include/asm-m68k/openprom.h
index 869ab91..c7dc7db 100644
--- a/include/asm-m68k/openprom.h
+++ b/include/asm-m68k/openprom.h
@@ -1,6 +1,6 @@
 /* $Id: openprom.h,v 1.19 1996/09/25 03:51:08 davem Exp $ */
-#ifndef __SPARC_OPENPROM_H
-#define __SPARC_OPENPROM_H
+#ifndef __M68K_OPENPROM_H
+#define __M68K_OPENPROM_H
 
 /* openprom.h:  Prom structures and defines for access to the OPENBOOT
  *              prom routines and data areas.
@@ -310,4 +310,4 @@ struct linux_prom_ranges {
 
 #endif /* !(__ASSEMBLY__) */
 
-#endif /* !(__SPARC_OPENPROM_H) */
+#endif /* !(__M68K_OPENPROM_H) */
diff --git a/include/asm-m68k/prom.h b/include/asm-m68k/prom.h
new file mode 100644
index 0000000..dcdbc0e
--- /dev/null
+++ b/include/asm-m68k/prom.h
@@ -0,0 +1,95 @@
+#ifndef _M68K_PROM_H
+#define _M68K_PROM_H
+#ifdef __KERNEL__
+
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC32 by David S. Miller
+ * Updates for sun3 by Sam Creasey
+ *
+ * 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.
+ */
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+
+#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT	1
+#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT	1
+
+#define of_compat_cmp(s1, s2, l)	strncmp((s1), (s2), (l))
+#define of_prop_cmp(s1, s2)		strcasecmp((s1), (s2))
+#define of_node_cmp(s1, s2)		strcmp((s1), (s2))
+
+typedef u32 phandle;
+typedef u32 ihandle;
+
+struct property {
+	char	*name;
+	int	length;
+	void	*value;
+	struct property *next;
+	unsigned long _flags;
+	unsigned int unique_id;
+};
+
+struct device_node {
+	const char	*name;
+	const char	*type;
+	phandle	node;
+	char	*path_component_name;
+	char	*full_name;
+
+	struct	property *properties;
+	struct  property *deadprops; /* removed properties */
+	struct	device_node *parent;
+	struct	device_node *child;
+	struct	device_node *sibling;
+	struct	device_node *next;	/* next device of same type */
+	struct	device_node *allnext;	/* next in list of all nodes */
+	struct  proc_dir_entry *pde;	/* this node's proc directory */
+	struct  kref kref;
+	unsigned long _flags;
+	void	*data;
+	unsigned int unique_id;
+};
+
+#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
+#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+
+extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
+extern int of_getintprop_default(struct device_node *np,
+				 const char *name,
+				 int def);
+extern int of_find_in_proplist(const char *list, const char *match, int len);
+
+extern void prom_build_devicetree(void);
+
+/* Dummy ref counting routines - to be implemented later */
+static inline struct device_node *of_node_get(struct device_node *node)
+{
+	return node;
+}
+static inline void of_node_put(struct device_node *node)
+{
+}
+
+/*
+ * NB:  This is here while we transition from using asm/prom.h
+ * to linux/of.h
+ */
+#include <linux/of.h>
+
+extern struct device_node *of_console_device;
+extern char *of_console_path;
+extern char *of_console_options;
+
+#endif /* __KERNEL__ */
+#endif /* _M68K_PROM_H */
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index caa9b16..3c83b4d 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -8,6 +8,23 @@
 
 #ifdef __KERNEL__
 
+/* compatibilty code for sparc drivers used in sun3/sun3x */
+#ifdef CONFIG_SUN3
+#include <asm/oplib.h>
+static inline void sun_do_break(void)
+{
+	prom_reboot("");
+}
+#else
+#ifdef CONFIG_SUN3X
+#include <asm/sun3xprom.h>
+static inline void sun_do_break(void)
+{
+	sun3x_reboot();
+}
+#endif
+#endif
+
 /*
  * switch_to(n) should switch tasks to task ptr, first checking that
  * ptr isn't the current task, in which case it does nothing.  This
-
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux