1 /* 2 * QEMU model of the Xilinx timer block. 3 * 4 * Copyright (c) 2009 Edgar E. Iglesias. 5 * 6 * DS573: https://docs.amd.com/v/u/en-US/xps_timer 7 * LogiCORE IP XPS Timer/Counter (v1.02a) 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * of this software and associated documentation files (the "Software"), to deal 11 * in the Software without restriction, including without limitation the rights 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 * copies of the Software, and to permit persons to whom the Software is 14 * furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 * THE SOFTWARE. 26 */ 27 28 #include "qemu/osdep.h" 29 #include "qapi/error.h" 30 #include "hw/sysbus.h" 31 #include "hw/irq.h" 32 #include "hw/ptimer.h" 33 #include "hw/qdev-properties.h" 34 #include "hw/qdev-properties-system.h" 35 #include "qemu/log.h" 36 #include "qemu/module.h" 37 #include "qom/object.h" 38 39 #define D(x) 40 41 #define R_TCSR 0 42 #define R_TLR 1 43 #define R_TCR 2 44 #define R_MAX 4 45 46 #define TCSR_MDT (1<<0) 47 #define TCSR_UDT (1<<1) 48 #define TCSR_GENT (1<<2) 49 #define TCSR_CAPT (1<<3) 50 #define TCSR_ARHT (1<<4) 51 #define TCSR_LOAD (1<<5) 52 #define TCSR_ENIT (1<<6) 53 #define TCSR_ENT (1<<7) 54 #define TCSR_TINT (1<<8) 55 #define TCSR_PWMA (1<<9) 56 #define TCSR_ENALL (1<<10) 57 58 struct xlx_timer 59 { 60 ptimer_state *ptimer; 61 void *parent; 62 int nr; /* for debug. */ 63 64 unsigned long timer_div; 65 66 uint32_t regs[R_MAX]; 67 }; 68 69 #define TYPE_XILINX_TIMER "xlnx.xps-timer" 70 typedef struct XpsTimerState XpsTimerState; 71 DECLARE_INSTANCE_CHECKER(XpsTimerState, XILINX_TIMER, TYPE_XILINX_TIMER) 72 73 struct XpsTimerState 74 { 75 SysBusDevice parent_obj; 76 77 EndianMode model_endianness; 78 MemoryRegion mmio; 79 qemu_irq irq; 80 uint8_t one_timer_only; 81 uint32_t freq_hz; 82 struct xlx_timer *timers; 83 }; 84 85 static inline unsigned int num_timers(XpsTimerState *t) 86 { 87 return 2 - t->one_timer_only; 88 } 89 90 static inline unsigned int timer_from_addr(hwaddr addr) 91 { 92 /* Timers get a 4x32bit control reg area each. */ 93 return addr >> 2; 94 } 95 96 static void timer_update_irq(XpsTimerState *t) 97 { 98 unsigned int i, irq = 0; 99 uint32_t csr; 100 101 for (i = 0; i < num_timers(t); i++) { 102 csr = t->timers[i].regs[R_TCSR]; 103 irq |= (csr & TCSR_TINT) && (csr & TCSR_ENIT); 104 } 105 106 /* All timers within the same slave share a single IRQ line. */ 107 qemu_set_irq(t->irq, !!irq); 108 } 109 110 static uint64_t 111 timer_read(void *opaque, hwaddr addr, unsigned int size) 112 { 113 XpsTimerState *t = opaque; 114 struct xlx_timer *xt; 115 uint32_t r = 0; 116 unsigned int timer; 117 118 addr >>= 2; 119 timer = timer_from_addr(addr); 120 xt = &t->timers[timer]; 121 /* Further decoding to address a specific timers reg. */ 122 addr &= 0x3; 123 switch (addr) 124 { 125 case R_TCR: 126 r = ptimer_get_count(xt->ptimer); 127 if (!(xt->regs[R_TCSR] & TCSR_UDT)) 128 r = ~r; 129 D(qemu_log("xlx_timer t=%d read counter=%x udt=%d\n", 130 timer, r, xt->regs[R_TCSR] & TCSR_UDT)); 131 break; 132 default: 133 if (addr < ARRAY_SIZE(xt->regs)) 134 r = xt->regs[addr]; 135 break; 136 137 } 138 D(fprintf(stderr, "%s timer=%d %x=%x\n", __func__, timer, addr * 4, r)); 139 return r; 140 } 141 142 /* Must be called inside ptimer transaction block */ 143 static void timer_enable(struct xlx_timer *xt) 144 { 145 uint64_t count; 146 147 D(fprintf(stderr, "%s timer=%d down=%d\n", __func__, 148 xt->nr, xt->regs[R_TCSR] & TCSR_UDT)); 149 150 ptimer_stop(xt->ptimer); 151 152 if (xt->regs[R_TCSR] & TCSR_UDT) 153 count = xt->regs[R_TLR]; 154 else 155 count = ~0 - xt->regs[R_TLR]; 156 ptimer_set_limit(xt->ptimer, count, 1); 157 ptimer_run(xt->ptimer, 1); 158 } 159 160 static void 161 timer_write(void *opaque, hwaddr addr, 162 uint64_t val64, unsigned int size) 163 { 164 XpsTimerState *t = opaque; 165 struct xlx_timer *xt; 166 unsigned int timer; 167 uint32_t value = val64; 168 169 addr >>= 2; 170 timer = timer_from_addr(addr); 171 xt = &t->timers[timer]; 172 D(fprintf(stderr, "%s addr=%x val=%x (timer=%d off=%d)\n", 173 __func__, addr * 4, value, timer, addr & 3)); 174 /* Further decoding to address a specific timers reg. */ 175 addr &= 3; 176 switch (addr) 177 { 178 case R_TCSR: 179 if (value & TCSR_TINT) 180 value &= ~TCSR_TINT; 181 182 xt->regs[addr] = value & 0x7ff; 183 if (value & TCSR_ENT) { 184 ptimer_transaction_begin(xt->ptimer); 185 timer_enable(xt); 186 ptimer_transaction_commit(xt->ptimer); 187 } 188 break; 189 190 default: 191 if (addr < ARRAY_SIZE(xt->regs)) 192 xt->regs[addr] = value; 193 break; 194 } 195 timer_update_irq(t); 196 } 197 198 static const MemoryRegionOps timer_ops[2] = { 199 [0 ... 1] = { 200 .read = timer_read, 201 .write = timer_write, 202 .impl = { 203 .min_access_size = 4, 204 .max_access_size = 4, 205 }, 206 .valid = { 207 .min_access_size = 4, 208 .max_access_size = 4, 209 }, 210 }, 211 [0].endianness = DEVICE_LITTLE_ENDIAN, 212 [1].endianness = DEVICE_BIG_ENDIAN, 213 }; 214 215 static void timer_hit(void *opaque) 216 { 217 struct xlx_timer *xt = opaque; 218 XpsTimerState *t = xt->parent; 219 D(fprintf(stderr, "%s %d\n", __func__, xt->nr)); 220 xt->regs[R_TCSR] |= TCSR_TINT; 221 222 if (xt->regs[R_TCSR] & TCSR_ARHT) 223 timer_enable(xt); 224 timer_update_irq(t); 225 } 226 227 static void xilinx_timer_realize(DeviceState *dev, Error **errp) 228 { 229 XpsTimerState *t = XILINX_TIMER(dev); 230 unsigned int i; 231 232 if (t->model_endianness == ENDIAN_MODE_UNSPECIFIED) { 233 error_setg(errp, TYPE_XILINX_TIMER " property 'endianness'" 234 " must be set to 'big' or 'little'"); 235 return; 236 } 237 238 /* Init all the ptimers. */ 239 t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t)); 240 for (i = 0; i < num_timers(t); i++) { 241 struct xlx_timer *xt = &t->timers[i]; 242 243 xt->parent = t; 244 xt->nr = i; 245 xt->ptimer = ptimer_init(timer_hit, xt, PTIMER_POLICY_LEGACY); 246 ptimer_transaction_begin(xt->ptimer); 247 ptimer_set_freq(xt->ptimer, t->freq_hz); 248 ptimer_transaction_commit(xt->ptimer); 249 } 250 251 memory_region_init_io(&t->mmio, OBJECT(t), 252 &timer_ops[t->model_endianness == ENDIAN_MODE_BIG], 253 t, "xlnx.xps-timer", R_MAX * 4 * num_timers(t)); 254 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio); 255 } 256 257 static void xilinx_timer_init(Object *obj) 258 { 259 XpsTimerState *t = XILINX_TIMER(obj); 260 261 /* All timers share a single irq line. */ 262 sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq); 263 } 264 265 static const Property xilinx_timer_properties[] = { 266 DEFINE_PROP_ENDIAN_NODEFAULT("endianness", XpsTimerState, model_endianness), 267 DEFINE_PROP_UINT32("clock-frequency", XpsTimerState, freq_hz, 62 * 1000000), 268 DEFINE_PROP_UINT8("one-timer-only", XpsTimerState, one_timer_only, 0), 269 }; 270 271 static void xilinx_timer_class_init(ObjectClass *klass, const void *data) 272 { 273 DeviceClass *dc = DEVICE_CLASS(klass); 274 275 dc->realize = xilinx_timer_realize; 276 device_class_set_props(dc, xilinx_timer_properties); 277 } 278 279 static const TypeInfo xilinx_timer_info = { 280 .name = TYPE_XILINX_TIMER, 281 .parent = TYPE_SYS_BUS_DEVICE, 282 .instance_size = sizeof(XpsTimerState), 283 .instance_init = xilinx_timer_init, 284 .class_init = xilinx_timer_class_init, 285 }; 286 287 static void xilinx_timer_register_types(void) 288 { 289 type_register_static(&xilinx_timer_info); 290 } 291 292 type_init(xilinx_timer_register_types) 293