]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/bfin/dv-bfin_uart2.c
Update copyright year range in header of all files managed by GDB
[thirdparty/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
1d506c26 4 Copyright (C) 2010-2024 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
6df01ab8
MF
22/* This must come before any other includes. */
23#include "defs.h"
ef016f83
MF
24
25#include "sim-main.h"
26#include "devices.h"
27#include "dv-bfin_uart2.h"
28
29/* XXX: Should we bother emulating the TX/RX FIFOs ? */
30
31/* Internal state needs to be the same as bfin_uart. */
32struct 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 /* Accessed indirectly by ier_{set,clear}. */
44 bu16 ier;
45
46 /* Order after here is important -- matches hardware MMR layout. */
47 bu16 BFIN_MMR_16(dll);
48 bu16 BFIN_MMR_16(dlh);
49 bu16 BFIN_MMR_16(gctl);
50 bu16 BFIN_MMR_16(lcr);
51 bu16 BFIN_MMR_16(mcr);
52 bu16 BFIN_MMR_16(lsr);
53 bu16 BFIN_MMR_16(msr);
54 bu16 BFIN_MMR_16(scr);
55 bu16 BFIN_MMR_16(ier_set);
56 bu16 BFIN_MMR_16(ier_clear);
57 bu16 BFIN_MMR_16(thr);
58 bu16 BFIN_MMR_16(rbr);
59};
60#define mmr_base() offsetof(struct bfin_uart, dll)
61#define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base())
62
990d19fd
MF
63static const char * const mmr_names[] =
64{
ef016f83
MF
65 "UART_DLL", "UART_DLH", "UART_GCTL", "UART_LCR", "UART_MCR", "UART_LSR",
66 "UART_MSR", "UART_SCR", "UART_IER_SET", "UART_IER_CLEAR", "UART_THR",
67 "UART_RBR",
68};
69#define mmr_name(off) mmr_names[(off) / 4]
70
71static unsigned
72bfin_uart_io_write_buffer (struct hw *me, const void *source,
73 int space, address_word addr, unsigned nr_bytes)
74{
75 struct bfin_uart *uart = hw_data (me);
76 bu32 mmr_off;
77 bu32 value;
78 bu16 *valuep;
79
466b619e
MF
80 /* Invalid access mode is higher priority than missing register. */
81 if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
82 return 0;
83
ef016f83
MF
84 value = dv_load_2 (source);
85 mmr_off = addr - uart->base;
f0bef2e9 86 valuep = (void *)((uintptr_t)uart + mmr_base() + mmr_off);
ef016f83
MF
87
88 HW_TRACE_WRITE ();
89
ef016f83
MF
90 /* XXX: All MMRs are "8bit" ... what happens to high 8bits ? */
91
92 switch (mmr_off)
93 {
94 case mmr_offset(thr):
28fe96b7 95 uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
ef016f83
MF
96 if (uart->ier & ETBEI)
97 hw_port_event (me, DV_PORT_TX, 1);
98 break;
99 case mmr_offset(ier_set):
100 uart->ier |= value;
101 break;
102 case mmr_offset(ier_clear):
9922f803 103 dv_w1c_2 (&uart->ier, value, -1);
ef016f83
MF
104 break;
105 case mmr_offset(lsr):
9922f803 106 dv_w1c_2 (valuep, value, TFI | BI | FE | PE | OE);
ef016f83
MF
107 break;
108 case mmr_offset(rbr):
109 /* XXX: Writes are ignored ? */
110 break;
111 case mmr_offset(msr):
112 dv_w1c_2 (valuep, value, SCTS);
113 break;
114 case mmr_offset(dll):
115 case mmr_offset(dlh):
116 case mmr_offset(gctl):
117 case mmr_offset(lcr):
118 case mmr_offset(mcr):
119 case mmr_offset(scr):
120 *valuep = value;
121 break;
122 default:
123 dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
466b619e 124 return 0;
ef016f83
MF
125 }
126
127 return nr_bytes;
128}
129
130static unsigned
131bfin_uart_io_read_buffer (struct hw *me, void *dest,
132 int space, address_word addr, unsigned nr_bytes)
133{
134 struct bfin_uart *uart = hw_data (me);
135 bu32 mmr_off;
136 bu16 *valuep;
137
466b619e
MF
138 /* Invalid access mode is higher priority than missing register. */
139 if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
140 return 0;
141
ef016f83 142 mmr_off = addr - uart->base;
f0bef2e9 143 valuep = (void *)((uintptr_t)uart + mmr_base() + mmr_off);
ef016f83
MF
144
145 HW_TRACE_READ ();
146
ef016f83
MF
147 switch (mmr_off)
148 {
149 case mmr_offset(rbr):
28fe96b7 150 uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
ef016f83
MF
151 dv_store_2 (dest, uart->rbr);
152 break;
153 case mmr_offset(ier_set):
154 case mmr_offset(ier_clear):
155 dv_store_2 (dest, uart->ier);
156 bfin_uart_reschedule (me);
157 break;
158 case mmr_offset(lsr):
b44f3f63 159 uart->lsr &= ~(DR | THRE | TEMT);
ef016f83 160 uart->lsr |= bfin_uart_get_status (me);
f0e2dc75 161 ATTRIBUTE_FALLTHROUGH;
ef016f83
MF
162 case mmr_offset(thr):
163 case mmr_offset(msr):
164 case mmr_offset(dll):
165 case mmr_offset(dlh):
166 case mmr_offset(gctl):
167 case mmr_offset(lcr):
168 case mmr_offset(mcr):
169 case mmr_offset(scr):
170 dv_store_2 (dest, *valuep);
171 break;
172 default:
173 dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
466b619e 174 return 0;
ef016f83
MF
175 }
176
177 return nr_bytes;
178}
179
180static unsigned
181bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space,
182 unsigned_word addr, unsigned nr_bytes)
183{
184 HW_TRACE_DMA_READ ();
185 return bfin_uart_read_buffer (me, dest, nr_bytes);
186}
187
188static unsigned
189bfin_uart_dma_write_buffer (struct hw *me, const void *source,
190 int space, unsigned_word addr,
191 unsigned nr_bytes,
192 int violate_read_only_section)
193{
194 struct bfin_uart *uart = hw_data (me);
195 unsigned ret;
196
197 HW_TRACE_DMA_WRITE ();
198
199 ret = bfin_uart_write_buffer (me, source, nr_bytes);
200
201 if (ret == nr_bytes && (uart->ier & ETBEI))
202 hw_port_event (me, DV_PORT_TX, 1);
203
204 return ret;
205}
206
990d19fd
MF
207static const struct hw_port_descriptor bfin_uart_ports[] =
208{
ef016f83
MF
209 { "tx", DV_PORT_TX, 0, output_port, },
210 { "rx", DV_PORT_RX, 0, output_port, },
211 { "stat", DV_PORT_STAT, 0, output_port, },
212 { NULL, 0, 0, 0, },
213};
214
215static void
216attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart)
217{
218 address_word attach_address;
219 int attach_space;
220 unsigned attach_size;
221 reg_property_spec reg;
222
223 if (hw_find_property (me, "reg") == NULL)
224 hw_abort (me, "Missing \"reg\" property");
225
226 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
227 hw_abort (me, "\"reg\" property must contain three addr/size entries");
228
229 hw_unit_address_to_attach_address (hw_parent (me),
230 &reg.address,
231 &attach_space, &attach_address, me);
232 hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
233
234 if (attach_size != BFIN_MMR_UART2_SIZE)
235 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART2_SIZE);
236
237 hw_attach_address (hw_parent (me),
238 0, attach_space, attach_address, attach_size, me);
239
240 uart->base = attach_address;
241}
242
243static void
244bfin_uart_finish (struct hw *me)
245{
246 struct bfin_uart *uart;
247
248 uart = HW_ZALLOC (me, struct bfin_uart);
249
250 set_hw_data (me, uart);
251 set_hw_io_read_buffer (me, bfin_uart_io_read_buffer);
252 set_hw_io_write_buffer (me, bfin_uart_io_write_buffer);
253 set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer);
254 set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer);
255 set_hw_ports (me, bfin_uart_ports);
256
257 attach_bfin_uart_regs (me, uart);
258
259 /* Initialize the UART. */
260 uart->dll = 0x0001;
261 uart->lsr = 0x0060;
262}
263
81d126c3
MF
264const struct hw_descriptor dv_bfin_uart2_descriptor[] =
265{
ef016f83
MF
266 {"bfin_uart2", bfin_uart_finish,},
267 {NULL, NULL},
268};