1 /* Blackfin device support. 2 3 Copyright (C) 2010-2014 Free Software Foundation, Inc. 4 Contributed by Analog Devices, Inc. 5 6 This file is part of simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 23 #include "sim-main.h" 24 #include "sim-hw.h" 25 #include "hw-device.h" 26 #include "devices.h" 27 #include "dv-bfin_cec.h" 28 #include "dv-bfin_mmu.h" 29 30 static void 31 bfin_mmr_invalid (struct hw *me, SIM_CPU *cpu, address_word addr, 32 unsigned nr_bytes, bool write) 33 { 34 if (!cpu) 35 cpu = hw_system_cpu (me); 36 37 /* Only throw a fit if the cpu is doing the access. DMA/GDB simply 38 go unnoticed. Not exactly hardware behavior, but close enough. */ 39 if (!cpu) 40 { 41 sim_io_eprintf (hw_system (me), "%s: invalid MMR access @ %#x\n", 42 hw_path (me), addr); 43 return; 44 } 45 46 HW_TRACE ((me, "invalid MMR %s to 0x%08lx length %u", 47 write ? "write" : "read", (unsigned long) addr, nr_bytes)); 48 49 /* XXX: is this what hardware does ? */ 50 if (addr >= BFIN_CORE_MMR_BASE) 51 /* XXX: This should be setting up CPLB fault addrs ? */ 52 mmu_process_fault (cpu, addr, write, false, false, true); 53 else 54 /* XXX: Newer parts set up an interrupt from EBIU and program 55 EBIU_ERRADDR with the address. */ 56 cec_hwerr (cpu, HWERR_SYSTEM_MMR); 57 } 58 59 void 60 dv_bfin_mmr_invalid (struct hw *me, address_word addr, unsigned nr_bytes, 61 bool write) 62 { 63 bfin_mmr_invalid (me, NULL, addr, nr_bytes, write); 64 } 65 66 void 67 dv_bfin_mmr_require (struct hw *me, address_word addr, unsigned nr_bytes, 68 unsigned size, bool write) 69 { 70 if (nr_bytes != size) 71 dv_bfin_mmr_invalid (me, addr, nr_bytes, write); 72 } 73 74 static bool 75 bfin_mmr_check (struct hw *me, SIM_CPU *cpu, address_word addr, 76 unsigned nr_bytes, bool write) 77 { 78 if (addr >= BFIN_CORE_MMR_BASE) 79 { 80 /* All Core MMRs are aligned 32bits. */ 81 if ((addr & 3) == 0 && nr_bytes == 4) 82 return true; 83 } 84 else if (addr >= BFIN_SYSTEM_MMR_BASE) 85 { 86 /* All System MMRs are 32bit aligned, but can be 16bits or 32bits. */ 87 if ((addr & 0x3) == 0 && (nr_bytes == 2 || nr_bytes == 4)) 88 return true; 89 } 90 else 91 return true; 92 93 /* Still here ? Must be crap. */ 94 bfin_mmr_invalid (me, cpu, addr, nr_bytes, write); 95 96 return false; 97 } 98 99 bool 100 dv_bfin_mmr_check (struct hw *me, address_word addr, unsigned nr_bytes, 101 bool write) 102 { 103 return bfin_mmr_check (me, NULL, addr, nr_bytes, write); 104 } 105 106 int 107 device_io_read_buffer (device *me, void *source, int space, 108 address_word addr, unsigned nr_bytes, 109 SIM_DESC sd, SIM_CPU *cpu, sim_cia cia) 110 { 111 struct hw *dv_me = (struct hw *) me; 112 113 if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) 114 return nr_bytes; 115 116 if (bfin_mmr_check (dv_me, cpu, addr, nr_bytes, false)) 117 if (cpu) 118 { 119 sim_cpu_hw_io_read_buffer (cpu, cia, dv_me, source, space, 120 addr, nr_bytes); 121 return nr_bytes; 122 } 123 else 124 return sim_hw_io_read_buffer (sd, dv_me, source, space, addr, nr_bytes); 125 else 126 return 0; 127 } 128 129 int 130 device_io_write_buffer (device *me, const void *source, int space, 131 address_word addr, unsigned nr_bytes, 132 SIM_DESC sd, SIM_CPU *cpu, sim_cia cia) 133 { 134 struct hw *dv_me = (struct hw *) me; 135 136 if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) 137 return nr_bytes; 138 139 if (bfin_mmr_check (dv_me, cpu, addr, nr_bytes, true)) 140 if (cpu) 141 { 142 sim_cpu_hw_io_write_buffer (cpu, cia, dv_me, source, space, 143 addr, nr_bytes); 144 return nr_bytes; 145 } 146 else 147 return sim_hw_io_write_buffer (sd, dv_me, source, space, addr, nr_bytes); 148 else 149 return 0; 150 } 151 152 void device_error (device *me, const char *message, ...) 153 { 154 /* Don't bother doing anything here -- any place in common code that 155 calls device_error() follows it with sim_hw_abort(). Since the 156 device isn't bound to the system yet, we can't call any common 157 hardware error funcs on it or we'll hit a NULL pointer. */ 158 } 159 160 unsigned int dv_get_bus_num (struct hw *me) 161 { 162 const hw_unit *unit = hw_unit_address (me); 163 return unit->cells[unit->nr_cells - 1]; 164 } 165