1 /* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model. 2 For "new style" UARTs on BF50x/BF54x parts. 3 4 Copyright (C) 2010-2017 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 "devices.h" 26 #include "dv-bfin_uart2.h" 27 28 /* XXX: Should we bother emulating the TX/RX FIFOs ? */ 29 30 /* Internal state needs to be the same as bfin_uart. */ 31 struct bfin_uart 32 { 33 /* This top portion matches common dv_bfin struct. */ 34 bu32 base; 35 struct hw *dma_master; 36 bool acked; 37 38 struct hw_event *handler; 39 char saved_byte; 40 int saved_count; 41 42 /* Accessed indirectly by ier_{set,clear}. */ 43 bu16 ier; 44 45 /* Order after here is important -- matches hardware MMR layout. */ 46 bu16 BFIN_MMR_16(dll); 47 bu16 BFIN_MMR_16(dlh); 48 bu16 BFIN_MMR_16(gctl); 49 bu16 BFIN_MMR_16(lcr); 50 bu16 BFIN_MMR_16(mcr); 51 bu16 BFIN_MMR_16(lsr); 52 bu16 BFIN_MMR_16(msr); 53 bu16 BFIN_MMR_16(scr); 54 bu16 BFIN_MMR_16(ier_set); 55 bu16 BFIN_MMR_16(ier_clear); 56 bu16 BFIN_MMR_16(thr); 57 bu16 BFIN_MMR_16(rbr); 58 }; 59 #define mmr_base() offsetof(struct bfin_uart, dll) 60 #define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base()) 61 62 static const char * const mmr_names[] = 63 { 64 "UART_DLL", "UART_DLH", "UART_GCTL", "UART_LCR", "UART_MCR", "UART_LSR", 65 "UART_MSR", "UART_SCR", "UART_IER_SET", "UART_IER_CLEAR", "UART_THR", 66 "UART_RBR", 67 }; 68 #define mmr_name(off) mmr_names[(off) / 4] 69 70 static unsigned 71 bfin_uart_io_write_buffer (struct hw *me, const void *source, 72 int space, address_word addr, unsigned nr_bytes) 73 { 74 struct bfin_uart *uart = hw_data (me); 75 bu32 mmr_off; 76 bu32 value; 77 bu16 *valuep; 78 79 /* Invalid access mode is higher priority than missing register. */ 80 if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true)) 81 return 0; 82 83 value = dv_load_2 (source); 84 mmr_off = addr - uart->base; 85 valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off); 86 87 HW_TRACE_WRITE (); 88 89 /* XXX: All MMRs are "8bit" ... what happens to high 8bits ? */ 90 91 switch (mmr_off) 92 { 93 case mmr_offset(thr): 94 uart->thr = bfin_uart_write_byte (me, value, uart->mcr); 95 if (uart->ier & ETBEI) 96 hw_port_event (me, DV_PORT_TX, 1); 97 break; 98 case mmr_offset(ier_set): 99 uart->ier |= value; 100 break; 101 case mmr_offset(ier_clear): 102 dv_w1c_2 (&uart->ier, value, -1); 103 break; 104 case mmr_offset(lsr): 105 dv_w1c_2 (valuep, value, TFI | BI | FE | PE | OE); 106 break; 107 case mmr_offset(rbr): 108 /* XXX: Writes are ignored ? */ 109 break; 110 case mmr_offset(msr): 111 dv_w1c_2 (valuep, value, SCTS); 112 break; 113 case mmr_offset(dll): 114 case mmr_offset(dlh): 115 case mmr_offset(gctl): 116 case mmr_offset(lcr): 117 case mmr_offset(mcr): 118 case mmr_offset(scr): 119 *valuep = value; 120 break; 121 default: 122 dv_bfin_mmr_invalid (me, addr, nr_bytes, true); 123 return 0; 124 } 125 126 return nr_bytes; 127 } 128 129 static unsigned 130 bfin_uart_io_read_buffer (struct hw *me, void *dest, 131 int space, address_word addr, unsigned nr_bytes) 132 { 133 struct bfin_uart *uart = hw_data (me); 134 bu32 mmr_off; 135 bu16 *valuep; 136 137 /* Invalid access mode is higher priority than missing register. */ 138 if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false)) 139 return 0; 140 141 mmr_off = addr - uart->base; 142 valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off); 143 144 HW_TRACE_READ (); 145 146 switch (mmr_off) 147 { 148 case mmr_offset(rbr): 149 uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL); 150 dv_store_2 (dest, uart->rbr); 151 break; 152 case mmr_offset(ier_set): 153 case mmr_offset(ier_clear): 154 dv_store_2 (dest, uart->ier); 155 bfin_uart_reschedule (me); 156 break; 157 case mmr_offset(lsr): 158 uart->lsr &= ~(DR | THRE | TEMT); 159 uart->lsr |= bfin_uart_get_status (me); 160 case mmr_offset(thr): 161 case mmr_offset(msr): 162 case mmr_offset(dll): 163 case mmr_offset(dlh): 164 case mmr_offset(gctl): 165 case mmr_offset(lcr): 166 case mmr_offset(mcr): 167 case mmr_offset(scr): 168 dv_store_2 (dest, *valuep); 169 break; 170 default: 171 dv_bfin_mmr_invalid (me, addr, nr_bytes, false); 172 return 0; 173 } 174 175 return nr_bytes; 176 } 177 178 static unsigned 179 bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space, 180 unsigned_word addr, unsigned nr_bytes) 181 { 182 HW_TRACE_DMA_READ (); 183 return bfin_uart_read_buffer (me, dest, nr_bytes); 184 } 185 186 static unsigned 187 bfin_uart_dma_write_buffer (struct hw *me, const void *source, 188 int space, unsigned_word addr, 189 unsigned nr_bytes, 190 int violate_read_only_section) 191 { 192 struct bfin_uart *uart = hw_data (me); 193 unsigned ret; 194 195 HW_TRACE_DMA_WRITE (); 196 197 ret = bfin_uart_write_buffer (me, source, nr_bytes); 198 199 if (ret == nr_bytes && (uart->ier & ETBEI)) 200 hw_port_event (me, DV_PORT_TX, 1); 201 202 return ret; 203 } 204 205 static const struct hw_port_descriptor bfin_uart_ports[] = 206 { 207 { "tx", DV_PORT_TX, 0, output_port, }, 208 { "rx", DV_PORT_RX, 0, output_port, }, 209 { "stat", DV_PORT_STAT, 0, output_port, }, 210 { NULL, 0, 0, 0, }, 211 }; 212 213 static void 214 attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart) 215 { 216 address_word attach_address; 217 int attach_space; 218 unsigned attach_size; 219 reg_property_spec reg; 220 221 if (hw_find_property (me, "reg") == NULL) 222 hw_abort (me, "Missing \"reg\" property"); 223 224 if (!hw_find_reg_array_property (me, "reg", 0, ®)) 225 hw_abort (me, "\"reg\" property must contain three addr/size entries"); 226 227 hw_unit_address_to_attach_address (hw_parent (me), 228 ®.address, 229 &attach_space, &attach_address, me); 230 hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); 231 232 if (attach_size != BFIN_MMR_UART2_SIZE) 233 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART2_SIZE); 234 235 hw_attach_address (hw_parent (me), 236 0, attach_space, attach_address, attach_size, me); 237 238 uart->base = attach_address; 239 } 240 241 static void 242 bfin_uart_finish (struct hw *me) 243 { 244 struct bfin_uart *uart; 245 246 uart = HW_ZALLOC (me, struct bfin_uart); 247 248 set_hw_data (me, uart); 249 set_hw_io_read_buffer (me, bfin_uart_io_read_buffer); 250 set_hw_io_write_buffer (me, bfin_uart_io_write_buffer); 251 set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer); 252 set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer); 253 set_hw_ports (me, bfin_uart_ports); 254 255 attach_bfin_uart_regs (me, uart); 256 257 /* Initialize the UART. */ 258 uart->dll = 0x0001; 259 uart->lsr = 0x0060; 260 } 261 262 const struct hw_descriptor dv_bfin_uart2_descriptor[] = 263 { 264 {"bfin_uart2", bfin_uart_finish,}, 265 {NULL, NULL}, 266 }; 267