[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", ®, 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |