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

[XenPPC] [pushed] [ppc] serial port discovery and zilog device driver



changeset:   10387:a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55
user:        jimix@xxxxxxxxxxxxxxxxxxxxx
date:        Thu May 25 15:20:20 2006 -0400
files:       xen/arch/ppc/boot_of.c xen/arch/ppc/setup.c 
xen/drivers/char/Makefile xen/drivers/char/ns16550.c 
xen/drivers/char/pmac_zilog.c xen/drivers/char/pmac_zilog.h 
xen/include/asm-ppc/uart.h xen/include/xen/serial.h
description:
[ppc] serial port discovery and zilog device driver

Signed-off-by: Maria Butrico <butrico@xxxxxxxxxxxxxx>


diff -r 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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", &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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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 2039069d08cabf46f89d4fafd594e8af32cac5e7 -r 
a1a0ff01e7c7e51ee2a1b418e463edbff19d7c55 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 15:20:20 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.