sbcv2: More UART features
authorAlan Cox <alan@linux.intel.com>
Sat, 25 Aug 2018 18:14:28 +0000 (19:14 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 25 Aug 2018 18:14:28 +0000 (19:14 +0100)
In particular set up the port properly rather than relying on ROMWBW. Also
turn on the interrupts.

Kernel/platform-sbcv2/devtty.c

index 6ea0ef9..6ef03a7 100644 (file)
@@ -1,5 +1,10 @@
 /*
  *     We have a 16x50 UART at 0x68 and maybe a PropIO2 at A8
+ *
+ *     TODO:
+ *     - Hardware flow control
+ *     - Support for abuse of 16x50 as interrupt controller
+ *     - Support for timer hack
  */
 
 #include <kernel.h>
 
 __sfr __at 0x68 uart_tx;
 __sfr __at 0x68 uart_rx;
+__sfr __at 0x68 uart_ls;
+__sfr __at 0x69 uart_ier;
+__sfr __at 0x69 uart_ms;
+__sfr __at 0x6A uart_fcr;
+__sfr __at 0x6B uart_lcr;
+__sfr __at 0x6C uart_mcr;
 __sfr __at 0x6D uart_lsr;
+__sfr __at 0x6E uart_msr;
+__sfr __at 0x6F uart_scr;
 
 static char tbuf1[TTYSIZ];
 static char tbuf2[TTYSIZ];
@@ -30,7 +43,6 @@ struct s_queue ttyinq[NUM_DEV_TTY + 1] = {    /* ttyinq[0] is never used */
 /* Write to system console */
 void kputchar(char c)
 {
-       /* Need to make console dynamic FIXME */
        if (c == '\n')
                tty_putc(1, '\r');
        tty_putc(1, c);
@@ -54,9 +66,50 @@ void tty_putc(uint8_t minor, unsigned char c)
                prop_tty_write(c);
 }
 
+static uint16_t clocks[] = {
+       12,             /* Not a real rate */
+       2304,
+       1536,
+       1047,
+       857,
+       768,
+       384,
+       192,
+       96,
+       48,
+       24,
+       12,
+       6,
+       3,
+       2,
+       1
+};
+
 void tty_setup(uint8_t minor)
 {
-       minor;
+       uint8_t d;
+       uint16_t w;
+       struct termios *t = &ttydata[minor].termios;
+       if (ttymap[minor] == 1) {
+               /* 16x50. Can actually be configured */
+               d = 0x80;       /* DLAB */
+               d |= (t->c_cflag & CSIZE) >> 4;
+               if(t->c_cflag & CSTOPB)
+                       d |= 0x04;
+               if (t->c_cflag & PARENB)
+                       d |= 0x08;
+               if (!(t->c_cflag & PARODD))
+                       d |= 0x10;
+               uart_lcr = d;
+               w = clocks[t->c_cflag & CBAUD];
+               uart_ls = w;
+               uart_ms = w >> 8;
+               uart_lcr = d & 0x7F;
+               /* FIXME: CTS/RTS support */
+               d = 0x00;       /* !DTR !RTS */
+               uart_lcr = d;
+               uart_ier = 0x0D;        /* We don't use tx ints */
+       }
 }
 
 void tty_sleeping(uint8_t minor)
@@ -66,7 +119,8 @@ void tty_sleeping(uint8_t minor)
 
 int tty_carrier(uint8_t minor)
 {
-        minor;
+        if (ttymap[minor] == 1)
+               return uart_msr & 0x80;
        return 1;
 }
 
@@ -76,7 +130,8 @@ void tty_data_consumed(uint8_t minor)
 
 void tty_poll(void)
 {      
-       /* Should be IRQ driven for this */
+       /* Should be IRQ driven but we might not be so poll anyway if
+          pending. IRQs are off here so this is safe */
        if (uart_lsr & 0x01)
                tty_inproc(ttymap[1], uart_rx);
        prop_tty_poll(ttymap[2]);