|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/drv/dev/serial/ns16550.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
1 /*- 2 * Copyright (c) 2009, Kohsuke Ohtani 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the author nor the names of any co-contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * ns16550.c - NS16550 serial driver 32 */ 33 34 #include <driver.h> 35 #include <tty.h> 36 #include <serial.h> 37 38 /* #define DEBUG_NS16550 1 */ 39 40 #ifdef DEBUG_NS16550 41 #define DPRINTF(a) printf a 42 #else 43 #define DPRINTF(a) 44 #endif 45 46 #define COM_BASE CONFIG_NS16550_BASE 47 #define COM_IRQ CONFIG_NS16550_IRQ 48 49 /* Register offsets */ 50 #define COM_RBR (COM_BASE + 0x00) /* receive buffer register */ 51 #define COM_THR (COM_BASE + 0x00) /* transmit holding register */ 52 #define COM_IER (COM_BASE + 0x01) /* interrupt enable register */ 53 #define COM_FCR (COM_BASE + 0x02) /* FIFO control register */ 54 #define COM_IIR (COM_BASE + 0x02) /* interrupt identification register */ 55 #define COM_LCR (COM_BASE + 0x03) /* line control register */ 56 #define COM_MCR (COM_BASE + 0x04) /* modem control register */ 57 #define COM_LSR (COM_BASE + 0x05) /* line status register */ 58 #define COM_MSR (COM_BASE + 0x06) /* modem status register */ 59 #define COM_DLL (COM_BASE + 0x00) /* divisor latch LSB (LCR[7] = 1) */ 60 #define COM_DLM (COM_BASE + 0x01) /* divisor latch MSB (LCR[7] = 1) */ 61 62 /* Interrupt enable register */ 63 #define IER_RDA 0x01 /* enable receive data available */ 64 #define IER_THRE 0x02 /* enable transmitter holding register empty */ 65 #define IER_RLS 0x04 /* enable recieve line status */ 66 #define IER_RMS 0x08 /* enable receive modem status */ 67 68 /* Interrupt identification register */ 69 #define IIR_MSR 0x00 /* modem status change */ 70 #define IIR_IP 0x01 /* 0 when interrupt pending */ 71 #define IIR_TXB 0x02 /* transmitter holding register empty */ 72 #define IIR_RXB 0x04 /* received data available */ 73 #define IIR_LSR 0x06 /* line status change */ 74 #define IIR_MASK 0x07 /* mask off just the meaningful bits */ 75 76 /* line status register */ 77 #define LSR_RCV_FIFO 0x80 78 #define LSR_TSRE 0x40 /* Transmitter empty: byte sent */ 79 #define LSR_TXRDY 0x20 /* Transmitter buffer empty */ 80 #define LSR_BI 0x10 /* Break detected */ 81 #define LSR_FE 0x08 /* Framing error: bad stop bit */ 82 #define LSR_PE 0x04 /* Parity error */ 83 #define LSR_OE 0x02 /* Overrun, lost incoming byte */ 84 #define LSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ 85 #define LSR_RCV_MASK 0x1f /* Mask for incoming data or error */ 86 87 /* Forward functions */ 88 static int ns16550_probe(struct driver *); 89 static int ns16550_init(struct driver *); 90 91 static void ns16550_xmt_char(struct serial_port *, char); 92 static char ns16550_rcv_char(struct serial_port *); 93 static void ns16550_set_poll(struct serial_port *, int); 94 static void ns16550_start(struct serial_port *); 95 static void ns16550_stop(struct serial_port *); 96 97 98 struct driver ns16550_driver = { 99 /* name */ "ns16550", 100 /* devops */ NULL, 101 /* devsz */ 0, 102 /* flags */ 0, 103 /* probe */ ns16550_probe, 104 /* init */ ns16550_init, 105 /* unload */ NULL, 106 }; 107 108 static struct serial_ops ns16550_ops = { 109 /* xmt_char */ ns16550_xmt_char, 110 /* rcv_char */ ns16550_rcv_char, 111 /* set_poll */ ns16550_set_poll, 112 /* start */ ns16550_start, 113 /* stop */ ns16550_stop, 114 }; 115 116 117 static struct serial_port ns16550_port; 118 119 120 static void 121 ns16550_xmt_char(struct serial_port *sp, char c) 122 { 123 124 while (!(bus_read_8(COM_LSR) & LSR_TXRDY)) 125 ; 126 bus_write_8(COM_THR, c); 127 } 128 129 static char 130 ns16550_rcv_char(struct serial_port *sp) 131 { 132 133 while (!(bus_read_8(COM_LSR) & LSR_RXRDY)) 134 ; 135 return bus_read_8(COM_RBR); 136 } 137 138 static void 139 ns16550_set_poll(struct serial_port *sp, int on) 140 { 141 142 if (on) { 143 /* Disable interrupt for polling mode. */ 144 bus_write_8(COM_IER, 0x00); 145 } else { 146 /* enable interrupt again */ 147 bus_write_8(COM_IER, IER_RDA|IER_THRE|IER_RLS); 148 } 149 } 150 151 static int 152 ns16550_isr(void *arg) 153 { 154 struct serial_port *sp = arg; 155 156 switch (bus_read_8(COM_IIR) & IIR_MASK) { 157 case IIR_MSR: /* Modem status change */ 158 break; 159 case IIR_LSR: /* Line status change */ 160 bus_read_8(COM_LSR); 161 break; 162 case IIR_TXB: /* Transmitter holding register empty */ 163 serial_xmt_done(sp); 164 break; 165 case IIR_RXB: /* Received data available */ 166 bus_read_8(COM_LSR); 167 serial_rcv_char(sp, bus_read_8(COM_RBR)); 168 break; 169 } 170 return 0; 171 } 172 173 static void 174 ns16550_start(struct serial_port *sp) 175 { 176 int s; 177 178 bus_write_8(COM_IER, 0x00); /* Disable interrupt */ 179 bus_write_8(COM_LCR, 0x80); /* Access baud rate */ 180 bus_write_8(COM_DLL, 0x01); /* 115200 baud */ 181 bus_write_8(COM_DLM, 0x00); 182 bus_write_8(COM_LCR, 0x03); /* N, 8, 1 */ 183 bus_write_8(COM_FCR, 0x06); /* Disable & clear FIFO */ 184 185 sp->irq = irq_attach(COM_IRQ, IPL_COMM, 0, ns16550_isr, 186 IST_NONE, sp); 187 188 s = splhigh(); 189 bus_write_8(COM_MCR, 0x0b); /* Enable OUT2 interrupt */ 190 bus_write_8(COM_IER, IER_RDA|IER_THRE|IER_RLS); /* Enable interrupt */ 191 bus_read_8(COM_IIR); 192 splx(s); 193 } 194 195 static void 196 ns16550_stop(struct serial_port *sp) 197 { 198 199 /* Disable all interrupts */ 200 bus_write_8(COM_IER, 0x00); 201 } 202 203 204 static int 205 ns16550_probe(struct driver *self) 206 { 207 208 if (bus_read_8(COM_LSR) == 0xff) 209 return ENXIO; /* Port is disabled */ 210 return 0; 211 } 212 213 static int 214 ns16550_init(struct driver *self) 215 { 216 217 serial_attach(&ns16550_ops, &ns16550_port); 218 return 0; 219 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |