dv-bfin_ppi.c revision 1.1 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.1 christos Copyright (C) 2010-2014 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.1 christos #include "config.h"
23 1.1 christos
24 1.1 christos #include "sim-main.h"
25 1.1 christos #include "devices.h"
26 1.1 christos #include "dv-bfin_ppi.h"
27 1.1 christos #include "gui.h"
28 1.1 christos
29 1.1 christos /* XXX: TX is merely a stub. */
30 1.1 christos
31 1.1 christos struct bfin_ppi
32 1.1 christos {
33 1.1 christos /* This top portion matches common dv_bfin struct. */
34 1.1 christos bu32 base;
35 1.1 christos struct hw *dma_master;
36 1.1 christos bool acked;
37 1.1 christos
38 1.1 christos struct hw_event *handler;
39 1.1 christos char saved_byte;
40 1.1 christos int saved_count;
41 1.1 christos
42 1.1 christos /* GUI state. */
43 1.1 christos void *gui_state;
44 1.1 christos int color;
45 1.1 christos
46 1.1 christos /* Order after here is important -- matches hardware MMR layout. */
47 1.1 christos bu16 BFIN_MMR_16(control);
48 1.1 christos bu16 BFIN_MMR_16(status);
49 1.1 christos bu16 BFIN_MMR_16(count);
50 1.1 christos bu16 BFIN_MMR_16(delay);
51 1.1 christos bu16 BFIN_MMR_16(frame);
52 1.1 christos };
53 1.1 christos #define mmr_base() offsetof(struct bfin_ppi, control)
54 1.1 christos #define mmr_offset(mmr) (offsetof(struct bfin_ppi, mmr) - mmr_base())
55 1.1 christos
56 1.1 christos static const char * const mmr_names[] =
57 1.1 christos {
58 1.1 christos "PPI_CONTROL", "PPI_STATUS", "PPI_COUNT", "PPI_DELAY", "PPI_FRAME",
59 1.1 christos };
60 1.1 christos #define mmr_name(off) mmr_names[(off) / 4]
61 1.1 christos
62 1.1 christos static void
63 1.1 christos bfin_ppi_gui_setup (struct bfin_ppi *ppi)
64 1.1 christos {
65 1.1 christos int bpp;
66 1.1 christos
67 1.1 christos /* If we are in RX mode, nothing to do. */
68 1.1 christos if (!(ppi->control & PORT_DIR))
69 1.1 christos return;
70 1.1 christos
71 1.1 christos bpp = bfin_gui_color_depth (ppi->color);
72 1.1 christos ppi->gui_state = bfin_gui_setup (ppi->gui_state,
73 1.1 christos ppi->control & PORT_EN,
74 1.1 christos (ppi->count + 1) / (bpp / 8),
75 1.1 christos ppi->frame,
76 1.1 christos ppi->color);
77 1.1 christos }
78 1.1 christos
79 1.1 christos static unsigned
80 1.1 christos bfin_ppi_io_write_buffer (struct hw *me, const void *source, int space,
81 1.1 christos address_word addr, unsigned nr_bytes)
82 1.1 christos {
83 1.1 christos struct bfin_ppi *ppi = hw_data (me);
84 1.1 christos bu32 mmr_off;
85 1.1 christos bu32 value;
86 1.1 christos bu16 *valuep;
87 1.1 christos
88 1.1 christos value = dv_load_2 (source);
89 1.1 christos mmr_off = addr - ppi->base;
90 1.1 christos valuep = (void *)((unsigned long)ppi + mmr_base() + mmr_off);
91 1.1 christos
92 1.1 christos HW_TRACE_WRITE ();
93 1.1 christos
94 1.1 christos dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
95 1.1 christos
96 1.1 christos switch (mmr_off)
97 1.1 christos {
98 1.1 christos case mmr_offset(control):
99 1.1 christos *valuep = value;
100 1.1 christos bfin_ppi_gui_setup (ppi);
101 1.1 christos break;
102 1.1 christos case mmr_offset(count):
103 1.1 christos case mmr_offset(delay):
104 1.1 christos case mmr_offset(frame):
105 1.1 christos *valuep = value;
106 1.1 christos break;
107 1.1 christos case mmr_offset(status):
108 1.1 christos dv_w1c_2 (valuep, value, ~(1 << 10));
109 1.1 christos break;
110 1.1 christos default:
111 1.1 christos dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
112 1.1 christos break;
113 1.1 christos }
114 1.1 christos
115 1.1 christos return nr_bytes;
116 1.1 christos }
117 1.1 christos
118 1.1 christos static unsigned
119 1.1 christos bfin_ppi_io_read_buffer (struct hw *me, void *dest, int space,
120 1.1 christos address_word addr, unsigned nr_bytes)
121 1.1 christos {
122 1.1 christos struct bfin_ppi *ppi = hw_data (me);
123 1.1 christos bu32 mmr_off;
124 1.1 christos bu16 *valuep;
125 1.1 christos
126 1.1 christos mmr_off = addr - ppi->base;
127 1.1 christos valuep = (void *)((unsigned long)ppi + mmr_base() + mmr_off);
128 1.1 christos
129 1.1 christos HW_TRACE_READ ();
130 1.1 christos
131 1.1 christos dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
132 1.1 christos
133 1.1 christos switch (mmr_off)
134 1.1 christos {
135 1.1 christos case mmr_offset(control):
136 1.1 christos case mmr_offset(count):
137 1.1 christos case mmr_offset(delay):
138 1.1 christos case mmr_offset(frame):
139 1.1 christos case mmr_offset(status):
140 1.1 christos dv_store_2 (dest, *valuep);
141 1.1 christos break;
142 1.1 christos default:
143 1.1 christos dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
144 1.1 christos break;
145 1.1 christos }
146 1.1 christos
147 1.1 christos return nr_bytes;
148 1.1 christos }
149 1.1 christos
150 1.1 christos static unsigned
151 1.1 christos bfin_ppi_dma_read_buffer (struct hw *me, void *dest, int space,
152 1.1 christos unsigned_word addr, unsigned nr_bytes)
153 1.1 christos {
154 1.1 christos HW_TRACE_DMA_READ ();
155 1.1 christos return 0;
156 1.1 christos }
157 1.1 christos
158 1.1 christos static unsigned
159 1.1 christos bfin_ppi_dma_write_buffer (struct hw *me, const void *source,
160 1.1 christos int space, unsigned_word addr,
161 1.1 christos unsigned nr_bytes,
162 1.1 christos int violate_read_only_section)
163 1.1 christos {
164 1.1 christos struct bfin_ppi *ppi = hw_data (me);
165 1.1 christos
166 1.1 christos HW_TRACE_DMA_WRITE ();
167 1.1 christos
168 1.1 christos return bfin_gui_update (ppi->gui_state, source, nr_bytes);
169 1.1 christos }
170 1.1 christos
171 1.1 christos static const struct hw_port_descriptor bfin_ppi_ports[] =
172 1.1 christos {
173 1.1 christos { "stat", 0, 0, output_port, },
174 1.1 christos { NULL, 0, 0, 0, },
175 1.1 christos };
176 1.1 christos
177 1.1 christos static void
178 1.1 christos attach_bfin_ppi_regs (struct hw *me, struct bfin_ppi *ppi)
179 1.1 christos {
180 1.1 christos address_word attach_address;
181 1.1 christos int attach_space;
182 1.1 christos unsigned attach_size;
183 1.1 christos reg_property_spec reg;
184 1.1 christos
185 1.1 christos if (hw_find_property (me, "reg") == NULL)
186 1.1 christos hw_abort (me, "Missing \"reg\" property");
187 1.1 christos
188 1.1 christos if (!hw_find_reg_array_property (me, "reg", 0, ®))
189 1.1 christos hw_abort (me, "\"reg\" property must contain three addr/size entries");
190 1.1 christos
191 1.1 christos hw_unit_address_to_attach_address (hw_parent (me),
192 1.1 christos ®.address,
193 1.1 christos &attach_space, &attach_address, me);
194 1.1 christos hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me);
195 1.1 christos
196 1.1 christos if (attach_size != BFIN_MMR_PPI_SIZE)
197 1.1 christos hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_PPI_SIZE);
198 1.1 christos
199 1.1 christos hw_attach_address (hw_parent (me),
200 1.1 christos 0, attach_space, attach_address, attach_size, me);
201 1.1 christos
202 1.1 christos ppi->base = attach_address;
203 1.1 christos }
204 1.1 christos
205 1.1 christos static void
206 1.1 christos bfin_ppi_finish (struct hw *me)
207 1.1 christos {
208 1.1 christos struct bfin_ppi *ppi;
209 1.1 christos const char *color;
210 1.1 christos
211 1.1 christos ppi = HW_ZALLOC (me, struct bfin_ppi);
212 1.1 christos
213 1.1 christos set_hw_data (me, ppi);
214 1.1 christos set_hw_io_read_buffer (me, bfin_ppi_io_read_buffer);
215 1.1 christos set_hw_io_write_buffer (me, bfin_ppi_io_write_buffer);
216 1.1 christos set_hw_dma_read_buffer (me, bfin_ppi_dma_read_buffer);
217 1.1 christos set_hw_dma_write_buffer (me, bfin_ppi_dma_write_buffer);
218 1.1 christos set_hw_ports (me, bfin_ppi_ports);
219 1.1 christos
220 1.1 christos attach_bfin_ppi_regs (me, ppi);
221 1.1 christos
222 1.1 christos /* Initialize the PPI. */
223 1.1 christos if (hw_find_property (me, "color"))
224 1.1 christos color = hw_find_string_property (me, "color");
225 1.1 christos else
226 1.1 christos color = NULL;
227 1.1 christos ppi->color = bfin_gui_color (color);
228 1.1 christos }
229 1.1 christos
230 1.1 christos const struct hw_descriptor dv_bfin_ppi_descriptor[] =
231 1.1 christos {
232 1.1 christos {"bfin_ppi", bfin_ppi_finish,},
233 1.1 christos {NULL, NULL},
234 1.1 christos };
235