Update copyright year range in all GDB files.
[deliverable/binutils-gdb.git] / sim / bfin / dv-bfin_uart2.c
CommitLineData
ef016f83
MF
1/* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
2 For "new style" UARTs on BF50x/BF54x parts.
3
b811d2c2 4 Copyright (C) 2010-2020 Free Software Foundation, Inc.
ef016f83
MF
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. */
31struct 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
990d19fd
MF
62static const char * const mmr_names[] =
63{
ef016f83
MF
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
70static unsigned
71bfin_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
466b619e
MF
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
ef016f83
MF
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
ef016f83
MF
89 /* XXX: All MMRs are "8bit" ... what happens to high 8bits ? */
90
91 switch (mmr_off)
92 {
93 case mmr_offset(thr):
28fe96b7 94 uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
ef016f83
MF
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):
9922f803 102 dv_w1c_2 (&uart->ier, value, -1);
ef016f83
MF
103 break;
104 case mmr_offset(lsr):
9922f803 105 dv_w1c_2 (valuep, value, TFI | BI | FE | PE | OE);
ef016f83
MF
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);
466b619e 123 return 0;
ef016f83
MF
124 }
125
126 return nr_bytes;
127}
128
129static unsigned
130bfin_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
466b619e
MF
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
ef016f83
MF
141 mmr_off = addr - uart->base;
142 valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
143
144 HW_TRACE_READ ();
145
ef016f83
MF
146 switch (mmr_off)
147 {
148 case mmr_offset(rbr):
28fe96b7 149 uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
ef016f83
MF
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):
b44f3f63 158 uart->lsr &= ~(DR | THRE | TEMT);
ef016f83
MF
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);
466b619e 172 return 0;
ef016f83
MF
173 }
174
175 return nr_bytes;
176}
177
178static unsigned
179bfin_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
186static unsigned
187bfin_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
990d19fd
MF
205static const struct hw_port_descriptor bfin_uart_ports[] =
206{
ef016f83
MF
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
213static void
214attach_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
241static void
242bfin_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
81d126c3
MF
262const struct hw_descriptor dv_bfin_uart2_descriptor[] =
263{
ef016f83
MF
264 {"bfin_uart2", bfin_uart_finish,},
265 {NULL, NULL},
266};
This page took 0.414133 seconds and 4 git commands to generate.