Signed-off-by: Maria Butrico <butrico@xxxxxxxxxxxxxx>
summary: serial port discovery and zilog device driver.
diff -r 2039069d08ca xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c Wed May 24 17:09:51 2006 -0500
+++ b/xen/arch/ppc/boot_of.c Thu May 25 12:21:06 2006 -0400
@@ -27,6 +27,9 @@
#include <public/of-devtree.h>
#include <asm/page.h>
#include <asm/io.h>
+#include <xen/string.h>
+#include <xen/serial.h>
+#include <asm-ppc/uart.h>
#include "exceptions.h"
static ulong of_vec;
@@ -36,7 +39,13 @@ static char bootargs[256];
static char bootargs[256];
static char dom0args[256];
-extern struct ns16550_defaults ns16550;
+struct uart uarts[] = {
+ { .type = ns16550, .uart_name = "ns16550", .p_sign = "isa",
+ .gp_sign = "ht", .uart_init_func = ns16550_init },
+ { .type = pmac_zilog, .uart_name = "zilog", .p_sign = "escc",
+ .gp_sign = "mac-io", .uart_init_func = pmac_zilog_init },
+};
+struct platform_serial_port global_serial_port;
#undef OF_DEBUG
@@ -48,6 +57,11 @@ extern struct ns16550_defaults ns16550;
#define of_panic(MSG...) \
do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
+
+#define _IF_OF_FAILURE_RET(rc) \
+ if (unlikely((rc)==OF_FAILURE)) { \
+ return OF_FAILURE; \
+ }
struct of_service {
u32 ofs_service;
@@ -366,7 +380,6 @@ static void boot_of_probemem(multiboot_i
root = of_finddevice("/");
p = of_getchild(root);
- /* code is writen to assume sizes of 1 */
of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
DBG("%s: address_cells=%d size_cells=%d\n",
@@ -702,7 +715,7 @@ static ulong find_space(u32 size, ulong
ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
ulong base;
- of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%lx\n",
+ DBG("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%lx\n",
__func__, space_base, eomem, size, align);
base = ALIGN_UP(space_base, PAGE_SIZE);
if ((base + size) >= 0x4000000) return 0;
@@ -714,7 +727,7 @@ static ulong find_space(u32 size, ulong
return base;
} else {
for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
- of_printf("Trying 0x%016lx\n", base);
+ DBG("Trying 0x%016lx\n", base);
if (of_claim((void*)base, size) != OF_FAILURE) {
space_base = base + size;
return base;
@@ -760,20 +773,221 @@ static void __init boot_of_fix_maple(voi
}
}
-static int __init boot_of_serial(void *oftree)
-{
- int n;
- int p;
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ *
+ * The number of integers in each size entry is
+ * determined by the value of the #size-cells property of this node (the node
in which the ranges property appears)
+ * or 1 if the #size-cells property is absent.
+ *
+ *
+ * pg 177, property "reg"
+ *
+ * The number of integers in each size entry is determined by the value of the
"#size-cells" property in the parent node.
+ * If the parent node has no such property, the value is one.
+ */
+static void boot_of_serial_ns16550(int ofout, int parent, int grandparent)
+{
+ u32 addr_cells, size_cells;
+
+ /* the struct isa_reg_property is for a value of 2 for #address-cells and a
+ * value of 1 for #size-cells (of the parent).
+ */
+ struct isa_reg_property {
+ u32 space;
+ u32 address;
+ u32 size;
+ } isa_reg;
+
+ struct of_pci_range64_s {
+ u32 flags;
+ u32 opa_mid;
+ u32 opa_lo;
+ u32 opr_phys_hi;
+ u32 opr_phys_lo;
+ u32 opr_size_hi;
+ u32 opr_size_lo;
+ } r64;
+ u32 clock;
+
+ /* note that if a property does not exist, then the 3rd parameter to
+ * of_getprop is *not* altered
+ */
+ addr_cells = 2;
+ size_cells = 1;
+ of_getprop(grandparent, "#address-cells", &addr_cells, sizeof(addr_cells));
+ of_getprop(grandparent, "#size-cells", &size_cells, sizeof(size_cells));
+ DBG("In %s: value for grandparent #address-cells %d "
+ "and #size-cells %d\n",
+ __func__, addr_cells, size_cells);
+ of_getprop(grandparent , "ranges", &r64, sizeof(r64));
+
+ addr_cells = 2;
+ size_cells = 1;
+ of_getprop(ofout, "#address-cells", &addr_cells, sizeof(addr_cells));
+ of_getprop(parent, "#size-cells", &size_cells, sizeof(size_cells));
+ DBG("In %s: value for #address-cells %d "
+ "and #size-cells %d\n",
+ __func__, addr_cells, size_cells);
+
+ of_getprop(ofout, "reg", &isa_reg, sizeof(isa_reg));
+
+ of_getprop(ofout, "clock-frequency", &clock, sizeof (clock));
+
+ of_printf("reg property address=0x%08x size=0x%08x\n",
+ isa_reg.address, isa_reg.size);
+ of_printf("ranges property %x:%x %x:%x\n",
+ r64.opr_phys_hi, r64.opr_phys_lo,
+ r64.opr_size_hi, r64.opr_size_lo);
+
+ global_serial_port.uart_io_base = isa_reg.address;
+ isa_io_base = r64.opr_phys_hi;
+ isa_io_base <<= 32;
+ isa_io_base |= r64.opr_phys_lo;
+ global_serial_port.clock = clock;
+}
+
+static void boot_of_serial_zilog(int ofout, int parent, int grandparent)
+{
+ u32 addr_cells, size_cells;
+
+ /* the struct reg_property32 is for a value of 1 for #address-cells and
+ * a value of 1 for #size-cells.
+ */
+ struct reg_property32 {
+ u32 address;
+ u32 size;
+ } reg;
+
+ /* the struct of_pic_range32_s is for a value of 1 of #address-cells
+ * for ?? and a value of 1 for #size-cells.
+ */
+ struct of_pci_range32_s {
+ u32 flags;
+ u32 opa_mid;
+ u32 opa_lo;
+ u32 opr_phys;
+ u32 opr_size;
+ } r32;
+
+ addr_cells = 2;
+ size_cells = 1;
+ of_getprop(grandparent, "#address-cells", &addr_cells, sizeof(addr_cells));
+ of_getprop(grandparent, "#size-cells", &size_cells, sizeof(size_cells));
+ DBG("In %s: value for grandparent #address-cells %d "
+ "or #size-cells %d\n",
+ __func__, addr_cells, size_cells);
+ of_getprop(grandparent , "ranges", &r32, sizeof(r32));
+
+ addr_cells = 2;
+ size_cells = 1;
+ of_getprop(ofout, "#address-cells", &addr_cells, sizeof(addr_cells));
+ of_getprop(parent, "#size-cells", &size_cells, sizeof(size_cells));
+ DBG("In %s %d: value for #address-cells %d "
+ "or #size-cells %d\n",
+ __func__, addr_cells, size_cells);
+ of_getprop(ofout, "reg", ®, sizeof(reg));
+
+ of_printf("reg property address=0x%08x size=0x%08x\n",
+ reg.address, reg.size);
+ of_printf("ranges property %x %x\n",
+ r32.opr_phys, r32.opr_size);
+
+ global_serial_port.uart_io_base = reg.address;
+ isa_io_base = r32.opr_phys;
+}
+
+/*
+ * return OF_FAILURE if it cannot find the serial device
+ * the of handle of the serial device otherwise
+ */
+static int __init boot_of_serial_simple_probe(void)
+{
+ int node;
+ char buf[64];
+
+ node = of_instance_to_package(of_out);
+ if (node == OF_FAILURE) {
+ return OF_FAILURE;
+ }
+
+ buf[0] = '\0';
+ of_getprop(node, "device_type", buf, sizeof (buf));
+ if (strstr(buf, "serial") == NULL) {
+ return OF_FAILURE;
+ }
+
+ return node;
+}
+
+/*
+ * return OF_FAILURE if it cannot find the serial device
+ * the of handle of the serial device otherwise
+ */
+static int __init boot_of_serial_canonical_probe()
+{
+ int p, ofout; /* of handle */
int rc;
- u32 val[3];
+ char ofout_path[256] = {0,};
+ const char serial[] = "serial";
+
+ /* copied and adapted from rhype */
+ ofout_path[0] = '\0';
+ ofout = OF_FAILURE;
+
+ /* probe /options tree */
+ rc = p = of_finddevice("/options");
+ if (p != OF_FAILURE) {
+ rc = of_getprop(p, "output-device", ofout_path,
+ sizeof(ofout_path));
+ }
+ if (OF_FAILURE == rc) {
+ strncpy(ofout_path, serial, sizeof(serial));
+ }
+
+ /*
+ * if the options are not a path (they do not start with '/')
+ * then they are aliases and we must look them up. we look it
+ * up in aliases because it is possible that the OF does not
+ * support finddevice() of an alias.
+ */
+ if (ofout_path[0] != '/') {
+ p = of_finddevice("/aliases");
+ if (p != OF_FAILURE) {
+ char alias[256];
+ memcpy(alias, ofout_path, sizeof(alias));
+ rc = of_getprop(p, alias, ofout_path, sizeof (ofout_path));
+ }
+ }
+
+ if (OF_FAILURE != rc) {
+ ofout = of_finddevice(ofout_path);
+ } else {
+ /*
+ * Our last chance is to figure out the package for
+ * the current console and hopefully discover it to be
+ * a serial device.
+ */
+ /* of_out is the phandle of the property 'stdout' of
+ *'chosen'.
+ */
+ rc = of_instance_to_path(of_out, ofout_path, sizeof(ofout_path));
+ if (rc != OF_FAILURE) {
+ ofout = of_finddevice(ofout_path);
+ }
+ }
+
+ return ofout;
+}
+
+static void __init boot_of_serial_prune(void *oftree, int n)
+{
char buf[128];
-
- n = of_instance_to_package(of_out);
- if (n == OF_FAILURE) {
- of_panic("instance-to-package of /chosen/stdout: failed\n");
- }
-
- /* prune this from the oftree */
+ int rc;
+
+ /* prune serial device from OF tree */
rc = of_package_to_path(n, buf, sizeof(buf));
if (rc == OF_FAILURE) {
of_panic("package-to-path of /chosen/stdout: failed\n");
@@ -782,54 +996,121 @@ static int __init boot_of_serial(void *o
" since Xen will be using it for console\n", buf);
rc = ofd_prune_path(oftree, buf);
if (rc < 0) {
- of_panic("prune path \"%s\" failed\n", buf);
- }
-
-
- p = of_getparent(n);
- if (p == OF_FAILURE) {
- of_panic("no parent for: 0x%x\n", n);
- }
-
- buf[0] = '\0';
- of_getprop(p, "device_type", buf, sizeof (buf));
- if (strstr(buf, "isa") == NULL) {
- of_panic("only ISA UARTS supported\n");
- }
-
- /* should get this from devtree */
- isa_io_base = 0xf4000000;
- of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
-
- buf[0] = '\0';
- of_getprop(n, "device_type", buf, sizeof (buf));
- if (strstr(buf, "serial") == NULL) {
- of_panic("only UARTS supported\n");
- }
-
- rc = of_getprop(n, "reg", val, sizeof (val));
+ of_panic("prune path \"%s\" failed\n", buf);
+ }
+}
+
+/*
+ * return 0 is a serial port is found.
+ * OF_FAILURE if no serial port can be found
+ */
+static int __init boot_of_serial(void *oftree)
+{
+ int ofout; /* of handle */
+ int rc;
+ char of_property[256];
+ const char serial[] = "serial";
+ u32 interrupts, baud;
+
+ memset(&global_serial_port, 0, sizeof(global_serial_port));
+
+ ofout = boot_of_serial_simple_probe();
+ if (OF_FAILURE == ofout) {
+ of_printf("Warning %s: simple probe of serial device failed.\n",
+ __func__);
+ ofout = boot_of_serial_canonical_probe();
+ }
+
+ DBG("serial port OF handle=0x%x\n", ofout);
+
+ if (OF_FAILURE == ofout) {
+ of_printf("Could not find serial device.\n");
+ return OF_FAILURE;
+ }
+
+ /* Now we have the OF handle of the serial device. The device
+ * must have type 'serial'.
+ */
+ rc = of_getprop(ofout, "device_type", of_property, sizeof(of_property));
+ if (strncmp(of_property, serial, sizeof(serial))) {
+ of_printf("Serial device is not serial\n");
+ return OF_FAILURE;
+ }
+
+ /*
+ * Remove the device from the ofd tree
+ */
+ boot_of_serial_prune(oftree, ofout);
+
+ interrupts = 0;
+ rc = of_getprop(ofout, "interrupts", &interrupts, sizeof(interrupts));
if (rc == OF_FAILURE) {
- of_panic("%s: no location for serial port\n", __func__);
- }
- ns16550.io_base = val[1];
-
- ns16550.baud = BAUD_AUTO;
- ns16550.data_bits = 8;
- ns16550.parity = 'n';
- ns16550.stop_bits = 1;
-
- rc = of_getprop(n, "interrupts", val, sizeof (val));
+ of_printf("%s: no ISRC\n", __func__);
+ global_serial_port.interrupts = 0;
+ } else {
+ of_printf("%s: ISRC 0x%x\n", __func__, interrupts);
+ global_serial_port.interrupts = interrupts;
+ }
+
+ baud = 0;
+ rc = of_getprop(ofout, "current-speed", &baud, sizeof(baud));
if (rc == OF_FAILURE) {
- of_printf("%s: no ISRC, forcing poll mode\n", __func__);
- ns16550.irq = 0;
+ global_serial_port.baud = 0;
} else {
- ns16550.irq = val[0];
- of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
- __func__, ns16550.irq);
- ns16550.irq = 0;
- }
-
- return 1;
+ global_serial_port.baud = baud;
+ }
+
+ /*
+ * Look at the name of the grandparent directory and try to match it
+ * to known names.
+ */
+ int parent, grandparent; /* of handles */
+ parent = of_getparent(ofout);
+ _IF_OF_FAILURE_RET(parent);
+ grandparent = of_getparent(parent);
+ _IF_OF_FAILURE_RET(grandparent);
+
+ of_getprop(grandparent, "name", of_property, sizeof(of_property));
+ /*
+ * Loop over the known uarts and try and find a match
+ */
+ int i;
+ for (i = 0; i < ARRAY_SIZE(uarts); i++) {
+ if (!strcmp(of_property, uarts[i].gp_sign)) {
+ of_getprop(parent, "device_type", of_property,
+ sizeof(of_property));
+ if (strncmp(of_property, uarts[i].p_sign,
+ sizeof(uarts[i].p_sign))) {
+ of_printf("Serial device parent's type (%s) is not "
+ "expected(%s).\n", of_property, uarts[i].p_sign);
+ return OF_FAILURE;
+ }
+
+ of_printf("Found uart of type %s\n", uarts[i].uart_name);
+ global_serial_port.uart_p = &(uarts[i]);
+
+ if (pmac_zilog == uarts[i].type)
+ boot_of_serial_zilog(ofout, parent, grandparent);
+ else
+ boot_of_serial_ns16550(ofout, parent, grandparent);
+
+ of_printf("%s: serial type=%d io base=0x%016lx "
+ "isa io@=0x%016lx clock=%d interrupts=0x%x "
+ "baud=%d\n",
+ __func__, global_serial_port.uart_p->type,
+ global_serial_port.uart_io_base,
+ isa_io_base,
+ global_serial_port.clock,
+ global_serial_port.interrupts,
+ global_serial_port.baud
+ );
+
+ return 0;
+ }
+ }
+ of_printf("Warning: boot_of::%s is not aware of this uart type. "
+ "%s is:\n", __func__, of_property);
+ return OF_FAILURE;
}
static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
diff -r 2039069d08ca xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c Wed May 24 17:09:51 2006 -0500
+++ b/xen/arch/ppc/setup.c Thu May 25 12:21:06 2006 -0400
@@ -37,6 +37,7 @@
#include <asm/cache.h>
#include <asm/debugger.h>
#include <asm/delay.h>
+#include <asm-ppc/uart.h>
#include "exceptions.h"
#define DEBUG
@@ -61,15 +62,14 @@ cpumask_t cpu_sibling_map[NR_CPUS] __rea
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
-/* XXX get this from ISA node in device tree */
-ulong isa_io_base;
-struct ns16550_defaults ns16550;
-
struct vcpu *idle_vcpu[NR_CPUS];
extern void idle_loop(void);
/* move us to a header file */
extern void initialize_keytable(void);
+
+extern struct platform_serial_port global_serial_port;
+ulong isa_io_base;
int is_kernel_text(unsigned long addr)
{
@@ -164,7 +164,22 @@ static void __init __start_xen(multiboot
if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
cmdline_parse(__va((ulong)mbi->cmdline));
- ns16550_init(0, &ns16550);
+ /* We initialise the serial devices very early so we can get debugging. */
+ {
+ /*
+ * the type of device is recorded in the global hardware stuff struct
+ */
+ struct ns16550_defaults ns16550 = {
+ .data_bits = 8,
+ .parity = 'n',
+ .stop_bits = 1,
+ .irq = 0,
+ };
+ ns16550.io_base = isa_io_base +
+ global_serial_port.uart_io_base;
+ ns16550.baud = global_serial_port.baud;
+ global_serial_port.uart_p->uart_init_func(0, &ns16550);
+ }
serial_init_preirq();
init_console();
diff -r 2039069d08ca xen/drivers/char/Makefile
--- a/xen/drivers/char/Makefile Wed May 24 17:09:51 2006 -0500
+++ b/xen/drivers/char/Makefile Thu May 25 12:21:06 2006 -0400
@@ -1,5 +1,6 @@ obj-y += console.o
obj-y += console.o
obj-y += ns16550.o
+obj-y += pmac_zilog.o
obj-y += serial.o
# Object file contains changeset and compiler information.
diff -r 2039069d08ca xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c Wed May 24 17:09:51 2006 -0500
+++ b/xen/drivers/char/ns16550.c Thu May 25 12:21:06 2006 -0400
@@ -276,7 +276,7 @@ static struct uart_driver ns16550_driver
.irq = ns16550_irq
};
-static int parse_parity_char(int c)
+int parse_parity_char(int c)
{
switch ( c )
{
diff -r 2039069d08ca xen/include/xen/serial.h
--- a/xen/include/xen/serial.h Wed May 24 17:09:51 2006 -0500
+++ b/xen/include/xen/serial.h Thu May 25 12:21:06 2006 -0400
@@ -8,6 +8,8 @@
#ifndef __XEN_SERIAL_H__
#define __XEN_SERIAL_H__
+
+#include <xen/spinlock.h>
struct cpu_user_regs;
@@ -128,6 +130,7 @@ struct ns16550_defaults {
unsigned long io_base; /* default io_base address */
};
void ns16550_init(int index, struct ns16550_defaults *defaults);
+void pmac_zilog_init(int index, struct ns16550_defaults *defaults);
/* Baud rate was pre-configured before invoking the UART driver. */
#define BAUD_AUTO (-1)
diff -r 2039069d08ca xen/drivers/char/pmac_zilog.c
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/drivers/char/pmac_zilog.c Thu May 25 12:21:06 2006 -0400
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: zilog.c,v 1.3 2005/05/05 20:51:04 mostrows Exp $
+ */
+
+/*
+ * linux/drivers/serial/pmac_zilog.c
+ *
+ * Driver for PowerMac Z85c30 based ESCC cell found in the
+ * "macio" ASICs of various PowerMac models
+ *
+ * Copyright (C) 2003 Ben. Herrenschmidt (benh@xxxxxxxxxxxxxxxxxxx)
+ *
+ * Derived from drivers/macintosh/macserial.c by Paul Mackerras
+ * and drivers/serial/sunzilog.c by David S. Miller
+ *
+ * Hrm... actually, I ripped most of sunzilog (Thanks David !) and
+ * adapted special tweaks needed for us. I don't think it's worth
+ * merging back those though. The DMA code still has to get in
+ * and once done, I expect that driver to remain fairly stable in
+ * the long term, unless we change the driver model again...
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 2004-08-06 Harald Welte <laforge@xxxxxxxxxxxx>
+ * - Enable BREAK interrupt
+ * - Add support for sysreq
+ *
+ * TODO: - Add DMA support
+ * - Defer port shutdown to a few seconds after close
+ * - maybe put something right into uap->clk_divisor
+ */
+
+/******************************************************************************
+ * pmac_zilog.c
+ *
+ * From rhype and linux
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/serial.h>
+#include <xen/iocap.h>
+#include <asm/io.h>
+#include <xen/delay.h>
+#include "pmac_zilog.h"
+
+#undef ZILOG_DEBUG
+#ifdef ZILOG_DEBUG
+int of_printf(const char *fmt, ...);
+#define DBG(args...) of_printf(args)
+#else
+#define DBG(args...)
+#endif
+
+
+/* from rhype and linux */
+
+struct uart_pmac_port uaps[MAX_ZS_PORTS];
+
+extern int parse_parity_char(int c);
+
+#define PANIC(_f) \
+ { \
+ printk( "ERROR: " _f "\n"); \
+ }
+
+/* internal */
+static char pmac_zilog_read_reg(struct uart_port *uart, int reg, int verbose)
+{
+ if (verbose)
+ DBG("%s: readb 0x%x\n", __func__, uart->remapped_io_base + reg);
+ return readb(uart->remapped_io_base + reg);
+}
+
+/* internal */
+static void pmac_zilog_write_reg(struct uart_port *uart, int reg, char c, int
verbose)
+{
+ if (verbose)
+ DBG("%s: writeb 0x%x 0x%02x\n", __func__, uart->remapped_io_base +
reg, c);
+ writeb(c, uart->remapped_io_base + reg);
+}
+
+/* internal */
+/* Note this is equivalent to linux read_zsreg followed by the bit AND */
+static int pmac_zilog_chkbit(struct uart_port *ops, int reg, int bit)
+{
+ char c;
+
+ // to read any register (but 0), first write the register number to the
+ // control register, then read the control register
+ //
+ if (reg != 0) { pmac_zilog_write_reg(ops, REG_CONTROL, reg, 0); }
+ c = pmac_zilog_read_reg(ops, REG_CONTROL, 0);
+ return (c & bit) == bit;
+}
+
+/* internal from linux */
+/*
+ * Load all registers to reprogram the port
+ * This function must only be called when the TX is not busy. The UART
+ * port lock must be held and local interrupts disabled.
+ */
+static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs)
+{
+ int i;
+
+ if (ZS_IS_ASLEEP(uap))
+ return;
+
+ /* Let pending transmits finish. */
+ for (i = 0; i < 1000; i++) {
+ unsigned char stat = read_zsreg(uap, R1);
+ if (stat & ALL_SNT)
+ break;
+ udelay(100);
+ }
+
+ ZS_CLEARERR(uap);
+ zssync(uap);
+ ZS_CLEARFIFO(uap);
+ zssync(uap);
+ ZS_CLEARERR(uap);
+
+ /* Disable all interrupts. */
+ write_zsreg(uap, R1,
+ regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
+
+ /* Set parity, sync config, stop bits, and clock divisor. */
+ write_zsreg(uap, R4, regs[R4]);
+
+ /* Set misc. TX/RX control bits. */
+ write_zsreg(uap, R10, regs[R10]);
+
+ /* Set TX/RX controls sans the enable bits. */
+ write_zsreg(uap, R3, regs[R3] & ~RxENABLE);
+ write_zsreg(uap, R5, regs[R5] & ~TxENABLE);
+
+ /* now set R7 "prime" on ESCC */
+ write_zsreg(uap, R15, regs[R15] | EN85C30);
+ write_zsreg(uap, R7, regs[R7P]);
+
+ /* make sure we use R7 "non-prime" on ESCC */
+ write_zsreg(uap, R15, regs[R15] & ~EN85C30);
+
+ /* Synchronous mode config. */
+ write_zsreg(uap, R6, regs[R6]);
+ write_zsreg(uap, R7, regs[R7]);
+
+ /* Disable baud generator. */
+ write_zsreg(uap, R14, regs[R14] & ~BRENAB);
+
+ /* Clock mode control. */
+ write_zsreg(uap, R11, regs[R11]);
+
+ /* Lower and upper byte of baud rate generator divisor. */
+ write_zsreg(uap, R12, regs[R12]);
+ write_zsreg(uap, R13, regs[R13]);
+
+ /* Now rewrite R14, with BRENAB (if set). */
+ write_zsreg(uap, R14, regs[R14]);
+
+ /* Reset external status interrupts. */
+ write_zsreg(uap, R0, RES_EXT_INT);
+ write_zsreg(uap, R0, RES_EXT_INT);
+
+ /* Rewrite R3/R5, this time without enables masked. */
+ write_zsreg(uap, R3, regs[R3]);
+ write_zsreg(uap, R5, regs[R5]);
+
+ /* Rewrite R1, this time without IRQ enabled masked. */
+ write_zsreg(uap, R1, regs[R1]);
+
+ /* Enable interrupts */
+ write_zsreg(uap, R9, regs[R9]);
+}
+
+static void pmac_zilog_init_preirq(struct serial_port *port)
+{
+ struct uart_pmac_port *uap = port->uart;
+ struct uart_port *uart = &(uap->port);
+ unsigned int divisor;
+
+ uart->remapped_io_base = (char *)ioremap(uart->io_base, 8);
+
+ /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
+ /* parity, data bit (8 or bust) and stop bits todo */
+
+#define LINUX_PMAC_ZILOG_INIT
+#ifdef LINUX_PMAC_ZILOG_INIT
+ /* from Linux's __pmz_startup(). Modified */
+ {
+ uap->flags = PMACZILOG_FLAG_IS_CHANNEL_A
+ | PMACZILOG_FLAG_IS_IRDA
+ ;
+
+ memset(&uap->curregs, 0, sizeof(uap->curregs));
+
+ /* Power up the SCC & underlying hardware (modem/irda) */
+ //(void) pmz_set_scc_power(uap, 1); TODO?
+
+ /* Nice buggy HW ... */
+ //pmz_fix_zero_bug_scc(uap); TODO
+
+ /* Reset the channel */
+ uap->curregs[R9] = 0;
+ write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB);
+ zssync(uap);
+ udelay(10);
+ write_zsreg(uap, 9, 0);
+ zssync(uap);
+
+ /* Clear the interrupt registers */
+ write_zsreg(uap, R1, 0);
+ write_zsreg(uap, R0, ERR_RES);
+ write_zsreg(uap, R0, ERR_RES);
+ write_zsreg(uap, R0, RES_H_IUS);
+ write_zsreg(uap, R0, RES_H_IUS);
+
+ /* Setup some valid baud rate */
+ uap->curregs[R4] = X16CLK | SB1;
+ uap->curregs[R3] = Rx8;
+ uap->curregs[R5] = Tx8 | RTS;
+ if (!ZS_IS_IRDA(uap))
+ uap->curregs[R5] |= DTR;
+
+ /* baud divisor */
+#define UART_CLOCK_HZ 0
+ if ( uart->baud == BAUD_AUTO ) {
+ divisor = read_zsreg(uap, R12);
+ divisor |= read_zsreg(uap, R13) << 8;
+ uart->baud = UART_CLOCK_HZ / (divisor * 16);
+ } else {
+ /* Baud rate specified: program it into the divisor latch. */
+ divisor = UART_CLOCK_HZ / (uart->baud * 16);
+ uap->curregs[R12] = (char)divisor; /* baud divisor lower byte */
+ uap->curregs[R13] = (char)(divisor >> 8); /* upper byte */
+ }
+
+ uap->curregs[R14] = BRENAB;
+
+ /* Clear handshaking, enable BREAK interrupts */
+ /* uap->curregs[R15] = BRKIE; we don't want interrupts */
+
+ /* Master interrupt enable */
+ /* uap->curregs[R9] |= NV | MIE; we don't want interrupts */
+
+ pmz_load_zsregs(uap, uap->curregs);
+
+ /* Enable receiver and transmitter. */
+ write_zsreg(uap, R3, uap->curregs[R3] |= RxENABLE);
+ write_zsreg(uap, R5, uap->curregs[R5] |= TxENABLE);
+
+ /* Remember status for DCD/CTS changes */
+ uap->prev_status = read_zsreg(uap, R0);
+
+ }
+#endif /* #ifdef LINUX_PMAC_ZILOG_INIT */
+
+ /* Enable and clear the FIFOs. Set a large trigger threshold. */
+ port->tx_fifo_size = 2048;
+}
+
+static void pmac_zilog_init_postirq(struct serial_port *port)
+{
+ PANIC("postirq!");
+}
+
+/* internal */
+static int pmac_zilog_write_avail(struct uart_port *ops)
+{
+ if (pmac_zilog_chkbit(ops, 0, Tx_BUF_EMP) &&
+ pmac_zilog_chkbit(ops, 1, ALL_SNT)) {
+ return 2048;
+ }
+ return 0;
+}
+
+/* Transmit FIFO ready to receive up to @tx_fifo_size characters? */
+static int pmac_zilog_tx_empty(struct serial_port *port)
+{
+ struct uart_pmac_port *uap = port->uart;
+ struct uart_port *uart = &(uap->port);
+
+ static int call_count = 0; // debug
+ call_count++;
+ if ((call_count < 1) ) {
+ DBG("%s: count=%d\n", __func__, call_count);
+ }
+
+ return pmac_zilog_write_avail(uart);
+}
+
+static void pmac_zilog_putc(struct serial_port *port, char c)
+{
+ struct uart_pmac_port *uap = port->uart;
+ struct uart_port *uart = &(uap->port);
+
+ static int call_count = 0; // debug
+ call_count++;
+ if ((call_count < 1 )) {
+ DBG("%s: count=%d\n", __func__, call_count);
+ }
+
+ pmac_zilog_write_reg(uart, REG_DATA, c, 0);
+}
+
+/* internal */
+static int pmac_zilog_read_avail(struct uart_port *ops)
+{
+ char c = pmac_zilog_read_reg(ops, REG_CONTROL, 0);
+ if (c & Rx_CH_AV) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* Get a character from the serial line: returns 0 if none available. */
+static int pmac_zilog_getc(struct serial_port *port, char *pc)
+{
+ struct uart_pmac_port *uap = port->uart;
+ struct uart_port *uart = &(uap->port);
+ int rc;
+
+ static int call_count = 0; // debug
+ call_count++;
+ if ((call_count < 1)) {
+ DBG("%s: count=%d\n", __func__, call_count);
+ }
+
+ if (pmac_zilog_read_avail(uart)) {
+ *pc = pmac_zilog_read_reg(uart, REG_DATA, 0);
+ rc = 1;
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+#define PARSE_ERR(_f, _a...) \
+ do { \
+ printk( "ERROR: " _f "\n" , ## _a ); \
+ return; \
+ } while ( 0 )
+
+static struct uart_driver pmac_zilog_driver = {
+ .init_preirq = pmac_zilog_init_preirq,
+ .init_postirq = pmac_zilog_init_postirq,
+ .endboot = NULL,
+ .tx_empty = pmac_zilog_tx_empty,
+ .putc = pmac_zilog_putc,
+ .getc = pmac_zilog_getc
+};
+
+/* internal */
+static void pmac_zilog_parse_port_config(struct uart_port *uart, char *conf)
+{
+ /* Sanity checks. */
+ if ( (uart->baud != BAUD_AUTO) &&
+ ((uart->baud < 1200) || (uart->baud > 115200)) )
+ PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
+ if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
+ PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
+ if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
+ PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
+ if ( uart->io_base == 0 )
+ PARSE_ERR("I/O base address must be specified.");
+}
+
+void pmac_zilog_init(int index, struct ns16550_defaults *defaults)
+{
+ if ( (index < 0) || (index >= MAX_ZS_PORTS) )
+ return;
+
+ memset(&uaps[index], 0, sizeof(struct uart_pmac_port));
+
+ if ( defaults != NULL )
+ {
+ uaps[index].port.baud = defaults->baud;
+ uaps[index].port.data_bits = defaults->data_bits;
+ uaps[index].port.parity = parse_parity_char(defaults->parity);
+ uaps[index].port.stop_bits = defaults->stop_bits;
+ uaps[index].port.irq = defaults->irq;
+ uaps[index].port.io_base = defaults->io_base;
+ }
+
+ pmac_zilog_parse_port_config(&(uaps[index].port), NULL);
+
+ /* Register with generic serial driver. */
+ serial_register_uart(index, &pmac_zilog_driver, &uaps[index]);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 2039069d08ca xen/drivers/char/pmac_zilog.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/drivers/char/pmac_zilog.h Thu May 25 12:21:06 2006 -0400
@@ -0,0 +1,405 @@
+#ifndef __PMAC_ZILOG_H__
+#define __PMAC_ZILOG_H__
+/****
+ * Linux code drivers/serial/pmac_zilog.h
+ * missing copyright notice in Linux tree
+ */
+
+/* Xen additions */
+/* copy of ns16550 in ns16550.c */
+struct uart_port {
+ int baud, data_bits, parity, stop_bits, irq;
+ unsigned long io_base; /* I/O port or memory-mapped I/O address. */
+ char *remapped_io_base; /* Remapped virtual address of mmap I/O. */
+ /* UART with IRQ line: interrupt-driven I/O. */
+ struct irqaction irqaction;
+ /* UART with no IRQ line: periodically-polled I/O. */
+ struct timer timer;
+};
+struct termios {
+};
+/* end Xen additions */
+
+#define pmz_debug(fmt,arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
+
+/*
+ * At most 2 ESCCs with 2 ports each
+ */
+#define MAX_ZS_PORTS 4
+
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+#define NUM_ZSREGS 17
+
+struct uart_pmac_port {
+ struct uart_port port;
+ struct uart_pmac_port *mate;
+
+ /* macio_dev for the escc holding this port (maybe be null on
+ * early inited port)
+ */
+ struct macio_dev *dev;
+ /* device node to this port, this points to one of 2 childs
+ * of "escc" node (ie. ch-a or ch-b)
+ */
+ struct device_node *node;
+
+ /* Port type as obtained from device tree (IRDA, modem, ...) */
+ int port_type;
+ u8 curregs[NUM_ZSREGS];
+
+ unsigned int flags;
+#define PMACZILOG_FLAG_IS_CONS 0x00000001
+#define PMACZILOG_FLAG_IS_KGDB 0x00000002
+#define PMACZILOG_FLAG_MODEM_STATUS 0x00000004
+#define PMACZILOG_FLAG_IS_CHANNEL_A 0x00000008
+#define PMACZILOG_FLAG_REGS_HELD 0x00000010
+#define PMACZILOG_FLAG_TX_STOPPED 0x00000020
+#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
+#define PMACZILOG_FLAG_ENABLED 0x00000080
+#define PMACZILOG_FLAG_IS_IRDA 0x00000100
+#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
+#define PMACZILOG_FLAG_HAS_DMA 0x00000400
+#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
+#define PMACZILOG_FLAG_IS_ASLEEP 0x00001000
+#define PMACZILOG_FLAG_IS_OPEN 0x00002000
+#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000
+#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
+#define PMACZILOG_FLAG_BREAK 0x00010000
+
+ unsigned char parity_mask;
+ unsigned char prev_status;
+
+ volatile u8 __iomem *control_reg;
+ volatile u8 __iomem *data_reg;
+
+ unsigned int tx_dma_irq;
+ unsigned int rx_dma_irq;
+ volatile struct dbdma_regs __iomem *tx_dma_regs;
+ volatile struct dbdma_regs __iomem *rx_dma_regs;
+
+ struct termios termios_cache;
+};
+
+#define to_pmz(p) ((struct uart_pmac_port *)(p))
+
+static inline struct uart_pmac_port *pmz_get_port_A(struct uart_pmac_port *uap)
+{
+ if (uap->flags & PMACZILOG_FLAG_IS_CHANNEL_A)
+ return uap;
+ return uap->mate;
+}
+
+/*
+ * Register acessors. Note that we don't need to enforce a recovery
+ * delay on PCI PowerMac hardware, it's dealt in HW by the MacIO chip,
+ * though if we try to use this driver on older machines, we might have
+ * to add it back
+ */
+static inline u8 read_zsreg(struct uart_pmac_port *port, u8 reg)
+{
+ if (reg != 0)
+ writeb(reg, port->control_reg);
+ return readb(port->control_reg);
+}
+
+static inline void write_zsreg(struct uart_pmac_port *port, u8 reg, u8 value)
+{
+ if (reg != 0)
+ writeb(reg, port->control_reg);
+ writeb(value, port->control_reg);
+}
+
+static inline u8 read_zsdata(struct uart_pmac_port *port)
+{
+ return readb(port->data_reg);
+}
+
+static inline void write_zsdata(struct uart_pmac_port *port, u8 data)
+{
+ writeb(data, port->data_reg);
+}
+
+static inline void zssync(struct uart_pmac_port *port)
+{
+ (void)readb(port->control_reg);
+}
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */
+
+/* The Zilog register set */
+
+#define FLAG 0x7e
+
+/* Write Register 0 */
+#define R0 0 /* Register selects */
+#define R1 1
+#define R2 2
+#define R3 3
+#define R4 4
+#define R5 5
+#define R6 6
+#define R7 7
+#define R8 8
+#define R9 9
+#define R10 10
+#define R11 11
+#define R12 12
+#define R13 13
+#define R14 14
+#define R15 15
+#define R7P 16
+
+#define NULLCODE 0 /* Null Code */
+#define POINT_HIGH 0x8 /* Select upper half of registers */
+#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
+#define SEND_ABORT 0x18 /* HDLC Abort */
+#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
+#define RES_Tx_P 0x28 /* Reset TxINT Pending */
+#define ERR_RES 0x30 /* Error Reset */
+#define RES_H_IUS 0x38 /* Reset highest IUS */
+
+#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
+#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
+#define RES_EOM_L 0xC0 /* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
+#define TxINT_ENAB 0x2 /* Tx Int Enable */
+#define PAR_SPEC 0x4 /* Parity is special condition */
+
+#define RxINT_DISAB 0 /* Rx Int Disable */
+#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or
Error */
+#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
+#define INT_ERR_Rx 0x18 /* Int on error only */
+#define RxINT_MASK 0x18
+
+#define WT_RDY_RT 0x20 /* W/Req reflects recv if 1, xmit if 0
*/
+#define WT_FN_RDYFN 0x40 /* W/Req pin is DMA request if 1, wait
if 0 */
+#define WT_RDY_ENAB 0x80 /* Enable W/Req pin */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define RxENABLE 0x1 /* Rx Enable */
+#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
+#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
+#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
+#define ENT_HM 0x10 /* Enter Hunt Mode */
+#define AUTO_ENAB 0x20 /* Auto Enables */
+#define Rx5 0x0 /* Rx 5 Bits/Character */
+#define Rx7 0x40 /* Rx 7 Bits/Character */
+#define Rx6 0x80 /* Rx 6 Bits/Character */
+#define Rx8 0xc0 /* Rx 8 Bits/Character */
+#define RxN_MASK 0xc0
+
+/* Write Register 4 */
+
+#define PAR_ENAB 0x1 /* Parity Enable */
+#define PAR_EVEN 0x2 /* Parity Even/Odd* */
+
+#define SYNC_ENAB 0 /* Sync Modes Enable */
+#define SB1 0x4 /* 1 stop bit/char */
+#define SB15 0x8 /* 1.5 stop bits/char */
+#define SB2 0xc /* 2 stop bits/char */
+#define SB_MASK 0xc
+
+#define MONSYNC 0 /* 8 Bit Sync character */
+#define BISYNC 0x10 /* 16 bit sync character */
+#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
+#define EXTSYNC 0x30 /* External Sync Mode */
+
+#define X1CLK 0x0 /* x1 clock mode */
+#define X16CLK 0x40 /* x16 clock mode */
+#define X32CLK 0x80 /* x32 clock mode */
+#define X64CLK 0xC0 /* x64 clock mode */
+#define XCLK_MASK 0xC0
+
+/* Write Register 5 */
+
+#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
+#define RTS 0x2 /* RTS */
+#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
+#define TxENABLE 0x8 /* Tx Enable */
+#define SND_BRK 0x10 /* Send Break */
+#define Tx5 0x0 /* Tx 5 bits (or less)/character */
+#define Tx7 0x20 /* Tx 7 bits/character */
+#define Tx6 0x40 /* Tx 6 bits/character */
+#define Tx8 0x60 /* Tx 8 bits/character */
+#define TxN_MASK 0x60
+#define DTR 0x80 /* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 7' (Some enhanced feature control) */
+#define ENEXREAD 0x40 /* Enable read of some write registers
*/
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define VIS 1 /* Vector Includes Status */
+#define NV 2 /* No Vector */
+#define DLC 4 /* Disable Lower Chain */
+#define MIE 8 /* Master Interrupt Enable */
+#define STATHI 0x10 /* Status high */
+#define NORESET 0 /* No reset on write to R9 */
+#define CHRB 0x40 /* Reset channel B */
+#define CHRA 0x80 /* Reset channel A */
+#define FHWRES 0xc0 /* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define BIT6 1 /* 6 bit/8bit sync */
+#define LOOPMODE 2 /* SDLC Loop mode */
+#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
+#define MARKIDLE 8 /* Mark/flag on idle */
+#define GAOP 0x10 /* Go active on poll */
+#define NRZ 0 /* NRZ mode */
+#define NRZI 0x20 /* NRZI mode */
+#define FM1 0x40 /* FM1 (transition = 1) */
+#define FM0 0x60 /* FM0 (transition = 0) */
+#define CRCPS 0x80 /* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define TRxCXT 0 /* TRxC = Xtal output */
+#define TRxCTC 1 /* TRxC = Transmit clock */
+#define TRxCBR 2 /* TRxC = BR Generator Output */
+#define TRxCDP 3 /* TRxC = DPLL output */
+#define TRxCOI 4 /* TRxC O/I */
+#define TCRTxCP 0 /* Transmit clock = RTxC pin */
+#define TCTRxCP 8 /* Transmit clock = TRxC pin */
+#define TCBR 0x10 /* Transmit clock = BR Generator output */
+#define TCDPLL 0x18 /* Transmit clock = DPLL output */
+#define RCRTxCP 0 /* Receive clock = RTxC pin */
+#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
+#define RCBR 0x40 /* Receive clock = BR Generator output */
+#define RCDPLL 0x60 /* Receive clock = DPLL output */
+#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define BRENAB 1 /* Baud rate generator enable */
+#define BRSRC 2 /* Baud rate generator source */
+#define DTRREQ 4 /* DTR/Request function */
+#define AUTOECHO 8 /* Auto Echo */
+#define LOOPBAK 0x10 /* Local loopback */
+#define SEARCH 0x20 /* Enter search mode */
+#define RMC 0x40 /* Reset missing clock */
+#define DISDPLL 0x60 /* Disable DPLL */
+#define SSBR 0x80 /* Set DPLL source = BR generator */
+#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
+#define SFMM 0xc0 /* Set FM mode */
+#define SNRZI 0xe0 /* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define EN85C30 1 /* Enable some 85c30-enhanced registers */
+#define ZCIE 2 /* Zero count IE */
+#define ENSTFIFO 4 /* Enable status FIFO (SDLC) */
+#define DCDIE 8 /* DCD IE */
+#define SYNCIE 0x10 /* Sync/hunt IE */
+#define CTSIE 0x20 /* CTS IE */
+#define TxUIE 0x40 /* Tx Underrun/EOM IE */
+#define BRKIE 0x80 /* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define Rx_CH_AV 0x1 /* Rx Character Available */
+#define ZCOUNT 0x2 /* Zero count */
+#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
+#define DCD 0x8 /* DCD */
+#define SYNC_HUNT 0x10 /* Sync/hunt */
+#define CTS 0x20 /* CTS */
+#define TxEOM 0x40 /* Tx underrun */
+#define BRK_ABRT 0x80 /* Break/Abort */
+
+/* Read Register 1 */
+#define ALL_SNT 0x1 /* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define RES3 0x8 /* 0/3 */
+#define RES4 0x4 /* 0/4 */
+#define RES5 0xc /* 0/5 */
+#define RES6 0x2 /* 0/6 */
+#define RES7 0xa /* 0/7 */
+#define RES8 0x6 /* 0/8 */
+#define RES18 0xe /* 1/8 */
+#define RES28 0x0 /* 2/8 */
+/* Special Rx Condition Interrupts */
+#define PAR_ERR 0x10 /* Parity error */
+#define Rx_OVR 0x20 /* Rx Overrun Error */
+#define CRC_ERR 0x40 /* CRC/Framing Error */
+#define END_FR 0x80 /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+#define CHB_Tx_EMPTY 0x00
+#define CHB_EXT_STAT 0x02
+#define CHB_Rx_AVAIL 0x04
+#define CHB_SPECIAL 0x06
+#define CHA_Tx_EMPTY 0x08
+#define CHA_EXT_STAT 0x0a
+#define CHA_Rx_AVAIL 0x0c
+#define CHA_SPECIAL 0x0e
+#define STATUS_MASK 0x06
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
+#define CHBTxIP 0x2 /* Channel B Tx IP */
+#define CHBRxIP 0x4 /* Channel B Rx IP */
+#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
+#define CHATxIP 0x10 /* Channel A Tx IP */
+#define CHARxIP 0x20 /* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10 (misc status bits) */
+#define ONLOOP 2 /* On loop */
+#define LOOPSEND 0x10 /* Loop sending */
+#define CLK2MIS 0x40 /* Two clocks missing */
+#define CLK1MIS 0x80 /* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
+
+/* Misc macros */
+#define ZS_CLEARERR(port) (write_zsreg(port, 0, ERR_RES))
+#define ZS_CLEARFIFO(port) do { volatile unsigned char garbage; \
+ garbage = read_zsdata(port); \
+ garbage = read_zsdata(port); \
+ garbage = read_zsdata(port); \
+ } while(0)
+
+#define ZS_IS_CONS(UP) ((UP)->flags & PMACZILOG_FLAG_IS_CONS)
+#define ZS_IS_KGDB(UP) ((UP)->flags & PMACZILOG_FLAG_IS_KGDB)
+#define ZS_IS_CHANNEL_A(UP) ((UP)->flags &
PMACZILOG_FLAG_IS_CHANNEL_A)
+#define ZS_REGS_HELD(UP) ((UP)->flags & PMACZILOG_FLAG_REGS_HELD)
+#define ZS_TX_STOPPED(UP) ((UP)->flags &
PMACZILOG_FLAG_TX_STOPPED)
+#define ZS_TX_ACTIVE(UP) ((UP)->flags & PMACZILOG_FLAG_TX_ACTIVE)
+#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags &
PMACZILOG_FLAG_MODEM_STATUS)
+#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
+#define ZS_IS_INTMODEM(UP) ((UP)->flags &
PMACZILOG_FLAG_IS_INTMODEM)
+#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
+#define ZS_IS_ASLEEP(UP) ((UP)->flags &
PMACZILOG_FLAG_IS_ASLEEP)
+#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
+#define ZS_IS_IRQ_ON(UP) ((UP)->flags &
PMACZILOG_FLAG_IS_IRQ_ON)
+#define ZS_IS_EXTCLK(UP) ((UP)->flags &
PMACZILOG_FLAG_IS_EXTCLK)
+
+/* Xen additions */
+#define REG_CONTROL R0
+#define REG_DATA 0x10
+/* end Xen additions */
+#endif /* __PMAC_ZILOG_H__ */
diff -r 2039069d08ca xen/drivers/char/pmac_zilog.o
Binary file xen/drivers/char/pmac_zilog.o has changed
diff -r 2039069d08ca xen/include/asm-ppc/uart.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/include/asm-ppc/uart.h Thu May 25 12:21:06 2006 -0400
@@ -0,0 +1,22 @@
+#ifndef _UART_H
+#define _UART_H
+#include <xen/serial.h>
+
+enum uart_type { ns16550 = 1, pmac_zilog = 2 };
+
+struct uart {
+ enum uart_type type;
+ char *uart_name;
+ char *p_sign; // parernt directory signature
+ char *gp_sign; // grandparent directory signature
+ void (* uart_init_func) (int i, struct ns16550_defaults * init_struct);
+};
+
+struct platform_serial_port {
+ unsigned long uart_io_base;
+ struct uart *uart_p;
+ u32 interrupts;
+ u32 clock;
+ u32 baud;
+};
+#endif /* #ifndef _UART_H */
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|