1 /* 2 * Nuvoton NPCM7xx Flash Interface Unit (FIU) 3 * 4 * Copyright 2020 Google LLC 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * for more details. 15 */ 16 17 #include "qemu/osdep.h" 18 19 #include "hw/irq.h" 20 #include "hw/qdev-properties.h" 21 #include "hw/ssi/npcm7xx_fiu.h" 22 #include "migration/vmstate.h" 23 #include "qapi/error.h" 24 #include "qemu/error-report.h" 25 #include "qemu/log.h" 26 #include "qemu/module.h" 27 #include "qemu/units.h" 28 29 #include "trace.h" 30 31 /* Up to 128 MiB of flash may be accessed directly as memory. */ 32 #define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB) 33 34 /* Each module has 4 KiB of register space. Only a fraction of it is used. */ 35 #define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB) 36 37 /* 32-bit FIU register indices. */ 38 enum NPCM7xxFIURegister { 39 NPCM7XX_FIU_DRD_CFG, 40 NPCM7XX_FIU_DWR_CFG, 41 NPCM7XX_FIU_UMA_CFG, 42 NPCM7XX_FIU_UMA_CTS, 43 NPCM7XX_FIU_UMA_CMD, 44 NPCM7XX_FIU_UMA_ADDR, 45 NPCM7XX_FIU_PRT_CFG, 46 NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t), 47 NPCM7XX_FIU_UMA_DW1, 48 NPCM7XX_FIU_UMA_DW2, 49 NPCM7XX_FIU_UMA_DW3, 50 NPCM7XX_FIU_UMA_DR0, 51 NPCM7XX_FIU_UMA_DR1, 52 NPCM7XX_FIU_UMA_DR2, 53 NPCM7XX_FIU_UMA_DR3, 54 NPCM7XX_FIU_PRT_CMD0, 55 NPCM7XX_FIU_PRT_CMD1, 56 NPCM7XX_FIU_PRT_CMD2, 57 NPCM7XX_FIU_PRT_CMD3, 58 NPCM7XX_FIU_PRT_CMD4, 59 NPCM7XX_FIU_PRT_CMD5, 60 NPCM7XX_FIU_PRT_CMD6, 61 NPCM7XX_FIU_PRT_CMD7, 62 NPCM7XX_FIU_PRT_CMD8, 63 NPCM7XX_FIU_PRT_CMD9, 64 NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t), 65 NPCM7XX_FIU_REGS_END, 66 }; 67 68 /* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */ 69 #define NPCM7XX_FIU_CFG_LCK BIT(31) 70 71 /* Direct Read configuration register fields. */ 72 #define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2) 73 #define FIU_ADDSIZ_3BYTES 0 74 #define FIU_ADDSIZ_4BYTES 1 75 #define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2) 76 #define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2) 77 #define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8) 78 79 /* Direct Write configuration register fields. */ 80 #define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2) 81 #define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8) 82 83 /* User-Mode Access register fields. */ 84 85 /* Command Mode Lock and the bits protected by it. */ 86 #define FIU_UMA_CFG_CMMLCK BIT(30) 87 #define FIU_UMA_CFG_CMMLCK_MASK 0x00000403 88 89 #define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5) 90 #define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3) 91 #define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5) 92 #define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3) 93 #define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1) 94 #define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2) 95 96 #define FIU_UMA_CTS_RDYIE BIT(25) 97 #define FIU_UMA_CTS_RDYST BIT(24) 98 #define FIU_UMA_CTS_SW_CS BIT(16) 99 #define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2) 100 #define FIU_UMA_CTS_EXEC_DONE BIT(0) 101 102 /* 103 * Returns the index of flash in the fiu->flash array. This corresponds to the 104 * chip select ID of the flash. 105 */ 106 static unsigned npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, 107 NPCM7xxFIUFlash *flash) 108 { 109 int index = flash - fiu->flash; 110 111 g_assert(index >= 0 && index < fiu->cs_count); 112 113 return index; 114 } 115 116 /* Assert the chip select specified in the UMA Control/Status Register. */ 117 static void npcm7xx_fiu_select(NPCM7xxFIUState *s, unsigned cs_id) 118 { 119 trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id); 120 121 if (cs_id < s->cs_count) { 122 qemu_irq_lower(s->cs_lines[cs_id]); 123 s->active_cs = cs_id; 124 } else { 125 qemu_log_mask(LOG_GUEST_ERROR, 126 "%s: UMA to CS%d; this module has only %d chip selects", 127 DEVICE(s)->canonical_path, cs_id, s->cs_count); 128 s->active_cs = -1; 129 } 130 } 131 132 /* Deassert the currently active chip select. */ 133 static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s) 134 { 135 if (s->active_cs < 0) { 136 return; 137 } 138 139 trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs); 140 141 qemu_irq_raise(s->cs_lines[s->active_cs]); 142 s->active_cs = -1; 143 } 144 145 /* Direct flash memory read handler. */ 146 static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr, 147 unsigned int size) 148 { 149 NPCM7xxFIUFlash *f = opaque; 150 NPCM7xxFIUState *fiu = f->fiu; 151 uint64_t value = 0; 152 uint32_t drd_cfg; 153 int dummy_cycles; 154 int i; 155 156 if (fiu->active_cs != -1) { 157 qemu_log_mask(LOG_GUEST_ERROR, 158 "%s: direct flash read with CS%d already active", 159 DEVICE(fiu)->canonical_path, fiu->active_cs); 160 } 161 162 npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f)); 163 164 drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG]; 165 ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg)); 166 167 switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) { 168 case FIU_ADDSIZ_4BYTES: 169 ssi_transfer(fiu->spi, extract32(addr, 24, 8)); 170 /* fall through */ 171 case FIU_ADDSIZ_3BYTES: 172 ssi_transfer(fiu->spi, extract32(addr, 16, 8)); 173 ssi_transfer(fiu->spi, extract32(addr, 8, 8)); 174 ssi_transfer(fiu->spi, extract32(addr, 0, 8)); 175 break; 176 177 default: 178 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n", 179 DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg)); 180 break; 181 } 182 183 /* Flash chip model expects one transfer per dummy bit, not byte */ 184 dummy_cycles = 185 (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg); 186 for (i = 0; i < dummy_cycles; i++) { 187 ssi_transfer(fiu->spi, 0); 188 } 189 190 for (i = 0; i < size; i++) { 191 value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0)); 192 } 193 194 trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs, 195 addr, size, value); 196 197 npcm7xx_fiu_deselect(fiu); 198 199 return value; 200 } 201 202 /* Direct flash memory write handler. */ 203 static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v, 204 unsigned int size) 205 { 206 NPCM7xxFIUFlash *f = opaque; 207 NPCM7xxFIUState *fiu = f->fiu; 208 uint32_t dwr_cfg; 209 unsigned cs_id; 210 int i; 211 212 if (fiu->active_cs != -1) { 213 qemu_log_mask(LOG_GUEST_ERROR, 214 "%s: direct flash write with CS%d already active", 215 DEVICE(fiu)->canonical_path, fiu->active_cs); 216 } 217 218 cs_id = npcm7xx_fiu_cs_index(fiu, f); 219 trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr, 220 size, v); 221 npcm7xx_fiu_select(fiu, cs_id); 222 223 dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG]; 224 ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg)); 225 226 switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) { 227 case FIU_ADDSIZ_4BYTES: 228 ssi_transfer(fiu->spi, extract32(addr, 24, 8)); 229 /* fall through */ 230 case FIU_ADDSIZ_3BYTES: 231 ssi_transfer(fiu->spi, extract32(addr, 16, 8)); 232 ssi_transfer(fiu->spi, extract32(addr, 8, 8)); 233 ssi_transfer(fiu->spi, extract32(addr, 0, 8)); 234 break; 235 236 default: 237 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n", 238 DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg)); 239 break; 240 } 241 242 for (i = 0; i < size; i++) { 243 ssi_transfer(fiu->spi, extract64(v, i * 8, 8)); 244 } 245 246 npcm7xx_fiu_deselect(fiu); 247 } 248 249 static const MemoryRegionOps npcm7xx_fiu_flash_ops = { 250 .read = npcm7xx_fiu_flash_read, 251 .write = npcm7xx_fiu_flash_write, 252 .endianness = DEVICE_LITTLE_ENDIAN, 253 .valid = { 254 .min_access_size = 1, 255 .max_access_size = 8, 256 .unaligned = true, 257 }, 258 }; 259 260 /* Control register read handler. */ 261 static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr, 262 unsigned int size) 263 { 264 hwaddr reg = addr / sizeof(uint32_t); 265 NPCM7xxFIUState *s = opaque; 266 uint32_t value; 267 268 if (reg < NPCM7XX_FIU_NR_REGS) { 269 value = s->regs[reg]; 270 } else { 271 qemu_log_mask(LOG_GUEST_ERROR, 272 "%s: read from invalid offset 0x%" PRIx64 "\n", 273 DEVICE(s)->canonical_path, addr); 274 value = 0; 275 } 276 277 trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value); 278 279 return value; 280 } 281 282 /* Send the specified number of address bytes from the UMA address register. */ 283 static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr) 284 { 285 switch (addsiz) { 286 case 4: 287 ssi_transfer(spi, extract32(addr, 24, 8)); 288 /* fall through */ 289 case 3: 290 ssi_transfer(spi, extract32(addr, 16, 8)); 291 /* fall through */ 292 case 2: 293 ssi_transfer(spi, extract32(addr, 8, 8)); 294 /* fall through */ 295 case 1: 296 ssi_transfer(spi, extract32(addr, 0, 8)); 297 /* fall through */ 298 case 0: 299 break; 300 } 301 } 302 303 /* Send the number of dummy bits specified in the UMA config register. */ 304 static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd) 305 { 306 unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg); 307 unsigned int i; 308 309 for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) { 310 /* Use bytes 0 and 1 first, then keep repeating byte 2 */ 311 unsigned int field = (i < 2) ? ((i + 1) * 8) : 24; 312 unsigned int j; 313 314 for (j = 0; j < 8; j += bits_per_clock) { 315 ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock)); 316 } 317 } 318 } 319 320 /* Perform a User-Mode Access transaction. */ 321 static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s) 322 { 323 uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS]; 324 uint32_t uma_cfg; 325 unsigned int i; 326 327 /* SW_CS means the CS is already forced low, so don't touch it. */ 328 if (uma_cts & FIU_UMA_CTS_SW_CS) { 329 int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]); 330 npcm7xx_fiu_select(s, cs_id); 331 } 332 333 /* Send command, if present. */ 334 uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG]; 335 if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) { 336 ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8)); 337 } 338 339 /* Send address, if present. */ 340 send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg), 341 s->regs[NPCM7XX_FIU_UMA_ADDR]); 342 343 /* Write data, if present. */ 344 for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) { 345 unsigned int reg = 346 (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3; 347 unsigned int field = (i % 4) * 8; 348 349 ssi_transfer(s->spi, extract32(s->regs[reg], field, 8)); 350 } 351 352 /* Send dummy bits, if present. */ 353 send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]); 354 355 /* Read data, if present. */ 356 for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) { 357 unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4; 358 unsigned int field = (i % 4) * 8; 359 uint8_t c; 360 361 c = ssi_transfer(s->spi, 0); 362 if (reg <= NPCM7XX_FIU_UMA_DR3) { 363 s->regs[reg] = deposit32(s->regs[reg], field, 8, c); 364 } 365 } 366 367 /* Again, don't touch CS if the user is forcing it low. */ 368 if (uma_cts & FIU_UMA_CTS_SW_CS) { 369 npcm7xx_fiu_deselect(s); 370 } 371 372 /* RDYST means a command has completed since it was cleared. */ 373 s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST; 374 /* EXEC_DONE means Execute Command / Not Done, so clear it here. */ 375 s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE; 376 } 377 378 /* Control register write handler. */ 379 static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v, 380 unsigned int size) 381 { 382 hwaddr reg = addr / sizeof(uint32_t); 383 NPCM7xxFIUState *s = opaque; 384 uint32_t value = v; 385 386 trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value); 387 388 switch (reg) { 389 case NPCM7XX_FIU_UMA_CFG: 390 if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) { 391 value &= ~FIU_UMA_CFG_CMMLCK_MASK; 392 value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK); 393 } 394 /* fall through */ 395 case NPCM7XX_FIU_DRD_CFG: 396 case NPCM7XX_FIU_DWR_CFG: 397 if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) { 398 qemu_log_mask(LOG_GUEST_ERROR, 399 "%s: write to locked register @ 0x%" PRIx64 "\n", 400 DEVICE(s)->canonical_path, addr); 401 return; 402 } 403 s->regs[reg] = value; 404 break; 405 406 case NPCM7XX_FIU_UMA_CTS: 407 if (value & FIU_UMA_CTS_RDYST) { 408 value &= ~FIU_UMA_CTS_RDYST; 409 } else { 410 value |= s->regs[reg] & FIU_UMA_CTS_RDYST; 411 } 412 if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) { 413 if (value & FIU_UMA_CTS_SW_CS) { 414 /* 415 * Don't drop CS if there's a transfer in progress, or we're 416 * about to start one. 417 */ 418 if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) { 419 npcm7xx_fiu_deselect(s); 420 } 421 } else { 422 int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]); 423 npcm7xx_fiu_select(s, cs_id); 424 } 425 } 426 s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE); 427 if (value & FIU_UMA_CTS_EXEC_DONE) { 428 npcm7xx_fiu_uma_transaction(s); 429 } 430 break; 431 432 case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3: 433 qemu_log_mask(LOG_GUEST_ERROR, 434 "%s: write to read-only register @ 0x%" PRIx64 "\n", 435 DEVICE(s)->canonical_path, addr); 436 return; 437 438 case NPCM7XX_FIU_PRT_CFG: 439 case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9: 440 qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__); 441 break; 442 443 case NPCM7XX_FIU_UMA_CMD: 444 case NPCM7XX_FIU_UMA_ADDR: 445 case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3: 446 case NPCM7XX_FIU_CFG: 447 s->regs[reg] = value; 448 break; 449 450 default: 451 qemu_log_mask(LOG_GUEST_ERROR, 452 "%s: write to invalid offset 0x%" PRIx64 "\n", 453 DEVICE(s)->canonical_path, addr); 454 return; 455 } 456 } 457 458 static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = { 459 .read = npcm7xx_fiu_ctrl_read, 460 .write = npcm7xx_fiu_ctrl_write, 461 .endianness = DEVICE_LITTLE_ENDIAN, 462 .valid = { 463 .min_access_size = 4, 464 .max_access_size = 4, 465 .unaligned = false, 466 }, 467 }; 468 469 static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type) 470 { 471 NPCM7xxFIUState *s = NPCM7XX_FIU(obj); 472 473 trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type); 474 475 memset(s->regs, 0, sizeof(s->regs)); 476 477 s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b; 478 s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002; 479 s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400; 480 s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000; 481 s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b; 482 s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400; 483 s->regs[NPCM7XX_FIU_CFG] = 0x0000000b; 484 } 485 486 static void npcm7xx_fiu_hold_reset(Object *obj) 487 { 488 NPCM7xxFIUState *s = NPCM7XX_FIU(obj); 489 int i; 490 491 trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path); 492 493 for (i = 0; i < s->cs_count; i++) { 494 qemu_irq_raise(s->cs_lines[i]); 495 } 496 } 497 498 static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp) 499 { 500 NPCM7xxFIUState *s = NPCM7XX_FIU(dev); 501 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 502 int i; 503 504 if (s->cs_count <= 0) { 505 error_setg(errp, "%s: %d chip selects specified, need at least one", 506 dev->canonical_path, s->cs_count); 507 return; 508 } 509 510 s->spi = ssi_create_bus(dev, "spi"); 511 s->cs_lines = g_new0(qemu_irq, s->cs_count); 512 qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count); 513 s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count); 514 515 /* 516 * Register the control registers region first. It may be followed by one 517 * or more direct flash access regions. 518 */ 519 memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl", 520 NPCM7XX_FIU_CTRL_REGS_SIZE); 521 sysbus_init_mmio(sbd, &s->mmio); 522 523 for (i = 0; i < s->cs_count; i++) { 524 NPCM7xxFIUFlash *flash = &s->flash[i]; 525 flash->fiu = s; 526 memory_region_init_io(&flash->direct_access, OBJECT(s), 527 &npcm7xx_fiu_flash_ops, &s->flash[i], "flash", 528 NPCM7XX_FIU_FLASH_WINDOW_SIZE); 529 sysbus_init_mmio(sbd, &flash->direct_access); 530 } 531 } 532 533 static const VMStateDescription vmstate_npcm7xx_fiu = { 534 .name = "npcm7xx-fiu", 535 .version_id = 0, 536 .minimum_version_id = 0, 537 .fields = (VMStateField[]) { 538 VMSTATE_INT32(active_cs, NPCM7xxFIUState), 539 VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS), 540 VMSTATE_END_OF_LIST(), 541 }, 542 }; 543 544 static Property npcm7xx_fiu_properties[] = { 545 DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0), 546 DEFINE_PROP_END_OF_LIST(), 547 }; 548 549 static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data) 550 { 551 ResettableClass *rc = RESETTABLE_CLASS(klass); 552 DeviceClass *dc = DEVICE_CLASS(klass); 553 554 QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS); 555 556 dc->desc = "NPCM7xx Flash Interface Unit"; 557 dc->realize = npcm7xx_fiu_realize; 558 dc->vmsd = &vmstate_npcm7xx_fiu; 559 rc->phases.enter = npcm7xx_fiu_enter_reset; 560 rc->phases.hold = npcm7xx_fiu_hold_reset; 561 device_class_set_props(dc, npcm7xx_fiu_properties); 562 } 563 564 static const TypeInfo npcm7xx_fiu_types[] = { 565 { 566 .name = TYPE_NPCM7XX_FIU, 567 .parent = TYPE_SYS_BUS_DEVICE, 568 .instance_size = sizeof(NPCM7xxFIUState), 569 .class_init = npcm7xx_fiu_class_init, 570 }, 571 }; 572 DEFINE_TYPES(npcm7xx_fiu_types); 573