1 /* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
2    For "old style" UARTs on BF53x/etc... parts.
3 
4    Copyright (C) 2010-2020 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.  */
32 struct 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 
63 static 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 };
mmr_name(struct bfin_uart * uart,bu32 idx)68 static 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 static void
bfin_uart_poll(struct hw * me,void * data)78 bfin_uart_poll (struct hw *me, void *data)
79 {
80   struct bfin_uart *uart = data;
81   bu16 lsr;
82 
83   uart->handler = NULL;
84 
85   lsr = bfin_uart_get_status (me);
86   if (lsr & DR)
87     hw_port_event (me, DV_PORT_RX, 1);
88 
89   bfin_uart_reschedule (me);
90 }
91 
92 void
bfin_uart_reschedule(struct hw * me)93 bfin_uart_reschedule (struct hw *me)
94 {
95   struct bfin_uart *uart = hw_data (me);
96 
97   if (uart->ier & ERBFI)
98     {
99       if (!uart->handler)
100 	uart->handler = hw_event_queue_schedule (me, 10000,
101 						 bfin_uart_poll, uart);
102     }
103   else
104     {
105       if (uart->handler)
106 	{
107 	  hw_event_queue_deschedule (me, uart->handler);
108 	  uart->handler = NULL;
109 	}
110     }
111 }
112 
113 bu16
bfin_uart_write_byte(struct hw * me,bu16 thr,bu16 mcr)114 bfin_uart_write_byte (struct hw *me, bu16 thr, bu16 mcr)
115 {
116   struct bfin_uart *uart = hw_data (me);
117   unsigned char ch = thr;
118 
119   if (mcr & LOOP_ENA)
120     {
121       /* XXX: This probably doesn't work exactly right with
122               external FIFOs ...  */
123       uart->saved_byte = thr;
124       uart->saved_count = 1;
125     }
126 
127   bfin_uart_write_buffer (me, &ch, 1);
128 
129   return thr;
130 }
131 
132 static unsigned
bfin_uart_io_write_buffer(struct hw * me,const void * source,int space,address_word addr,unsigned nr_bytes)133 bfin_uart_io_write_buffer (struct hw *me, const void *source,
134 			   int space, address_word addr, unsigned nr_bytes)
135 {
136   struct bfin_uart *uart = hw_data (me);
137   bu32 mmr_off;
138   bu32 value;
139   bu16 *valuep;
140 
141   /* Invalid access mode is higher priority than missing register.  */
142   if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
143     return 0;
144 
145   value = dv_load_2 (source);
146   mmr_off = addr - uart->base;
147   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
148 
149   HW_TRACE_WRITE ();
150 
151   /* XXX: All MMRs are "8bit" ... what happens to high 8bits ?  */
152   switch (mmr_off)
153     {
154     case mmr_offset(dll):
155       if (uart->lcr & DLAB)
156 	uart->dll = value;
157       else
158 	{
159 	  uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
160 
161 	  if (uart->ier & ETBEI)
162 	    hw_port_event (me, DV_PORT_TX, 1);
163 	}
164       break;
165     case mmr_offset(dlh):
166       if (uart->lcr & DLAB)
167 	uart->dlh = value;
168       else
169 	{
170 	  uart->ier = value;
171 	  bfin_uart_reschedule (me);
172 	}
173       break;
174     case mmr_offset(iir):
175     case mmr_offset(lsr):
176       /* XXX: Writes are ignored ?  */
177       break;
178     case mmr_offset(lcr):
179     case mmr_offset(mcr):
180     case mmr_offset(scr):
181     case mmr_offset(gctl):
182       *valuep = value;
183       break;
184     default:
185       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
186       return 0;
187     }
188 
189   return nr_bytes;
190 }
191 
192 /* Switch between socket and stdin on the fly.  */
193 bu16
bfin_uart_get_next_byte(struct hw * me,bu16 rbr,bu16 mcr,bool * fresh)194 bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bu16 mcr, bool *fresh)
195 {
196   SIM_DESC sd = hw_system (me);
197   struct bfin_uart *uart = hw_data (me);
198   int status = dv_sockser_status (sd);
199   bool _fresh;
200 
201   /* NB: The "uart" here may only use interal state.  */
202 
203   if (!fresh)
204     fresh = &_fresh;
205 
206   *fresh = false;
207 
208   if (uart->saved_count > 0)
209     {
210       *fresh = true;
211       rbr = uart->saved_byte;
212       --uart->saved_count;
213     }
214   else if (mcr & LOOP_ENA)
215     {
216       /* RX is disconnected, so only return local data.  */
217     }
218   else if (status & DV_SOCKSER_DISCONNECTED)
219     {
220       char byte;
221       int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
222 
223       if (ret > 0)
224 	{
225 	  *fresh = true;
226 	  rbr = byte;
227 	}
228     }
229   else
230     rbr = dv_sockser_read (sd);
231 
232   return rbr;
233 }
234 
235 bu16
bfin_uart_get_status(struct hw * me)236 bfin_uart_get_status (struct hw *me)
237 {
238   SIM_DESC sd = hw_system (me);
239   struct bfin_uart *uart = hw_data (me);
240   int status = dv_sockser_status (sd);
241   bu16 lsr = 0;
242 
243   if (status & DV_SOCKSER_DISCONNECTED)
244     {
245       if (uart->saved_count <= 0)
246 	uart->saved_count = sim_io_poll_read (sd, 0/*STDIN*/,
247 					      &uart->saved_byte, 1);
248       lsr |= TEMT | THRE | (uart->saved_count > 0 ? DR : 0);
249     }
250   else
251     lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) |
252 	   (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
253 
254   return lsr;
255 }
256 
257 static unsigned
bfin_uart_io_read_buffer(struct hw * me,void * dest,int space,address_word addr,unsigned nr_bytes)258 bfin_uart_io_read_buffer (struct hw *me, void *dest,
259 			  int space, address_word addr, unsigned nr_bytes)
260 {
261   struct bfin_uart *uart = hw_data (me);
262   bu32 mmr_off;
263   bu16 *valuep;
264 
265   /* Invalid access mode is higher priority than missing register.  */
266   if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
267     return 0;
268 
269   mmr_off = addr - uart->base;
270   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
271 
272   HW_TRACE_READ ();
273 
274   switch (mmr_off)
275     {
276     case mmr_offset(dll):
277       if (uart->lcr & DLAB)
278 	dv_store_2 (dest, uart->dll);
279       else
280 	{
281 	  uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
282 	  dv_store_2 (dest, uart->rbr);
283 	}
284       break;
285     case mmr_offset(dlh):
286       if (uart->lcr & DLAB)
287 	dv_store_2 (dest, uart->dlh);
288       else
289 	dv_store_2 (dest, uart->ier);
290       break;
291     case mmr_offset(lsr):
292       /* XXX: Reads are destructive on most parts, but not all ...  */
293       uart->lsr |= bfin_uart_get_status (me);
294       dv_store_2 (dest, *valuep);
295       uart->lsr = 0;
296       break;
297     case mmr_offset(iir):
298       /* XXX: Reads are destructive ...  */
299     case mmr_offset(lcr):
300     case mmr_offset(mcr):
301     case mmr_offset(scr):
302     case mmr_offset(gctl):
303       dv_store_2 (dest, *valuep);
304       break;
305     default:
306       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
307       return 0;
308     }
309 
310   return nr_bytes;
311 }
312 
313 unsigned
bfin_uart_read_buffer(struct hw * me,unsigned char * buffer,unsigned nr_bytes)314 bfin_uart_read_buffer (struct hw *me, unsigned char *buffer, unsigned nr_bytes)
315 {
316   SIM_DESC sd = hw_system (me);
317   struct bfin_uart *uart = hw_data (me);
318   int status = dv_sockser_status (sd);
319   unsigned i = 0;
320 
321   if (status & DV_SOCKSER_DISCONNECTED)
322     {
323       int ret;
324 
325       while (uart->saved_count > 0 && i < nr_bytes)
326 	{
327 	  buffer[i++] = uart->saved_byte;
328 	  --uart->saved_count;
329 	}
330 
331       ret = sim_io_poll_read (sd, 0/*STDIN*/, (char *) buffer, nr_bytes - i);
332       if (ret > 0)
333 	i += ret;
334     }
335   else
336     buffer[i++] = dv_sockser_read (sd);
337 
338   return i;
339 }
340 
341 static unsigned
bfin_uart_dma_read_buffer(struct hw * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes)342 bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space,
343 			   unsigned_word addr, unsigned nr_bytes)
344 {
345   HW_TRACE_DMA_READ ();
346   return bfin_uart_read_buffer (me, dest, nr_bytes);
347 }
348 
349 unsigned
bfin_uart_write_buffer(struct hw * me,const unsigned char * buffer,unsigned nr_bytes)350 bfin_uart_write_buffer (struct hw *me, const unsigned char *buffer,
351 			unsigned nr_bytes)
352 {
353   SIM_DESC sd = hw_system (me);
354   int status = dv_sockser_status (sd);
355 
356   if (status & DV_SOCKSER_DISCONNECTED)
357     {
358       sim_io_write_stdout (sd, (const char *) buffer, nr_bytes);
359       sim_io_flush_stdout (sd);
360     }
361   else
362     {
363       /* Normalize errors to a value of 0.  */
364       int ret = dv_sockser_write_buffer (sd, buffer, nr_bytes);
365       nr_bytes = CLAMP (ret, 0, nr_bytes);
366     }
367 
368   return nr_bytes;
369 }
370 
371 static unsigned
bfin_uart_dma_write_buffer(struct hw * me,const void * source,int space,unsigned_word addr,unsigned nr_bytes,int violate_read_only_section)372 bfin_uart_dma_write_buffer (struct hw *me, const void *source,
373 			    int space, unsigned_word addr,
374 			    unsigned nr_bytes,
375 			    int violate_read_only_section)
376 {
377   struct bfin_uart *uart = hw_data (me);
378   unsigned ret;
379 
380   HW_TRACE_DMA_WRITE ();
381 
382   ret = bfin_uart_write_buffer (me, source, nr_bytes);
383 
384   if (ret == nr_bytes && (uart->ier & ETBEI))
385     hw_port_event (me, DV_PORT_TX, 1);
386 
387   return ret;
388 }
389 
390 static const struct hw_port_descriptor bfin_uart_ports[] =
391 {
392   { "tx",   DV_PORT_TX,   0, output_port, },
393   { "rx",   DV_PORT_RX,   0, output_port, },
394   { "stat", DV_PORT_STAT, 0, output_port, },
395   { NULL, 0, 0, 0, },
396 };
397 
398 static void
attach_bfin_uart_regs(struct hw * me,struct bfin_uart * uart)399 attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart)
400 {
401   address_word attach_address;
402   int attach_space;
403   unsigned attach_size;
404   reg_property_spec reg;
405 
406   if (hw_find_property (me, "reg") == NULL)
407     hw_abort (me, "Missing \"reg\" property");
408 
409   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
410     hw_abort (me, "\"reg\" property must contain three addr/size entries");
411 
412   hw_unit_address_to_attach_address (hw_parent (me),
413 				     &reg.address,
414 				     &attach_space, &attach_address, me);
415   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
416 
417   if (attach_size != BFIN_MMR_UART_SIZE)
418     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART_SIZE);
419 
420   hw_attach_address (hw_parent (me),
421 		     0, attach_space, attach_address, attach_size, me);
422 
423   uart->base = attach_address;
424 }
425 
426 static void
bfin_uart_finish(struct hw * me)427 bfin_uart_finish (struct hw *me)
428 {
429   struct bfin_uart *uart;
430 
431   uart = HW_ZALLOC (me, struct bfin_uart);
432 
433   set_hw_data (me, uart);
434   set_hw_io_read_buffer (me, bfin_uart_io_read_buffer);
435   set_hw_io_write_buffer (me, bfin_uart_io_write_buffer);
436   set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer);
437   set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer);
438   set_hw_ports (me, bfin_uart_ports);
439 
440   attach_bfin_uart_regs (me, uart);
441 
442   /* Initialize the UART.  */
443   uart->dll = 0x0001;
444   uart->iir = 0x0001;
445   uart->lsr = 0x0060;
446 }
447 
448 const struct hw_descriptor dv_bfin_uart_descriptor[] =
449 {
450   {"bfin_uart", bfin_uart_finish,},
451   {NULL, NULL},
452 };
453