1 /* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
2 For "new style" UARTs on BF50x/BF54x parts.
4 Copyright (C) 2010-2023 Free Software Foundation, Inc.
5 Contributed by Analog Devices, Inc.
7 This file is part of simulators.
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.
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.
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/>. */
22 /* This must come before any other includes. */
27 #include "dv-bfin_uart2.h"
29 /* XXX: Should we bother emulating the TX/RX FIFOs ? */
31 /* Internal state needs to be the same as bfin_uart. */
34 /* This top portion matches common dv_bfin struct. */
36 struct hw
*dma_master
;
39 struct hw_event
*handler
;
43 /* Accessed indirectly by ier_{set,clear}. */
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
);
60 #define mmr_base() offsetof(struct bfin_uart, dll)
61 #define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base())
63 static const char * const mmr_names
[] =
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",
69 #define mmr_name(off) mmr_names[(off) / 4]
72 bfin_uart_io_write_buffer (struct hw
*me
, const void *source
,
73 int space
, address_word addr
, unsigned nr_bytes
)
75 struct bfin_uart
*uart
= hw_data (me
);
80 /* Invalid access mode is higher priority than missing register. */
81 if (!dv_bfin_mmr_require_16 (me
, addr
, nr_bytes
, true))
84 value
= dv_load_2 (source
);
85 mmr_off
= addr
- uart
->base
;
86 valuep
= (void *)((uintptr_t)uart
+ mmr_base() + mmr_off
);
90 /* XXX: All MMRs are "8bit" ... what happens to high 8bits ? */
95 uart
->thr
= bfin_uart_write_byte (me
, value
, uart
->mcr
);
96 if (uart
->ier
& ETBEI
)
97 hw_port_event (me
, DV_PORT_TX
, 1);
99 case mmr_offset(ier_set
):
102 case mmr_offset(ier_clear
):
103 dv_w1c_2 (&uart
->ier
, value
, -1);
105 case mmr_offset(lsr
):
106 dv_w1c_2 (valuep
, value
, TFI
| BI
| FE
| PE
| OE
);
108 case mmr_offset(rbr
):
109 /* XXX: Writes are ignored ? */
111 case mmr_offset(msr
):
112 dv_w1c_2 (valuep
, value
, SCTS
);
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
):
123 dv_bfin_mmr_invalid (me
, addr
, nr_bytes
, true);
131 bfin_uart_io_read_buffer (struct hw
*me
, void *dest
,
132 int space
, address_word addr
, unsigned nr_bytes
)
134 struct bfin_uart
*uart
= hw_data (me
);
138 /* Invalid access mode is higher priority than missing register. */
139 if (!dv_bfin_mmr_require_16 (me
, addr
, nr_bytes
, false))
142 mmr_off
= addr
- uart
->base
;
143 valuep
= (void *)((uintptr_t)uart
+ mmr_base() + mmr_off
);
149 case mmr_offset(rbr
):
150 uart
->rbr
= bfin_uart_get_next_byte (me
, uart
->rbr
, uart
->mcr
, NULL
);
151 dv_store_2 (dest
, uart
->rbr
);
153 case mmr_offset(ier_set
):
154 case mmr_offset(ier_clear
):
155 dv_store_2 (dest
, uart
->ier
);
156 bfin_uart_reschedule (me
);
158 case mmr_offset(lsr
):
159 uart
->lsr
&= ~(DR
| THRE
| TEMT
);
160 uart
->lsr
|= bfin_uart_get_status (me
);
161 case mmr_offset(thr
):
162 case mmr_offset(msr
):
163 case mmr_offset(dll
):
164 case mmr_offset(dlh
):
165 case mmr_offset(gctl
):
166 case mmr_offset(lcr
):
167 case mmr_offset(mcr
):
168 case mmr_offset(scr
):
169 dv_store_2 (dest
, *valuep
);
172 dv_bfin_mmr_invalid (me
, addr
, nr_bytes
, false);
180 bfin_uart_dma_read_buffer (struct hw
*me
, void *dest
, int space
,
181 unsigned_word addr
, unsigned nr_bytes
)
183 HW_TRACE_DMA_READ ();
184 return bfin_uart_read_buffer (me
, dest
, nr_bytes
);
188 bfin_uart_dma_write_buffer (struct hw
*me
, const void *source
,
189 int space
, unsigned_word addr
,
191 int violate_read_only_section
)
193 struct bfin_uart
*uart
= hw_data (me
);
196 HW_TRACE_DMA_WRITE ();
198 ret
= bfin_uart_write_buffer (me
, source
, nr_bytes
);
200 if (ret
== nr_bytes
&& (uart
->ier
& ETBEI
))
201 hw_port_event (me
, DV_PORT_TX
, 1);
206 static const struct hw_port_descriptor bfin_uart_ports
[] =
208 { "tx", DV_PORT_TX
, 0, output_port
, },
209 { "rx", DV_PORT_RX
, 0, output_port
, },
210 { "stat", DV_PORT_STAT
, 0, output_port
, },
215 attach_bfin_uart_regs (struct hw
*me
, struct bfin_uart
*uart
)
217 address_word attach_address
;
219 unsigned attach_size
;
220 reg_property_spec reg
;
222 if (hw_find_property (me
, "reg") == NULL
)
223 hw_abort (me
, "Missing \"reg\" property");
225 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
226 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
228 hw_unit_address_to_attach_address (hw_parent (me
),
230 &attach_space
, &attach_address
, me
);
231 hw_unit_size_to_attach_size (hw_parent (me
), ®
.size
, &attach_size
, me
);
233 if (attach_size
!= BFIN_MMR_UART2_SIZE
)
234 hw_abort (me
, "\"reg\" size must be %#x", BFIN_MMR_UART2_SIZE
);
236 hw_attach_address (hw_parent (me
),
237 0, attach_space
, attach_address
, attach_size
, me
);
239 uart
->base
= attach_address
;
243 bfin_uart_finish (struct hw
*me
)
245 struct bfin_uart
*uart
;
247 uart
= HW_ZALLOC (me
, struct bfin_uart
);
249 set_hw_data (me
, uart
);
250 set_hw_io_read_buffer (me
, bfin_uart_io_read_buffer
);
251 set_hw_io_write_buffer (me
, bfin_uart_io_write_buffer
);
252 set_hw_dma_read_buffer (me
, bfin_uart_dma_read_buffer
);
253 set_hw_dma_write_buffer (me
, bfin_uart_dma_write_buffer
);
254 set_hw_ports (me
, bfin_uart_ports
);
256 attach_bfin_uart_regs (me
, uart
);
258 /* Initialize the UART. */
263 const struct hw_descriptor dv_bfin_uart2_descriptor
[] =
265 {"bfin_uart2", bfin_uart_finish
,},