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.  */
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 #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 
83 static void
bfin_uart_poll(struct hw * me,void * data)84 bfin_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 
98 void
bfin_uart_reschedule(struct hw * me)99 bfin_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 
119 bu16
bfin_uart_write_byte(struct hw * me,bu16 thr)120 bfin_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 
127 static unsigned
bfin_uart_io_write_buffer(struct hw * me,const void * source,int space,address_word addr,unsigned nr_bytes)128 bfin_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.  */
186 bu16
bfin_uart_get_next_byte(struct hw * me,bu16 rbr,bool * fresh)187 bfin_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 
225 bu16
bfin_uart_get_status(struct hw * me)226 bfin_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 
247 static unsigned
bfin_uart_io_read_buffer(struct hw * me,void * dest,int space,address_word addr,unsigned nr_bytes)248 bfin_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 
301 unsigned
bfin_uart_read_buffer(struct hw * me,unsigned char * buffer,unsigned nr_bytes)302 bfin_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 
329 static unsigned
bfin_uart_dma_read_buffer(struct hw * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes)330 bfin_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 
337 unsigned
bfin_uart_write_buffer(struct hw * me,const unsigned char * buffer,unsigned nr_bytes)338 bfin_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 
359 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)360 bfin_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 
378 static 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 
386 static void
attach_bfin_uart_regs(struct hw * me,struct bfin_uart * uart)387 attach_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, &reg))
398     hw_abort (me, "\"reg\" property must contain three addr/size entries");
399 
400   hw_unit_address_to_attach_address (hw_parent (me),
401 				     &reg.address,
402 				     &attach_space, &attach_address, me);
403   hw_unit_size_to_attach_size (hw_parent (me), &reg.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 
414 static void
bfin_uart_finish(struct hw * me)415 bfin_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 
436 const struct hw_descriptor dv_bfin_uart_descriptor[] =
437 {
438   {"bfin_uart", bfin_uart_finish,},
439   {NULL, NULL},
440 };
441