rx_icu.c (10748B)
1/* 2 * RX Interrupt Control Unit 3 * 4 * Warning: Only ICUa is supported. 5 * 6 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware 7 * (Rev.1.40 R01UH0033EJ0140) 8 * 9 * Copyright (c) 2019 Yoshinori Sato 10 * 11 * SPDX-License-Identifier: GPL-2.0-or-later 12 * 13 * This program is free software; you can redistribute it and/or modify it 14 * under the terms and conditions of the GNU General Public License, 15 * version 2 or later, as published by the Free Software Foundation. 16 * 17 * This program is distributed in the hope it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20 * more details. 21 * 22 * You should have received a copy of the GNU General Public License along with 23 * this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26#include "qemu/osdep.h" 27#include "qemu/log.h" 28#include "qemu/error-report.h" 29#include "hw/irq.h" 30#include "hw/registerfields.h" 31#include "hw/qdev-properties.h" 32#include "hw/intc/rx_icu.h" 33#include "migration/vmstate.h" 34 35REG8(IR, 0) 36 FIELD(IR, IR, 0, 1) 37REG8(DTCER, 0x100) 38 FIELD(DTCER, DTCE, 0, 1) 39REG8(IER, 0x200) 40REG8(SWINTR, 0x2e0) 41 FIELD(SWINTR, SWINT, 0, 1) 42REG16(FIR, 0x2f0) 43 FIELD(FIR, FVCT, 0, 8) 44 FIELD(FIR, FIEN, 15, 1) 45REG8(IPR, 0x300) 46 FIELD(IPR, IPR, 0, 4) 47REG8(DMRSR, 0x400) 48REG8(IRQCR, 0x500) 49 FIELD(IRQCR, IRQMD, 2, 2) 50REG8(NMISR, 0x580) 51 FIELD(NMISR, NMIST, 0, 1) 52 FIELD(NMISR, LVDST, 1, 1) 53 FIELD(NMISR, OSTST, 2, 1) 54REG8(NMIER, 0x581) 55 FIELD(NMIER, NMIEN, 0, 1) 56 FIELD(NMIER, LVDEN, 1, 1) 57 FIELD(NMIER, OSTEN, 2, 1) 58REG8(NMICLR, 0x582) 59 FIELD(NMICLR, NMICLR, 0, 1) 60 FIELD(NMICLR, OSTCLR, 2, 1) 61REG8(NMICR, 0x583) 62 FIELD(NMICR, NMIMD, 3, 1) 63 64static void set_irq(RXICUState *icu, int n_IRQ, int req) 65{ 66 if ((icu->fir & R_FIR_FIEN_MASK) && 67 (icu->fir & R_FIR_FVCT_MASK) == n_IRQ) { 68 qemu_set_irq(icu->_fir, req); 69 } else { 70 qemu_set_irq(icu->_irq, req); 71 } 72} 73 74static uint16_t rxicu_level(RXICUState *icu, unsigned n) 75{ 76 return (icu->ipr[icu->map[n]] << 8) | n; 77} 78 79static void rxicu_request(RXICUState *icu, int n_IRQ) 80{ 81 int enable; 82 83 enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7)); 84 if (n_IRQ > 0 && enable != 0 && qatomic_read(&icu->req_irq) < 0) { 85 qatomic_set(&icu->req_irq, n_IRQ); 86 set_irq(icu, n_IRQ, rxicu_level(icu, n_IRQ)); 87 } 88} 89 90static void rxicu_set_irq(void *opaque, int n_IRQ, int level) 91{ 92 RXICUState *icu = opaque; 93 struct IRQSource *src; 94 int issue; 95 96 if (n_IRQ >= NR_IRQS) { 97 error_report("%s: IRQ %d out of range", __func__, n_IRQ); 98 return; 99 } 100 101 src = &icu->src[n_IRQ]; 102 103 level = (level != 0); 104 switch (src->sense) { 105 case TRG_LEVEL: 106 /* level-sensitive irq */ 107 issue = level; 108 src->level = level; 109 break; 110 case TRG_NEDGE: 111 issue = (level == 0 && src->level == 1); 112 src->level = level; 113 break; 114 case TRG_PEDGE: 115 issue = (level == 1 && src->level == 0); 116 src->level = level; 117 break; 118 case TRG_BEDGE: 119 issue = ((level ^ src->level) & 1); 120 src->level = level; 121 break; 122 default: 123 g_assert_not_reached(); 124 } 125 if (issue == 0 && src->sense == TRG_LEVEL) { 126 icu->ir[n_IRQ] = 0; 127 if (qatomic_read(&icu->req_irq) == n_IRQ) { 128 /* clear request */ 129 set_irq(icu, n_IRQ, 0); 130 qatomic_set(&icu->req_irq, -1); 131 } 132 return; 133 } 134 if (issue) { 135 icu->ir[n_IRQ] = 1; 136 rxicu_request(icu, n_IRQ); 137 } 138} 139 140static void rxicu_ack_irq(void *opaque, int no, int level) 141{ 142 RXICUState *icu = opaque; 143 int i; 144 int n_IRQ; 145 int max_pri; 146 147 n_IRQ = qatomic_read(&icu->req_irq); 148 if (n_IRQ < 0) { 149 return; 150 } 151 qatomic_set(&icu->req_irq, -1); 152 if (icu->src[n_IRQ].sense != TRG_LEVEL) { 153 icu->ir[n_IRQ] = 0; 154 } 155 156 max_pri = 0; 157 n_IRQ = -1; 158 for (i = 0; i < NR_IRQS; i++) { 159 if (icu->ir[i]) { 160 if (max_pri < icu->ipr[icu->map[i]]) { 161 n_IRQ = i; 162 max_pri = icu->ipr[icu->map[i]]; 163 } 164 } 165 } 166 167 if (n_IRQ >= 0) { 168 rxicu_request(icu, n_IRQ); 169 } 170} 171 172static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size) 173{ 174 RXICUState *icu = opaque; 175 int reg = addr & 0xff; 176 177 if ((addr != A_FIR && size != 1) || 178 (addr == A_FIR && size != 2)) { 179 qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid read size 0x%" 180 HWADDR_PRIX "\n", 181 addr); 182 return UINT64_MAX; 183 } 184 switch (addr) { 185 case A_IR ... A_IR + 0xff: 186 return icu->ir[reg] & R_IR_IR_MASK; 187 case A_DTCER ... A_DTCER + 0xff: 188 return icu->dtcer[reg] & R_DTCER_DTCE_MASK; 189 case A_IER ... A_IER + 0x1f: 190 return icu->ier[reg]; 191 case A_SWINTR: 192 return 0; 193 case A_FIR: 194 return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); 195 case A_IPR ... A_IPR + 0x8f: 196 return icu->ipr[reg] & R_IPR_IPR_MASK; 197 case A_DMRSR: 198 case A_DMRSR + 4: 199 case A_DMRSR + 8: 200 case A_DMRSR + 12: 201 return icu->dmasr[reg >> 2]; 202 case A_IRQCR ... A_IRQCR + 0x1f: 203 return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT; 204 case A_NMISR: 205 case A_NMICLR: 206 return 0; 207 case A_NMIER: 208 return icu->nmier; 209 case A_NMICR: 210 return icu->nmicr; 211 default: 212 qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX " " 213 "not implemented.\n", 214 addr); 215 break; 216 } 217 return UINT64_MAX; 218} 219 220static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 221{ 222 RXICUState *icu = opaque; 223 int reg = addr & 0xff; 224 225 if ((addr != A_FIR && size != 1) || 226 (addr == A_FIR && size != 2)) { 227 qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at " 228 "0x%" HWADDR_PRIX "\n", 229 addr); 230 return; 231 } 232 switch (addr) { 233 case A_IR ... A_IR + 0xff: 234 if (icu->src[reg].sense != TRG_LEVEL && val == 0) { 235 icu->ir[reg] = 0; 236 } 237 break; 238 case A_DTCER ... A_DTCER + 0xff: 239 icu->dtcer[reg] = val & R_DTCER_DTCE_MASK; 240 qemu_log_mask(LOG_UNIMP, "rx_icu: DTC not implemented\n"); 241 break; 242 case A_IER ... A_IER + 0x1f: 243 icu->ier[reg] = val; 244 break; 245 case A_SWINTR: 246 if (val & R_SWINTR_SWINT_MASK) { 247 qemu_irq_pulse(icu->_swi); 248 } 249 break; 250 case A_FIR: 251 icu->fir = val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); 252 break; 253 case A_IPR ... A_IPR + 0x8f: 254 icu->ipr[reg] = val & R_IPR_IPR_MASK; 255 break; 256 case A_DMRSR: 257 case A_DMRSR + 4: 258 case A_DMRSR + 8: 259 case A_DMRSR + 12: 260 icu->dmasr[reg >> 2] = val; 261 qemu_log_mask(LOG_UNIMP, "rx_icu: DMAC not implemented\n"); 262 break; 263 case A_IRQCR ... A_IRQCR + 0x1f: 264 icu->src[64 + reg].sense = val >> R_IRQCR_IRQMD_SHIFT; 265 break; 266 case A_NMICLR: 267 break; 268 case A_NMIER: 269 icu->nmier |= val & (R_NMIER_NMIEN_MASK | 270 R_NMIER_LVDEN_MASK | 271 R_NMIER_OSTEN_MASK); 272 break; 273 case A_NMICR: 274 if ((icu->nmier & R_NMIER_NMIEN_MASK) == 0) { 275 icu->nmicr = val & R_NMICR_NMIMD_MASK; 276 } 277 break; 278 default: 279 qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX " " 280 "not implemented\n", 281 addr); 282 break; 283 } 284} 285 286static const MemoryRegionOps icu_ops = { 287 .write = icu_write, 288 .read = icu_read, 289 .endianness = DEVICE_LITTLE_ENDIAN, 290 .impl = { 291 .min_access_size = 1, 292 .max_access_size = 2, 293 }, 294 .valid = { 295 .min_access_size = 1, 296 .max_access_size = 2, 297 }, 298}; 299 300static void rxicu_realize(DeviceState *dev, Error **errp) 301{ 302 RXICUState *icu = RX_ICU(dev); 303 int i; 304 305 if (icu->init_sense == NULL) { 306 qemu_log_mask(LOG_GUEST_ERROR, 307 "rx_icu: trigger-level property must be set."); 308 return; 309 } 310 311 for (i = 0; i < NR_IRQS; i++) { 312 icu->src[i].sense = TRG_PEDGE; 313 } 314 for (i = 0; i < icu->nr_sense; i++) { 315 uint8_t irqno = icu->init_sense[i]; 316 icu->src[irqno].sense = TRG_LEVEL; 317 } 318 icu->req_irq = -1; 319} 320 321static void rxicu_init(Object *obj) 322{ 323 SysBusDevice *d = SYS_BUS_DEVICE(obj); 324 RXICUState *icu = RX_ICU(obj); 325 326 memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops, 327 icu, "rx-icu", 0x600); 328 sysbus_init_mmio(d, &icu->memory); 329 330 qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS); 331 qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1); 332 sysbus_init_irq(d, &icu->_irq); 333 sysbus_init_irq(d, &icu->_fir); 334 sysbus_init_irq(d, &icu->_swi); 335} 336 337static void rxicu_fini(Object *obj) 338{ 339 RXICUState *icu = RX_ICU(obj); 340 g_free(icu->map); 341 g_free(icu->init_sense); 342} 343 344static const VMStateDescription vmstate_rxicu = { 345 .name = "rx-icu", 346 .version_id = 1, 347 .minimum_version_id = 1, 348 .fields = (VMStateField[]) { 349 VMSTATE_UINT8_ARRAY(ir, RXICUState, NR_IRQS), 350 VMSTATE_UINT8_ARRAY(dtcer, RXICUState, NR_IRQS), 351 VMSTATE_UINT8_ARRAY(ier, RXICUState, NR_IRQS / 8), 352 VMSTATE_UINT8_ARRAY(ipr, RXICUState, 142), 353 VMSTATE_UINT8_ARRAY(dmasr, RXICUState, 4), 354 VMSTATE_UINT16(fir, RXICUState), 355 VMSTATE_UINT8(nmisr, RXICUState), 356 VMSTATE_UINT8(nmier, RXICUState), 357 VMSTATE_UINT8(nmiclr, RXICUState), 358 VMSTATE_UINT8(nmicr, RXICUState), 359 VMSTATE_INT16(req_irq, RXICUState), 360 VMSTATE_END_OF_LIST() 361 } 362}; 363 364static Property rxicu_properties[] = { 365 DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map, 366 qdev_prop_uint8, uint8_t), 367 DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense, 368 qdev_prop_uint8, uint8_t), 369 DEFINE_PROP_END_OF_LIST(), 370}; 371 372static void rxicu_class_init(ObjectClass *klass, void *data) 373{ 374 DeviceClass *dc = DEVICE_CLASS(klass); 375 376 dc->realize = rxicu_realize; 377 dc->vmsd = &vmstate_rxicu; 378 device_class_set_props(dc, rxicu_properties); 379} 380 381static const TypeInfo rxicu_info = { 382 .name = TYPE_RX_ICU, 383 .parent = TYPE_SYS_BUS_DEVICE, 384 .instance_size = sizeof(RXICUState), 385 .instance_init = rxicu_init, 386 .instance_finalize = rxicu_fini, 387 .class_init = rxicu_class_init, 388}; 389 390static void rxicu_register_types(void) 391{ 392 type_register_static(&rxicu_info); 393} 394 395type_init(rxicu_register_types)