1 /* Blackfin device support. 2 3 Copyright (C) 2010-2011 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 "dv-bfin_cec.h" 27 #include "dv-bfin_mmu.h" 28 29 static void 30 bfin_mmr_invalid (struct hw *me, SIM_CPU *cpu, address_word addr, 31 unsigned nr_bytes, bool write) 32 { 33 if (!cpu) 34 cpu = hw_system_cpu (me); 35 36 /* Only throw a fit if the cpu is doing the access. DMA/GDB simply 37 go unnoticed. Not exactly hardware behavior, but close enough. */ 38 if (!cpu) 39 { 40 sim_io_eprintf (hw_system (me), "%s: invalid MMR access @ %#x\n", 41 hw_path (me), addr); 42 return; 43 } 44 45 HW_TRACE ((me, "invalid MMR %s to 0x%08lx length %u", 46 write ? "write" : "read", (unsigned long) addr, nr_bytes)); 47 48 /* XXX: is this what hardware does ? */ 49 if (addr >= BFIN_CORE_MMR_BASE) 50 /* XXX: This should be setting up CPLB fault addrs ? */ 51 mmu_process_fault (cpu, addr, write, false, false, true); 52 else 53 /* XXX: Newer parts set up an interrupt from EBIU and program 54 EBIU_ERRADDR with the address. */ 55 cec_hwerr (cpu, HWERR_SYSTEM_MMR); 56 } 57 58 void 59 dv_bfin_mmr_invalid (struct hw *me, address_word addr, unsigned nr_bytes, 60 bool write) 61 { 62 bfin_mmr_invalid (me, NULL, addr, nr_bytes, write); 63 } 64 65 void 66 dv_bfin_mmr_require (struct hw *me, address_word addr, unsigned nr_bytes, 67 unsigned size, bool write) 68 { 69 if (nr_bytes != size) 70 dv_bfin_mmr_invalid (me, addr, nr_bytes, write); 71 } 72 73 static bool 74 bfin_mmr_check (struct hw *me, SIM_CPU *cpu, address_word addr, 75 unsigned nr_bytes, bool write) 76 { 77 if (addr >= BFIN_CORE_MMR_BASE) 78 { 79 /* All Core MMRs are aligned 32bits. */ 80 if ((addr & 3) == 0 && nr_bytes == 4) 81 return true; 82 } 83 else if (addr >= BFIN_SYSTEM_MMR_BASE) 84 { 85 /* All System MMRs are 32bit aligned, but can be 16bits or 32bits. */ 86 if ((addr & 0x3) == 0 && (nr_bytes == 2 || nr_bytes == 4)) 87 return true; 88 } 89 else 90 return true; 91 92 /* Still here ? Must be crap. */ 93 bfin_mmr_invalid (me, cpu, addr, nr_bytes, write); 94 95 return false; 96 } 97 98 bool 99 dv_bfin_mmr_check (struct hw *me, address_word addr, unsigned nr_bytes, 100 bool write) 101 { 102 return bfin_mmr_check (me, NULL, addr, nr_bytes, write); 103 } 104 105 int 106 device_io_read_buffer (device *me, void *source, int space, 107 address_word addr, unsigned nr_bytes, 108 SIM_DESC sd, SIM_CPU *cpu, sim_cia cia) 109 { 110 struct hw *dv_me = (struct hw *) me; 111 112 if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) 113 return nr_bytes; 114 115 if (bfin_mmr_check (dv_me, cpu, addr, nr_bytes, false)) 116 if (cpu) 117 { 118 sim_cpu_hw_io_read_buffer (cpu, cia, dv_me, source, space, 119 addr, nr_bytes); 120 return nr_bytes; 121 } 122 else 123 return sim_hw_io_read_buffer (sd, dv_me, source, space, addr, nr_bytes); 124 else 125 return 0; 126 } 127 128 int 129 device_io_write_buffer (device *me, const void *source, int space, 130 address_word addr, unsigned nr_bytes, 131 SIM_DESC sd, SIM_CPU *cpu, sim_cia cia) 132 { 133 struct hw *dv_me = (struct hw *) me; 134 135 if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) 136 return nr_bytes; 137 138 if (bfin_mmr_check (dv_me, cpu, addr, nr_bytes, true)) 139 if (cpu) 140 { 141 sim_cpu_hw_io_write_buffer (cpu, cia, dv_me, source, space, 142 addr, nr_bytes); 143 return nr_bytes; 144 } 145 else 146 return sim_hw_io_write_buffer (sd, dv_me, source, space, addr, nr_bytes); 147 else 148 return 0; 149 } 150 151 void device_error (device *me, const char *message, ...) 152 { 153 /* Don't bother doing anything here -- any place in common code that 154 calls device_error() follows it with sim_hw_abort(). Since the 155 device isn't bound to the system yet, we can't call any common 156 hardware error funcs on it or we'll hit a NULL pointer. */ 157 } 158 159 unsigned int dv_get_bus_num (struct hw *me) 160 { 161 const hw_unit *unit = hw_unit_address (me); 162 return unit->cells[unit->nr_cells - 1]; 163 } 164