1 /* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
2    For "new style" UARTs on BF50x/BF54x 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 "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
bfin_uart_io_write_buffer(struct hw * me,const void * source,int space,address_word addr,unsigned nr_bytes)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   value = dv_load_2 (source);
80   mmr_off = addr - uart->base;
81   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
82 
83   HW_TRACE_WRITE ();
84 
85   dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
86 
87   /* XXX: All MMRs are "8bit" ... what happens to high 8bits ?  */
88 
89   switch (mmr_off)
90     {
91     case mmr_offset(thr):
92       uart->thr = bfin_uart_write_byte (me, value);
93       if (uart->ier & ETBEI)
94 	hw_port_event (me, DV_PORT_TX, 1);
95       break;
96     case mmr_offset(ier_set):
97       uart->ier |= value;
98       break;
99     case mmr_offset(ier_clear):
100       dv_w1c_2 (&uart->ier, value, -1);
101       break;
102     case mmr_offset(lsr):
103       dv_w1c_2 (valuep, value, TFI | BI | FE | PE | OE);
104       break;
105     case mmr_offset(rbr):
106       /* XXX: Writes are ignored ?  */
107       break;
108     case mmr_offset(msr):
109       dv_w1c_2 (valuep, value, SCTS);
110       break;
111     case mmr_offset(dll):
112     case mmr_offset(dlh):
113     case mmr_offset(gctl):
114     case mmr_offset(lcr):
115     case mmr_offset(mcr):
116     case mmr_offset(scr):
117       *valuep = value;
118       break;
119     default:
120       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
121       break;
122     }
123 
124   return nr_bytes;
125 }
126 
127 static unsigned
bfin_uart_io_read_buffer(struct hw * me,void * dest,int space,address_word addr,unsigned nr_bytes)128 bfin_uart_io_read_buffer (struct hw *me, void *dest,
129 			  int space, address_word addr, unsigned nr_bytes)
130 {
131   struct bfin_uart *uart = hw_data (me);
132   bu32 mmr_off;
133   bu16 *valuep;
134 
135   mmr_off = addr - uart->base;
136   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
137 
138   HW_TRACE_READ ();
139 
140   dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
141 
142   switch (mmr_off)
143     {
144     case mmr_offset(rbr):
145       uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL);
146       dv_store_2 (dest, uart->rbr);
147       break;
148     case mmr_offset(ier_set):
149     case mmr_offset(ier_clear):
150       dv_store_2 (dest, uart->ier);
151       bfin_uart_reschedule (me);
152       break;
153     case mmr_offset(lsr):
154       uart->lsr |= bfin_uart_get_status (me);
155     case mmr_offset(thr):
156     case mmr_offset(msr):
157     case mmr_offset(dll):
158     case mmr_offset(dlh):
159     case mmr_offset(gctl):
160     case mmr_offset(lcr):
161     case mmr_offset(mcr):
162     case mmr_offset(scr):
163       dv_store_2 (dest, *valuep);
164       break;
165     default:
166       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
167       break;
168     }
169 
170   return nr_bytes;
171 }
172 
173 static unsigned
bfin_uart_dma_read_buffer(struct hw * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes)174 bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space,
175 			   unsigned_word addr, unsigned nr_bytes)
176 {
177   HW_TRACE_DMA_READ ();
178   return bfin_uart_read_buffer (me, dest, nr_bytes);
179 }
180 
181 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)182 bfin_uart_dma_write_buffer (struct hw *me, const void *source,
183 			    int space, unsigned_word addr,
184 			    unsigned nr_bytes,
185 			    int violate_read_only_section)
186 {
187   struct bfin_uart *uart = hw_data (me);
188   unsigned ret;
189 
190   HW_TRACE_DMA_WRITE ();
191 
192   ret = bfin_uart_write_buffer (me, source, nr_bytes);
193 
194   if (ret == nr_bytes && (uart->ier & ETBEI))
195     hw_port_event (me, DV_PORT_TX, 1);
196 
197   return ret;
198 }
199 
200 static const struct hw_port_descriptor bfin_uart_ports[] =
201 {
202   { "tx",   DV_PORT_TX,   0, output_port, },
203   { "rx",   DV_PORT_RX,   0, output_port, },
204   { "stat", DV_PORT_STAT, 0, output_port, },
205   { NULL, 0, 0, 0, },
206 };
207 
208 static void
attach_bfin_uart_regs(struct hw * me,struct bfin_uart * uart)209 attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart)
210 {
211   address_word attach_address;
212   int attach_space;
213   unsigned attach_size;
214   reg_property_spec reg;
215 
216   if (hw_find_property (me, "reg") == NULL)
217     hw_abort (me, "Missing \"reg\" property");
218 
219   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
220     hw_abort (me, "\"reg\" property must contain three addr/size entries");
221 
222   hw_unit_address_to_attach_address (hw_parent (me),
223 				     &reg.address,
224 				     &attach_space, &attach_address, me);
225   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
226 
227   if (attach_size != BFIN_MMR_UART2_SIZE)
228     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART2_SIZE);
229 
230   hw_attach_address (hw_parent (me),
231 		     0, attach_space, attach_address, attach_size, me);
232 
233   uart->base = attach_address;
234 }
235 
236 static void
bfin_uart_finish(struct hw * me)237 bfin_uart_finish (struct hw *me)
238 {
239   struct bfin_uart *uart;
240 
241   uart = HW_ZALLOC (me, struct bfin_uart);
242 
243   set_hw_data (me, uart);
244   set_hw_io_read_buffer (me, bfin_uart_io_read_buffer);
245   set_hw_io_write_buffer (me, bfin_uart_io_write_buffer);
246   set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer);
247   set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer);
248   set_hw_ports (me, bfin_uart_ports);
249 
250   attach_bfin_uart_regs (me, uart);
251 
252   /* Initialize the UART.  */
253   uart->dll = 0x0001;
254   uart->lsr = 0x0060;
255 }
256 
257 const struct hw_descriptor dv_bfin_uart2_descriptor[] =
258 {
259   {"bfin_uart2", bfin_uart_finish,},
260   {NULL, NULL},
261 };
262