| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * RX Interrupt Control Unit | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Warning: Only ICUa is supported. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware | 
					
						
							|  |  |  |  *            (Rev.1.40 R01UH0033EJ0140) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2019 Yoshinori Sato | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: GPL-2.0-or-later | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify it | 
					
						
							|  |  |  |  * under the terms and conditions of the GNU General Public License, | 
					
						
							|  |  |  |  * version 2 or later, as published by the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope it will be useful, but WITHOUT | 
					
						
							|  |  |  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | 
					
						
							|  |  |  |  * more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License along with | 
					
						
							|  |  |  |  * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "qemu/osdep.h"
 | 
					
						
							|  |  |  | #include "qemu/log.h"
 | 
					
						
							|  |  |  | #include "qemu/error-report.h"
 | 
					
						
							|  |  |  | #include "hw/irq.h"
 | 
					
						
							|  |  |  | #include "hw/registerfields.h"
 | 
					
						
							|  |  |  | #include "hw/qdev-properties.h"
 | 
					
						
							|  |  |  | #include "hw/intc/rx_icu.h"
 | 
					
						
							|  |  |  | #include "migration/vmstate.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | REG8(IR, 0) | 
					
						
							|  |  |  |   FIELD(IR, IR,  0, 1) | 
					
						
							|  |  |  | REG8(DTCER, 0x100) | 
					
						
							|  |  |  |   FIELD(DTCER, DTCE,  0, 1) | 
					
						
							|  |  |  | REG8(IER, 0x200) | 
					
						
							|  |  |  | REG8(SWINTR, 0x2e0) | 
					
						
							|  |  |  |   FIELD(SWINTR, SWINT, 0, 1) | 
					
						
							|  |  |  | REG16(FIR, 0x2f0) | 
					
						
							|  |  |  |   FIELD(FIR, FVCT, 0,  8) | 
					
						
							|  |  |  |   FIELD(FIR, FIEN, 15, 1) | 
					
						
							|  |  |  | REG8(IPR, 0x300) | 
					
						
							|  |  |  |   FIELD(IPR, IPR, 0, 4) | 
					
						
							|  |  |  | REG8(DMRSR, 0x400) | 
					
						
							|  |  |  | REG8(IRQCR, 0x500) | 
					
						
							|  |  |  |   FIELD(IRQCR, IRQMD, 2, 2) | 
					
						
							|  |  |  | REG8(NMISR, 0x580) | 
					
						
							|  |  |  |   FIELD(NMISR, NMIST, 0, 1) | 
					
						
							|  |  |  |   FIELD(NMISR, LVDST, 1, 1) | 
					
						
							|  |  |  |   FIELD(NMISR, OSTST, 2, 1) | 
					
						
							|  |  |  | REG8(NMIER, 0x581) | 
					
						
							|  |  |  |   FIELD(NMIER, NMIEN, 0, 1) | 
					
						
							|  |  |  |   FIELD(NMIER, LVDEN, 1, 1) | 
					
						
							|  |  |  |   FIELD(NMIER, OSTEN, 2, 1) | 
					
						
							|  |  |  | REG8(NMICLR, 0x582) | 
					
						
							|  |  |  |   FIELD(NMICLR, NMICLR, 0, 1) | 
					
						
							|  |  |  |   FIELD(NMICLR, OSTCLR, 2, 1) | 
					
						
							|  |  |  | REG8(NMICR, 0x583) | 
					
						
							|  |  |  |   FIELD(NMICR, NMIMD, 3, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void set_irq(RXICUState *icu, int n_IRQ, int req) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if ((icu->fir & R_FIR_FIEN_MASK) && | 
					
						
							|  |  |  |         (icu->fir & R_FIR_FVCT_MASK) == n_IRQ) { | 
					
						
							|  |  |  |         qemu_set_irq(icu->_fir, req); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         qemu_set_irq(icu->_irq, req); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint16_t rxicu_level(RXICUState *icu, unsigned n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return (icu->ipr[icu->map[n]] << 8) | n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_request(RXICUState *icu, int n_IRQ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int enable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7)); | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     if (n_IRQ > 0 && enable != 0 && qatomic_read(&icu->req_irq) < 0) { | 
					
						
							|  |  |  |         qatomic_set(&icu->req_irq, n_IRQ); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  |         set_irq(icu, n_IRQ, rxicu_level(icu, n_IRQ)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_set_irq(void *opaque, int n_IRQ, int level) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RXICUState *icu = opaque; | 
					
						
							|  |  |  |     struct IRQSource *src; | 
					
						
							|  |  |  |     int issue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (n_IRQ >= NR_IRQS) { | 
					
						
							|  |  |  |         error_report("%s: IRQ %d out of range", __func__, n_IRQ); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     src = &icu->src[n_IRQ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     level = (level != 0); | 
					
						
							|  |  |  |     switch (src->sense) { | 
					
						
							|  |  |  |     case TRG_LEVEL: | 
					
						
							|  |  |  |         /* level-sensitive irq */ | 
					
						
							|  |  |  |         issue = level; | 
					
						
							|  |  |  |         src->level = level; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TRG_NEDGE: | 
					
						
							|  |  |  |         issue = (level == 0 && src->level == 1); | 
					
						
							|  |  |  |         src->level = level; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TRG_PEDGE: | 
					
						
							|  |  |  |         issue = (level == 1 && src->level == 0); | 
					
						
							|  |  |  |         src->level = level; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TRG_BEDGE: | 
					
						
							|  |  |  |         issue = ((level ^ src->level) & 1); | 
					
						
							|  |  |  |         src->level = level; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         g_assert_not_reached(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (issue == 0 && src->sense == TRG_LEVEL) { | 
					
						
							|  |  |  |         icu->ir[n_IRQ] = 0; | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |         if (qatomic_read(&icu->req_irq) == n_IRQ) { | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  |             /* clear request */ | 
					
						
							|  |  |  |             set_irq(icu, n_IRQ, 0); | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |             qatomic_set(&icu->req_irq, -1); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (issue) { | 
					
						
							|  |  |  |         icu->ir[n_IRQ] = 1; | 
					
						
							|  |  |  |         rxicu_request(icu, n_IRQ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_ack_irq(void *opaque, int no, int level) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RXICUState *icu = opaque; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     int n_IRQ; | 
					
						
							|  |  |  |     int max_pri; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     n_IRQ = qatomic_read(&icu->req_irq); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  |     if (n_IRQ < 0) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     qatomic_set(&icu->req_irq, -1); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  |     if (icu->src[n_IRQ].sense != TRG_LEVEL) { | 
					
						
							|  |  |  |         icu->ir[n_IRQ] = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     max_pri = 0; | 
					
						
							|  |  |  |     n_IRQ = -1; | 
					
						
							|  |  |  |     for (i = 0; i < NR_IRQS; i++) { | 
					
						
							|  |  |  |         if (icu->ir[i]) { | 
					
						
							|  |  |  |             if (max_pri < icu->ipr[icu->map[i]]) { | 
					
						
							|  |  |  |                 n_IRQ = i; | 
					
						
							|  |  |  |                 max_pri = icu->ipr[icu->map[i]]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (n_IRQ >= 0) { | 
					
						
							|  |  |  |         rxicu_request(icu, n_IRQ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RXICUState *icu = opaque; | 
					
						
							|  |  |  |     int reg = addr & 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((addr != A_FIR && size != 1) || | 
					
						
							|  |  |  |         (addr == A_FIR && size != 2)) { | 
					
						
							|  |  |  |         qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid read size 0x%" | 
					
						
							|  |  |  |                                        HWADDR_PRIX "\n", | 
					
						
							|  |  |  |                       addr); | 
					
						
							|  |  |  |         return UINT64_MAX; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     switch (addr) { | 
					
						
							|  |  |  |     case A_IR ... A_IR + 0xff: | 
					
						
							|  |  |  |         return icu->ir[reg] & R_IR_IR_MASK; | 
					
						
							|  |  |  |     case A_DTCER ... A_DTCER + 0xff: | 
					
						
							|  |  |  |         return icu->dtcer[reg] & R_DTCER_DTCE_MASK; | 
					
						
							|  |  |  |     case A_IER ... A_IER + 0x1f: | 
					
						
							|  |  |  |         return icu->ier[reg]; | 
					
						
							|  |  |  |     case A_SWINTR: | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     case A_FIR: | 
					
						
							|  |  |  |         return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); | 
					
						
							|  |  |  |     case A_IPR ... A_IPR + 0x8f: | 
					
						
							|  |  |  |         return icu->ipr[reg] & R_IPR_IPR_MASK; | 
					
						
							|  |  |  |     case A_DMRSR: | 
					
						
							|  |  |  |     case A_DMRSR + 4: | 
					
						
							|  |  |  |     case A_DMRSR + 8: | 
					
						
							|  |  |  |     case A_DMRSR + 12: | 
					
						
							|  |  |  |         return icu->dmasr[reg >> 2]; | 
					
						
							|  |  |  |     case A_IRQCR ... A_IRQCR + 0x1f: | 
					
						
							|  |  |  |         return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT; | 
					
						
							|  |  |  |     case A_NMISR: | 
					
						
							|  |  |  |     case A_NMICLR: | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     case A_NMIER: | 
					
						
							|  |  |  |         return icu->nmier; | 
					
						
							|  |  |  |     case A_NMICR: | 
					
						
							|  |  |  |         return icu->nmicr; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX " " | 
					
						
							|  |  |  |                                  "not implemented.\n", | 
					
						
							|  |  |  |                       addr); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return UINT64_MAX; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RXICUState *icu = opaque; | 
					
						
							|  |  |  |     int reg = addr & 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((addr != A_FIR && size != 1) || | 
					
						
							|  |  |  |         (addr == A_FIR && size != 2)) { | 
					
						
							|  |  |  |         qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at " | 
					
						
							|  |  |  |                                        "0x%" HWADDR_PRIX "\n", | 
					
						
							|  |  |  |                       addr); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     switch (addr) { | 
					
						
							|  |  |  |     case A_IR ... A_IR + 0xff: | 
					
						
							|  |  |  |         if (icu->src[reg].sense != TRG_LEVEL && val == 0) { | 
					
						
							|  |  |  |             icu->ir[reg] = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_DTCER ... A_DTCER + 0xff: | 
					
						
							|  |  |  |         icu->dtcer[reg] = val & R_DTCER_DTCE_MASK; | 
					
						
							|  |  |  |         qemu_log_mask(LOG_UNIMP, "rx_icu: DTC not implemented\n"); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_IER ... A_IER + 0x1f: | 
					
						
							|  |  |  |         icu->ier[reg] = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_SWINTR: | 
					
						
							|  |  |  |         if (val & R_SWINTR_SWINT_MASK) { | 
					
						
							|  |  |  |             qemu_irq_pulse(icu->_swi); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_FIR: | 
					
						
							|  |  |  |         icu->fir = val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_IPR ... A_IPR + 0x8f: | 
					
						
							|  |  |  |         icu->ipr[reg] = val & R_IPR_IPR_MASK; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_DMRSR: | 
					
						
							|  |  |  |     case A_DMRSR + 4: | 
					
						
							|  |  |  |     case A_DMRSR + 8: | 
					
						
							|  |  |  |     case A_DMRSR + 12: | 
					
						
							|  |  |  |         icu->dmasr[reg >> 2] = val; | 
					
						
							|  |  |  |         qemu_log_mask(LOG_UNIMP, "rx_icu: DMAC not implemented\n"); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_IRQCR ... A_IRQCR + 0x1f: | 
					
						
							|  |  |  |         icu->src[64 + reg].sense = val >> R_IRQCR_IRQMD_SHIFT; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_NMICLR: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_NMIER: | 
					
						
							|  |  |  |         icu->nmier |= val & (R_NMIER_NMIEN_MASK | | 
					
						
							|  |  |  |                              R_NMIER_LVDEN_MASK | | 
					
						
							|  |  |  |                              R_NMIER_OSTEN_MASK); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case A_NMICR: | 
					
						
							|  |  |  |         if ((icu->nmier & R_NMIER_NMIEN_MASK) == 0) { | 
					
						
							|  |  |  |             icu->nmicr = val & R_NMICR_NMIMD_MASK; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX " " | 
					
						
							|  |  |  |                                  "not implemented\n", | 
					
						
							|  |  |  |                       addr); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const MemoryRegionOps icu_ops = { | 
					
						
							|  |  |  |     .write = icu_write, | 
					
						
							|  |  |  |     .read  = icu_read, | 
					
						
							|  |  |  |     .endianness = DEVICE_LITTLE_ENDIAN, | 
					
						
							|  |  |  |     .impl = { | 
					
						
							|  |  |  |         .min_access_size = 1, | 
					
						
							|  |  |  |         .max_access_size = 2, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     .valid = { | 
					
						
							|  |  |  |         .min_access_size = 1, | 
					
						
							|  |  |  |         .max_access_size = 2, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_realize(DeviceState *dev, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RXICUState *icu = RX_ICU(dev); | 
					
						
							| 
									
										
										
										
											2020-11-11 22:17:33 +08:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (icu->init_sense == NULL) { | 
					
						
							|  |  |  |         qemu_log_mask(LOG_GUEST_ERROR, | 
					
						
							|  |  |  |                       "rx_icu: trigger-level property must be set."); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-11 22:17:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < NR_IRQS; i++) { | 
					
						
							|  |  |  |         icu->src[i].sense = TRG_PEDGE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (i = 0; i < icu->nr_sense; i++) { | 
					
						
							|  |  |  |         uint8_t irqno = icu->init_sense[i]; | 
					
						
							|  |  |  |         icu->src[irqno].sense = TRG_LEVEL; | 
					
						
							| 
									
										
										
										
											2019-01-21 22:15:57 +09:00
										 |  |  |     } | 
					
						
							|  |  |  |     icu->req_irq = -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_init(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SysBusDevice *d = SYS_BUS_DEVICE(obj); | 
					
						
							|  |  |  |     RXICUState *icu = RX_ICU(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops, | 
					
						
							|  |  |  |                           icu, "rx-icu", 0x600); | 
					
						
							|  |  |  |     sysbus_init_mmio(d, &icu->memory); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS); | 
					
						
							|  |  |  |     qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1); | 
					
						
							|  |  |  |     sysbus_init_irq(d, &icu->_irq); | 
					
						
							|  |  |  |     sysbus_init_irq(d, &icu->_fir); | 
					
						
							|  |  |  |     sysbus_init_irq(d, &icu->_swi); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_fini(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RXICUState *icu = RX_ICU(obj); | 
					
						
							|  |  |  |     g_free(icu->map); | 
					
						
							|  |  |  |     g_free(icu->init_sense); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const VMStateDescription vmstate_rxicu = { | 
					
						
							|  |  |  |     .name = "rx-icu", | 
					
						
							|  |  |  |     .version_id = 1, | 
					
						
							|  |  |  |     .minimum_version_id = 1, | 
					
						
							|  |  |  |     .fields = (VMStateField[]) { | 
					
						
							|  |  |  |         VMSTATE_UINT8_ARRAY(ir, RXICUState, NR_IRQS), | 
					
						
							|  |  |  |         VMSTATE_UINT8_ARRAY(dtcer, RXICUState, NR_IRQS), | 
					
						
							|  |  |  |         VMSTATE_UINT8_ARRAY(ier, RXICUState, NR_IRQS / 8), | 
					
						
							|  |  |  |         VMSTATE_UINT8_ARRAY(ipr, RXICUState, 142), | 
					
						
							|  |  |  |         VMSTATE_UINT8_ARRAY(dmasr, RXICUState, 4), | 
					
						
							|  |  |  |         VMSTATE_UINT16(fir, RXICUState), | 
					
						
							|  |  |  |         VMSTATE_UINT8(nmisr, RXICUState), | 
					
						
							|  |  |  |         VMSTATE_UINT8(nmier, RXICUState), | 
					
						
							|  |  |  |         VMSTATE_UINT8(nmiclr, RXICUState), | 
					
						
							|  |  |  |         VMSTATE_UINT8(nmicr, RXICUState), | 
					
						
							|  |  |  |         VMSTATE_INT16(req_irq, RXICUState), | 
					
						
							|  |  |  |         VMSTATE_END_OF_LIST() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Property rxicu_properties[] = { | 
					
						
							|  |  |  |     DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map, | 
					
						
							|  |  |  |                       qdev_prop_uint8, uint8_t), | 
					
						
							|  |  |  |     DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense, | 
					
						
							|  |  |  |                       qdev_prop_uint8, uint8_t), | 
					
						
							|  |  |  |     DEFINE_PROP_END_OF_LIST(), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dc->realize = rxicu_realize; | 
					
						
							|  |  |  |     dc->vmsd = &vmstate_rxicu; | 
					
						
							|  |  |  |     device_class_set_props(dc, rxicu_properties); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TypeInfo rxicu_info = { | 
					
						
							|  |  |  |     .name = TYPE_RX_ICU, | 
					
						
							|  |  |  |     .parent = TYPE_SYS_BUS_DEVICE, | 
					
						
							|  |  |  |     .instance_size = sizeof(RXICUState), | 
					
						
							|  |  |  |     .instance_init = rxicu_init, | 
					
						
							|  |  |  |     .instance_finalize = rxicu_fini, | 
					
						
							|  |  |  |     .class_init = rxicu_class_init, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rxicu_register_types(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     type_register_static(&rxicu_info); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type_init(rxicu_register_types) |