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