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