1/* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model. 2 For "old style" UARTs on BF53x/etc... parts. 3 4 Copyright (C) 2010-2011 Free Software Foundation, Inc. 5 Contributed by Analog Devices, Inc. 6 7 This file is part of simulators. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22#include "config.h" 23 24#include "sim-main.h" 25#include "dv-sockser.h" 26#include "devices.h" 27#include "dv-bfin_uart.h" 28 29/* XXX: Should we bother emulating the TX/RX FIFOs ? */ 30 31/* Internal state needs to be the same as bfin_uart2. */ 32struct bfin_uart 33{ 34 /* This top portion matches common dv_bfin struct. */ 35 bu32 base; 36 struct hw *dma_master; 37 bool acked; 38 39 struct hw_event *handler; 40 char saved_byte; 41 int saved_count; 42 43 /* This is aliased to DLH. */ 44 bu16 ier; 45 /* These are aliased to DLL. */ 46 bu16 thr, rbr; 47 48 /* Order after here is important -- matches hardware MMR layout. */ 49 bu16 BFIN_MMR_16(dll); 50 bu16 BFIN_MMR_16(dlh); 51 bu16 BFIN_MMR_16(iir); 52 bu16 BFIN_MMR_16(lcr); 53 bu16 BFIN_MMR_16(mcr); 54 bu16 BFIN_MMR_16(lsr); 55 bu16 BFIN_MMR_16(msr); 56 bu16 BFIN_MMR_16(scr); 57 bu16 _pad0[2]; 58 bu16 BFIN_MMR_16(gctl); 59}; 60#define mmr_base() offsetof(struct bfin_uart, dll) 61#define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base()) 62 63static const char * const mmr_names[] = 64{ 65 "UART_RBR/UART_THR", "UART_IER", "UART_IIR", "UART_LCR", "UART_MCR", 66 "UART_LSR", "UART_MSR", "UART_SCR", "<INV>", "UART_GCTL", 67}; 68static const char *mmr_name (struct bfin_uart *uart, bu32 idx) 69{ 70 if (uart->lcr & DLAB) 71 if (idx < 2) 72 return idx == 0 ? "UART_DLL" : "UART_DLH"; 73 return mmr_names[idx]; 74} 75#define mmr_name(off) mmr_name (uart, (off) / 4) 76 77#ifndef HAVE_DV_SOCKSER 78# define dv_sockser_status(sd) -1 79# define dv_sockser_write(sd, byte) do { ; } while (0) 80# define dv_sockser_read(sd) 0xff 81#endif 82 83static void 84bfin_uart_poll (struct hw *me, void *data) 85{ 86 struct bfin_uart *uart = data; 87 bu16 lsr; 88 89 uart->handler = NULL; 90 91 lsr = bfin_uart_get_status (me); 92 if (lsr & DR) 93 hw_port_event (me, DV_PORT_RX, 1); 94 95 bfin_uart_reschedule (me); 96} 97 98void 99bfin_uart_reschedule (struct hw *me) 100{ 101 struct bfin_uart *uart = hw_data (me); 102 103 if (uart->ier & ERBFI) 104 { 105 if (!uart->handler) 106 uart->handler = hw_event_queue_schedule (me, 10000, 107 bfin_uart_poll, uart); 108 } 109 else 110 { 111 if (uart->handler) 112 { 113 hw_event_queue_deschedule (me, uart->handler); 114 uart->handler = NULL; 115 } 116 } 117} 118 119bu16 120bfin_uart_write_byte (struct hw *me, bu16 thr) 121{ 122 unsigned char ch = thr; 123 bfin_uart_write_buffer (me, &ch, 1); 124 return thr; 125} 126 127static unsigned 128bfin_uart_io_write_buffer (struct hw *me, const void *source, 129 int space, address_word addr, unsigned nr_bytes) 130{ 131 struct bfin_uart *uart = hw_data (me); 132 bu32 mmr_off; 133 bu32 value; 134 bu16 *valuep; 135 136 value = dv_load_2 (source); 137 mmr_off = addr - uart->base; 138 valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off); 139 140 HW_TRACE_WRITE (); 141 142 dv_bfin_mmr_require_16 (me, addr, nr_bytes, true); 143 144 /* XXX: All MMRs are "8bit" ... what happens to high 8bits ? */ 145 switch (mmr_off) 146 { 147 case mmr_offset(dll): 148 if (uart->lcr & DLAB) 149 uart->dll = value; 150 else 151 { 152 uart->thr = bfin_uart_write_byte (me, value); 153 154 if (uart->ier & ETBEI) 155 hw_port_event (me, DV_PORT_TX, 1); 156 } 157 break; 158 case mmr_offset(dlh): 159 if (uart->lcr & DLAB) 160 uart->dlh = value; 161 else 162 { 163 uart->ier = value; 164 bfin_uart_reschedule (me); 165 } 166 break; 167 case mmr_offset(iir): 168 case mmr_offset(lsr): 169 /* XXX: Writes are ignored ? */ 170 break; 171 case mmr_offset(lcr): 172 case mmr_offset(mcr): 173 case mmr_offset(scr): 174 case mmr_offset(gctl): 175 *valuep = value; 176 break; 177 default: 178 dv_bfin_mmr_invalid (me, addr, nr_bytes, true); 179 break; 180 } 181 182 return nr_bytes; 183} 184 185/* Switch between socket and stdin on the fly. */ 186bu16 187bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh) 188{ 189 SIM_DESC sd = hw_system (me); 190 struct bfin_uart *uart = hw_data (me); 191 int status = dv_sockser_status (sd); 192 bool _fresh; 193 194 /* NB: The "uart" here may only use interal state. */ 195 196 if (!fresh) 197 fresh = &_fresh; 198 199 *fresh = false; 200 if (status & DV_SOCKSER_DISCONNECTED) 201 { 202 if (uart->saved_count > 0) 203 { 204 *fresh = true; 205 rbr = uart->saved_byte; 206 --uart->saved_count; 207 } 208 else 209 { 210 char byte; 211 int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1); 212 if (ret > 0) 213 { 214 *fresh = true; 215 rbr = byte; 216 } 217 } 218 } 219 else 220 rbr = dv_sockser_read (sd); 221 222 return rbr; 223} 224 225bu16 226bfin_uart_get_status (struct hw *me) 227{ 228 SIM_DESC sd = hw_system (me); 229 struct bfin_uart *uart = hw_data (me); 230 int status = dv_sockser_status (sd); 231 bu16 lsr = 0; 232 233 if (status & DV_SOCKSER_DISCONNECTED) 234 { 235 if (uart->saved_count <= 0) 236 uart->saved_count = sim_io_poll_read (sd, 0/*STDIN*/, 237 &uart->saved_byte, 1); 238 lsr |= TEMT | THRE | (uart->saved_count > 0 ? DR : 0); 239 } 240 else 241 lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) | 242 (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0); 243 244 return lsr; 245} 246 247static unsigned 248bfin_uart_io_read_buffer (struct hw *me, void *dest, 249 int space, address_word addr, unsigned nr_bytes) 250{ 251 struct bfin_uart *uart = hw_data (me); 252 bu32 mmr_off; 253 bu16 *valuep; 254 255 mmr_off = addr - uart->base; 256 valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off); 257 258 HW_TRACE_READ (); 259 260 dv_bfin_mmr_require_16 (me, addr, nr_bytes, false); 261 262 switch (mmr_off) 263 { 264 case mmr_offset(dll): 265 if (uart->lcr & DLAB) 266 dv_store_2 (dest, uart->dll); 267 else 268 { 269 uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL); 270 dv_store_2 (dest, uart->rbr); 271 } 272 break; 273 case mmr_offset(dlh): 274 if (uart->lcr & DLAB) 275 dv_store_2 (dest, uart->dlh); 276 else 277 dv_store_2 (dest, uart->ier); 278 break; 279 case mmr_offset(lsr): 280 /* XXX: Reads are destructive on most parts, but not all ... */ 281 uart->lsr |= bfin_uart_get_status (me); 282 dv_store_2 (dest, *valuep); 283 uart->lsr = 0; 284 break; 285 case mmr_offset(iir): 286 /* XXX: Reads are destructive ... */ 287 case mmr_offset(lcr): 288 case mmr_offset(mcr): 289 case mmr_offset(scr): 290 case mmr_offset(gctl): 291 dv_store_2 (dest, *valuep); 292 break; 293 default: 294 dv_bfin_mmr_invalid (me, addr, nr_bytes, false); 295 break; 296 } 297 298 return nr_bytes; 299} 300 301unsigned 302bfin_uart_read_buffer (struct hw *me, unsigned char *buffer, unsigned nr_bytes) 303{ 304 SIM_DESC sd = hw_system (me); 305 struct bfin_uart *uart = hw_data (me); 306 int status = dv_sockser_status (sd); 307 unsigned i = 0; 308 309 if (status & DV_SOCKSER_DISCONNECTED) 310 { 311 int ret; 312 313 while (uart->saved_count > 0 && i < nr_bytes) 314 { 315 buffer[i++] = uart->saved_byte; 316 --uart->saved_count; 317 } 318 319 ret = sim_io_poll_read (sd, 0/*STDIN*/, (char *) buffer, nr_bytes - i); 320 if (ret > 0) 321 i += ret; 322 } 323 else 324 buffer[i++] = dv_sockser_read (sd); 325 326 return i; 327} 328 329static unsigned 330bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space, 331 unsigned_word addr, unsigned nr_bytes) 332{ 333 HW_TRACE_DMA_READ (); 334 return bfin_uart_read_buffer (me, dest, nr_bytes); 335} 336 337unsigned 338bfin_uart_write_buffer (struct hw *me, const unsigned char *buffer, 339 unsigned nr_bytes) 340{ 341 SIM_DESC sd = hw_system (me); 342 int status = dv_sockser_status (sd); 343 344 if (status & DV_SOCKSER_DISCONNECTED) 345 { 346 sim_io_write_stdout (sd, (const char *) buffer, nr_bytes); 347 sim_io_flush_stdout (sd); 348 } 349 else 350 { 351 /* Normalize errors to a value of 0. */ 352 int ret = dv_sockser_write_buffer (sd, buffer, nr_bytes); 353 nr_bytes = CLAMP (ret, 0, nr_bytes); 354 } 355 356 return nr_bytes; 357} 358 359static unsigned 360bfin_uart_dma_write_buffer (struct hw *me, const void *source, 361 int space, unsigned_word addr, 362 unsigned nr_bytes, 363 int violate_read_only_section) 364{ 365 struct bfin_uart *uart = hw_data (me); 366 unsigned ret; 367 368 HW_TRACE_DMA_WRITE (); 369 370 ret = bfin_uart_write_buffer (me, source, nr_bytes); 371 372 if (ret == nr_bytes && (uart->ier & ETBEI)) 373 hw_port_event (me, DV_PORT_TX, 1); 374 375 return ret; 376} 377 378static const struct hw_port_descriptor bfin_uart_ports[] = 379{ 380 { "tx", DV_PORT_TX, 0, output_port, }, 381 { "rx", DV_PORT_RX, 0, output_port, }, 382 { "stat", DV_PORT_STAT, 0, output_port, }, 383 { NULL, 0, 0, 0, }, 384}; 385 386static void 387attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart) 388{ 389 address_word attach_address; 390 int attach_space; 391 unsigned attach_size; 392 reg_property_spec reg; 393 394 if (hw_find_property (me, "reg") == NULL) 395 hw_abort (me, "Missing \"reg\" property"); 396 397 if (!hw_find_reg_array_property (me, "reg", 0, ®)) 398 hw_abort (me, "\"reg\" property must contain three addr/size entries"); 399 400 hw_unit_address_to_attach_address (hw_parent (me), 401 ®.address, 402 &attach_space, &attach_address, me); 403 hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); 404 405 if (attach_size != BFIN_MMR_UART_SIZE) 406 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART_SIZE); 407 408 hw_attach_address (hw_parent (me), 409 0, attach_space, attach_address, attach_size, me); 410 411 uart->base = attach_address; 412} 413 414static void 415bfin_uart_finish (struct hw *me) 416{ 417 struct bfin_uart *uart; 418 419 uart = HW_ZALLOC (me, struct bfin_uart); 420 421 set_hw_data (me, uart); 422 set_hw_io_read_buffer (me, bfin_uart_io_read_buffer); 423 set_hw_io_write_buffer (me, bfin_uart_io_write_buffer); 424 set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer); 425 set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer); 426 set_hw_ports (me, bfin_uart_ports); 427 428 attach_bfin_uart_regs (me, uart); 429 430 /* Initialize the UART. */ 431 uart->dll = 0x0001; 432 uart->iir = 0x0001; 433 uart->lsr = 0x0060; 434} 435 436const struct hw_descriptor dv_bfin_uart_descriptor[] = 437{ 438 {"bfin_uart", bfin_uart_finish,}, 439 {NULL, NULL}, 440}; 441