dv-bfin_ppi.c revision 1.11 1 1.1 christos /* Blackfin Parallel Port Interface (PPI) model
2 1.1 christos For "old style" PPIs on BF53x/etc... parts.
3 1.1 christos
4 1.11 christos Copyright (C) 2010-2024 Free Software Foundation, Inc.
5 1.1 christos Contributed by Analog Devices, Inc.
6 1.1 christos
7 1.1 christos This file is part of simulators.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 1.1 christos
22 1.10 christos /* This must come before any other includes. */
23 1.10 christos #include "defs.h"
24 1.1 christos
25 1.1 christos #include "sim-main.h"
26 1.1 christos #include "devices.h"
27 1.1 christos #include "dv-bfin_ppi.h"
28 1.1 christos #include "gui.h"
29 1.1 christos
30 1.1 christos /* XXX: TX is merely a stub. */
31 1.1 christos
32 1.1 christos struct bfin_ppi
33 1.1 christos {
34 1.1 christos /* This top portion matches common dv_bfin struct. */
35 1.1 christos bu32 base;
36 1.1 christos struct hw *dma_master;
37 1.1 christos bool acked;
38 1.1 christos
39 1.1 christos struct hw_event *handler;
40 1.1 christos char saved_byte;
41 1.1 christos int saved_count;
42 1.1 christos
43 1.1 christos /* GUI state. */
44 1.1 christos void *gui_state;
45 1.1 christos int color;
46 1.1 christos
47 1.1 christos /* Order after here is important -- matches hardware MMR layout. */
48 1.1 christos bu16 BFIN_MMR_16(control);
49 1.1 christos bu16 BFIN_MMR_16(status);
50 1.1 christos bu16 BFIN_MMR_16(count);
51 1.1 christos bu16 BFIN_MMR_16(delay);
52 1.1 christos bu16 BFIN_MMR_16(frame);
53 1.1 christos };
54 1.1 christos #define mmr_base() offsetof(struct bfin_ppi, control)
55 1.1 christos #define mmr_offset(mmr) (offsetof(struct bfin_ppi, mmr) - mmr_base())
56 1.1 christos
57 1.1 christos static const char * const mmr_names[] =
58 1.1 christos {
59 1.1 christos "PPI_CONTROL", "PPI_STATUS", "PPI_COUNT", "PPI_DELAY", "PPI_FRAME",
60 1.1 christos };
61 1.1 christos #define mmr_name(off) mmr_names[(off) / 4]
62 1.1 christos
63 1.1 christos static void
64 1.1 christos bfin_ppi_gui_setup (struct bfin_ppi *ppi)
65 1.1 christos {
66 1.1 christos int bpp;
67 1.1 christos
68 1.1 christos /* If we are in RX mode, nothing to do. */
69 1.1 christos if (!(ppi->control & PORT_DIR))
70 1.1 christos return;
71 1.1 christos
72 1.1 christos bpp = bfin_gui_color_depth (ppi->color);
73 1.1 christos ppi->gui_state = bfin_gui_setup (ppi->gui_state,
74 1.1 christos ppi->control & PORT_EN,
75 1.1 christos (ppi->count + 1) / (bpp / 8),
76 1.1 christos ppi->frame,
77 1.1 christos ppi->color);
78 1.1 christos }
79 1.1 christos
80 1.1 christos static unsigned
81 1.1 christos bfin_ppi_io_write_buffer (struct hw *me, const void *source, int space,
82 1.1 christos address_word addr, unsigned nr_bytes)
83 1.1 christos {
84 1.1 christos struct bfin_ppi *ppi = hw_data (me);
85 1.1 christos bu32 mmr_off;
86 1.1 christos bu32 value;
87 1.1 christos bu16 *valuep;
88 1.1 christos
89 1.6 christos /* Invalid access mode is higher priority than missing register. */
90 1.6 christos if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
91 1.6 christos return 0;
92 1.6 christos
93 1.1 christos value = dv_load_2 (source);
94 1.1 christos mmr_off = addr - ppi->base;
95 1.10 christos valuep = (void *)((uintptr_t)ppi + mmr_base() + mmr_off);
96 1.1 christos
97 1.1 christos HW_TRACE_WRITE ();
98 1.1 christos
99 1.1 christos switch (mmr_off)
100 1.1 christos {
101 1.1 christos case mmr_offset(control):
102 1.1 christos *valuep = value;
103 1.1 christos bfin_ppi_gui_setup (ppi);
104 1.1 christos break;
105 1.1 christos case mmr_offset(count):
106 1.1 christos case mmr_offset(delay):
107 1.1 christos case mmr_offset(frame):
108 1.1 christos *valuep = value;
109 1.1 christos break;
110 1.1 christos case mmr_offset(status):
111 1.1 christos dv_w1c_2 (valuep, value, ~(1 << 10));
112 1.1 christos break;
113 1.1 christos default:
114 1.1 christos dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
115 1.6 christos return 0;
116 1.1 christos }
117 1.1 christos
118 1.1 christos return nr_bytes;
119 1.1 christos }
120 1.1 christos
121 1.1 christos static unsigned
122 1.1 christos bfin_ppi_io_read_buffer (struct hw *me, void *dest, int space,
123 1.1 christos address_word addr, unsigned nr_bytes)
124 1.1 christos {
125 1.1 christos struct bfin_ppi *ppi = hw_data (me);
126 1.1 christos bu32 mmr_off;
127 1.1 christos bu16 *valuep;
128 1.1 christos
129 1.6 christos /* Invalid access mode is higher priority than missing register. */
130 1.6 christos if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
131 1.6 christos return 0;
132 1.6 christos
133 1.1 christos mmr_off = addr - ppi->base;
134 1.10 christos valuep = (void *)((uintptr_t)ppi + mmr_base() + mmr_off);
135 1.1 christos
136 1.1 christos HW_TRACE_READ ();
137 1.1 christos
138 1.1 christos switch (mmr_off)
139 1.1 christos {
140 1.1 christos case mmr_offset(control):
141 1.1 christos case mmr_offset(count):
142 1.1 christos case mmr_offset(delay):
143 1.1 christos case mmr_offset(frame):
144 1.1 christos case mmr_offset(status):
145 1.1 christos dv_store_2 (dest, *valuep);
146 1.1 christos break;
147 1.1 christos default:
148 1.1 christos dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
149 1.6 christos return 0;
150 1.1 christos }
151 1.1 christos
152 1.1 christos return nr_bytes;
153 1.1 christos }
154 1.1 christos
155 1.1 christos static unsigned
156 1.1 christos bfin_ppi_dma_read_buffer (struct hw *me, void *dest, int space,
157 1.1 christos unsigned_word addr, unsigned nr_bytes)
158 1.1 christos {
159 1.1 christos HW_TRACE_DMA_READ ();
160 1.1 christos return 0;
161 1.1 christos }
162 1.1 christos
163 1.1 christos static unsigned
164 1.1 christos bfin_ppi_dma_write_buffer (struct hw *me, const void *source,
165 1.1 christos int space, unsigned_word addr,
166 1.1 christos unsigned nr_bytes,
167 1.1 christos int violate_read_only_section)
168 1.1 christos {
169 1.1 christos struct bfin_ppi *ppi = hw_data (me);
170 1.1 christos
171 1.1 christos HW_TRACE_DMA_WRITE ();
172 1.1 christos
173 1.1 christos return bfin_gui_update (ppi->gui_state, source, nr_bytes);
174 1.1 christos }
175 1.1 christos
176 1.1 christos static const struct hw_port_descriptor bfin_ppi_ports[] =
177 1.1 christos {
178 1.1 christos { "stat", 0, 0, output_port, },
179 1.1 christos { NULL, 0, 0, 0, },
180 1.1 christos };
181 1.1 christos
182 1.1 christos static void
183 1.1 christos attach_bfin_ppi_regs (struct hw *me, struct bfin_ppi *ppi)
184 1.1 christos {
185 1.1 christos address_word attach_address;
186 1.1 christos int attach_space;
187 1.1 christos unsigned attach_size;
188 1.1 christos reg_property_spec reg;
189 1.1 christos
190 1.1 christos if (hw_find_property (me, "reg") == NULL)
191 1.1 christos hw_abort (me, "Missing \"reg\" property");
192 1.1 christos
193 1.1 christos if (!hw_find_reg_array_property (me, "reg", 0, ®))
194 1.1 christos hw_abort (me, "\"reg\" property must contain three addr/size entries");
195 1.1 christos
196 1.1 christos hw_unit_address_to_attach_address (hw_parent (me),
197 1.1 christos ®.address,
198 1.1 christos &attach_space, &attach_address, me);
199 1.1 christos hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me);
200 1.1 christos
201 1.1 christos if (attach_size != BFIN_MMR_PPI_SIZE)
202 1.1 christos hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_PPI_SIZE);
203 1.1 christos
204 1.1 christos hw_attach_address (hw_parent (me),
205 1.1 christos 0, attach_space, attach_address, attach_size, me);
206 1.1 christos
207 1.1 christos ppi->base = attach_address;
208 1.1 christos }
209 1.1 christos
210 1.1 christos static void
211 1.1 christos bfin_ppi_finish (struct hw *me)
212 1.1 christos {
213 1.1 christos struct bfin_ppi *ppi;
214 1.1 christos const char *color;
215 1.1 christos
216 1.1 christos ppi = HW_ZALLOC (me, struct bfin_ppi);
217 1.1 christos
218 1.1 christos set_hw_data (me, ppi);
219 1.1 christos set_hw_io_read_buffer (me, bfin_ppi_io_read_buffer);
220 1.1 christos set_hw_io_write_buffer (me, bfin_ppi_io_write_buffer);
221 1.1 christos set_hw_dma_read_buffer (me, bfin_ppi_dma_read_buffer);
222 1.1 christos set_hw_dma_write_buffer (me, bfin_ppi_dma_write_buffer);
223 1.1 christos set_hw_ports (me, bfin_ppi_ports);
224 1.1 christos
225 1.1 christos attach_bfin_ppi_regs (me, ppi);
226 1.1 christos
227 1.1 christos /* Initialize the PPI. */
228 1.1 christos if (hw_find_property (me, "color"))
229 1.1 christos color = hw_find_string_property (me, "color");
230 1.1 christos else
231 1.1 christos color = NULL;
232 1.1 christos ppi->color = bfin_gui_color (color);
233 1.1 christos }
234 1.1 christos
235 1.1 christos const struct hw_descriptor dv_bfin_ppi_descriptor[] =
236 1.1 christos {
237 1.1 christos {"bfin_ppi", bfin_ppi_finish,},
238 1.1 christos {NULL, NULL},
239 1.1 christos };
240