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