From 0a63518e55a1a9b8d6e7aec6fd0f973c3b8c84ef Mon Sep 17 00:00:00 2001 From: Sergey Kiselev Date: Fri, 13 Mar 2015 23:18:49 -0700 Subject: [PATCH] zeta-v2: implement UART auto detection; enable FIFO on UARTs that support it; move device initialization code to _DISCARD --- Kernel/platform-zeta-v2/Makefile | 2 +- Kernel/platform-zeta-v2/devices.c | 17 ++-- Kernel/platform-zeta-v2/devtty.c | 2 + Kernel/platform-zeta-v2/devtty.h | 9 ++ Kernel/platform-zeta-v2/devtty_discard.c | 113 +++++++++++++++++++++++ Kernel/platform-zeta-v2/discard.c | 29 +++--- Kernel/platform-zeta-v2/fuzix.lnk | 1 + Kernel/platform-zeta-v2/zeta-v2.s | 4 +- 8 files changed, 152 insertions(+), 25 deletions(-) create mode 100644 Kernel/platform-zeta-v2/devtty_discard.c diff --git a/Kernel/platform-zeta-v2/Makefile b/Kernel/platform-zeta-v2/Makefile index 7fcdb22e..718b662f 100644 --- a/Kernel/platform-zeta-v2/Makefile +++ b/Kernel/platform-zeta-v2/Makefile @@ -1,7 +1,7 @@ ASRCS = crt0.s tricks.s commonmem.s zeta-v2.s monitor.s ASRCS += ds1302-n8vem.s devrd_hw.s CSRCS = devices.c main.c devtty.c devrd.c -DISCARD_CSRCS = discard.c +DISCARD_CSRCS = discard.c devtty_discard.c DISCARD_DSRCS = ../dev/ds1302_discard.c DSRCS = ../dev/devfd.c ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c DSRCS += ../dev/ds1302.c diff --git a/Kernel/platform-zeta-v2/devices.c b/Kernel/platform-zeta-v2/devices.c index df6865dc..1e4af908 100644 --- a/Kernel/platform-zeta-v2/devices.c +++ b/Kernel/platform-zeta-v2/devices.c @@ -26,15 +26,10 @@ struct devsw dev_tab[] = /* The device driver switch table */ bool validdev(uint16_t dev) { - /* This is a bit uglier than needed but the right hand side is - a constant this way */ - if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) + 255) - return false; - else - return true; -} - -void device_init(void) -{ - ds1302_init(); + /* This is a bit uglier than needed but the right hand side is + a constant this way */ + if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) + 255) + return false; + else + return true; } diff --git a/Kernel/platform-zeta-v2/devtty.c b/Kernel/platform-zeta-v2/devtty.c index 25232940..c652f065 100644 --- a/Kernel/platform-zeta-v2/devtty.c +++ b/Kernel/platform-zeta-v2/devtty.c @@ -12,6 +12,8 @@ char tbuf1[TTYSIZ]; char tbufp[TTYSIZ]; #endif +unsigned char uart0_type; + struct s_queue ttyinq[NUM_DEV_TTY+1] = { /* ttyinq[0] is never used */ {NULL, NULL, NULL, 0, 0, 0}, {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2}, diff --git a/Kernel/platform-zeta-v2/devtty.h b/Kernel/platform-zeta-v2/devtty.h index 709b94e4..db70d87a 100644 --- a/Kernel/platform-zeta-v2/devtty.h +++ b/Kernel/platform-zeta-v2/devtty.h @@ -1,9 +1,18 @@ #ifndef __DEVTTY_DOT_H__ #define __DEVTTY_DOT_H__ +#define UART_NAME 0x0F +#define UART_CAP_FIFO 0x80 /* UART has functioning FIFO */ +#define UART_CAP_AFE 0x40 /* UART support autoflow control */ +#define UART_8250 1 +#define UART_16450 2 +#define UART_16550 3 +#define UART_16550A 4 + #define UART_CLOCK 1843200UL void tty_putc(uint8_t minor, unsigned char c); void tty_pollirq_uart0(void); +void uart0_init(void); #ifdef CONFIG_PPP void tty_poll_ppp(void); diff --git a/Kernel/platform-zeta-v2/devtty_discard.c b/Kernel/platform-zeta-v2/devtty_discard.c new file mode 100644 index 00000000..6fea1563 --- /dev/null +++ b/Kernel/platform-zeta-v2/devtty_discard.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include + +extern unsigned char uart0_type; + +unsigned char uart0_detect(); + +/* uart0_init - detect UART type, enable FIFO if present + */ +void uart0_init() { + const char *uart_name; + uart0_type = uart0_detect(); + switch (uart0_type & UART_NAME) { + case UART_8250: + uart_name = "8250"; + break; + case UART_16450: + uart_name = "8250A or 16450"; + break; + case UART_16550: + uart_name = "16550"; + break; + case UART_16550A: + uart_name = "16550A"; + break; + default: + uart_name = "Unknown"; + } + kprintf("UART0 type: %s", uart_name); + if (uart0_type & UART_CAP_FIFO) { + kprintf(" (with FIFO"); + if (uart0_type & UART_CAP_AFE) + kprintf(" and auto-flow control"); + /* the last dot is lost when FIFO is cleaned */ + kprintf("). Enabling FIFO..."); + /* enable FIFOs + set interrupt theshold to 8 bytes + */ + UART0_FCR = 0x83; + } + kprintf(".\n"); +} + +unsigned char uart0_detect() { + unsigned char type, scratch; + + type = UART_8250; /* default */ + + /* 8250 doesn't have scratch register, 8250A and later UARTs do. + Try writting a value to that register, read it back and compare + */ + UART0_SCR = 0x5A; + if (UART0_SCR != 0x5A) + goto out; /* no scratch register - 8250 */ + + UART0_SCR = 0xA5; + if (UART0_SCR != 0xA5) + goto out; /* no scratch register - 8250 */ + + /* Test for FIFO. Enable FIFO, and test bits 6 & 7 of IIR. + UARTs with functioning FIFO will have bits 6 and 7 set to 1 + when FIFO is enabled. Original 16550 with broken FIFO will have + only bit 7 set. + */ + + UART0_FCR = 0x01; /* try to enable FIFO */ + scratch = UART0_IIR; /* read IIR */ + UART0_FCR = 0x00; /* disable FIFO */ + scratch &= 0xC0; /* get FIFO status bits */ + + if (!scratch) { + type = UART_16450; + goto out; /* bits 6 and 7 are not set - 16450 */ + } + + if (scratch == 0x80) { + type = UART_16550; /* only bit 7 is set - bad 16550 */ + goto out; + } + + /* Must be 16550A or later. Normally comes with FIFO */ + type = UART_16550A | UART_CAP_FIFO; + + /* TODO: Test for UARTs with EFR */ + + /* Test for auto-flow control. This feature is present in some + 16550 versions (TI TL16C550C, NXP SC16C550B) */ + __critical { + UART0_IER = 0x00; /* disable interrupts */ + UART0_MCR = 0x30; /* enable auto-flow and loopback */ + UART0_IER = 0x08; /* enable modem status interrupt */ + scratch = UART0_MSR; /* read MSR to reset IIR */ + UART0_MCR = 0x32; /* set RTS = 1 */ + scratch = UART0_IIR; /* read IIR */ + UART0_MCR = 0x00; /* reset MCR bits */ + scratch &= 0x0F; /* get the interrupt type bits */ + + if (scratch == 0x01) { + /* No interrupt detected, RTS change has been eaten by + auto-flow control */ + type |= UART_CAP_AFE; + } + scratch = UART0_MSR; /* reset IIR again */ + UART0_IER = 0x01; /* enable receive interrupt */ + } +out: + return type; +} diff --git a/Kernel/platform-zeta-v2/discard.c b/Kernel/platform-zeta-v2/discard.c index fca69f88..1a14456b 100644 --- a/Kernel/platform-zeta-v2/discard.c +++ b/Kernel/platform-zeta-v2/discard.c @@ -2,25 +2,32 @@ #include #include #include +#include #include "config.h" void pagemap_init(void) { - int i; + int i; - /* ZETA SBC V2 has RAM in the top 512 KiB of physical memory - * corresponding pages are 32-63 (page size is 16 KiB) - * Pages 32-34 are used by the kernel - * Page 35 is the common area - * Pages starting from DEV_RD_START are used by RAM disk - */ - for (i = 32 + 4; i < DEV_RD_START; i++) - pagemap_add(i); + /* ZETA SBC V2 has RAM in the top 512 KiB of physical memory + * corresponding pages are 32-63 (page size is 16 KiB) + * Pages 32-34 are used by the kernel + * Page 35 is the common area + * Pages starting from DEV_RD_START are used by RAM disk + */ + for (i = 32 + 4; i < DEV_RD_START; i++) + pagemap_add(i); - /* finally add the common area */ - pagemap_add(32 + 3); + /* finally add the common area */ + pagemap_add(32 + 3); } void map_init(void) { } + +void device_init(void) +{ + ds1302_init(); + uart0_init(); +} diff --git a/Kernel/platform-zeta-v2/fuzix.lnk b/Kernel/platform-zeta-v2/fuzix.lnk index da7e6a96..9c1573df 100644 --- a/Kernel/platform-zeta-v2/fuzix.lnk +++ b/Kernel/platform-zeta-v2/fuzix.lnk @@ -37,6 +37,7 @@ usermem.rel usermem_std-z80.rel platform-zeta-v2/discard.rel platform-zeta-v2/devtty.rel +platform-zeta-v2/devtty_discard.rel platform-zeta-v2/mbr.rel platform-zeta-v2/blkdev.rel platform-zeta-v2/ds1302.rel diff --git a/Kernel/platform-zeta-v2/zeta-v2.s b/Kernel/platform-zeta-v2/zeta-v2.s index 0b6113b7..bed7dfe4 100644 --- a/Kernel/platform-zeta-v2/zeta-v2.s +++ b/Kernel/platform-zeta-v2/zeta-v2.s @@ -66,8 +66,8 @@ init_hardware: ld a,#0x03 ; value for LCR and MCR out (UART0_LCR),a ; 8 bit data, 1 stop, no parity out (UART0_MCR),a ; DTR ON, RTS ON - ld a,#0x07 ; enable and clear FIFOs - out (UART0_FCR),a ; interrupt theshold 1 byte + ld a,#0x06 ; disable and clear FIFOs + out (UART0_FCR),a ld a,#0x01 ; enable receive data available out (UART0_IER),a ; interrupt ; initialize CTC -- 2.34.1