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.  */
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
77static void
78bfin_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
92void
93bfin_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
113bu16
114bfin_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
132static unsigned
133bfin_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.  */
193bu16
194bfin_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
235bu16
236bfin_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
257static unsigned
258bfin_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
313unsigned
314bfin_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
341static unsigned
342bfin_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
349unsigned
350bfin_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
371static unsigned
372bfin_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
390static 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
398static void
399attach_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
426static void
427bfin_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
448const struct hw_descriptor dv_bfin_uart_descriptor[] =
449{
450  {"bfin_uart", bfin_uart_finish,},
451  {NULL, NULL},
452};
453