Lines Matching +full:spi +full:- +full:flash

2  * Nuvoton NPCM7xx Flash Interface Unit (FIU)
20 #include "hw/qdev-properties.h"
24 #include "qemu/error-report.h"
31 /* Up to 128 MiB of flash may be accessed directly as memory. */
37 /* 32-bit FIU register indices. */
83 /* User-Mode Access register fields. */
103 * Returns the index of flash in the fiu->flash array. This corresponds to the
104 * chip select ID of the flash.
107 NPCM7xxFIUFlash *flash) in npcm7xx_fiu_cs_index() argument
109 int index = flash - fiu->flash; in npcm7xx_fiu_cs_index()
111 g_assert(index >= 0 && index < fiu->cs_count); in npcm7xx_fiu_cs_index()
119 trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id); in npcm7xx_fiu_select()
121 if (cs_id < s->cs_count) { in npcm7xx_fiu_select()
122 qemu_irq_lower(s->cs_lines[cs_id]); in npcm7xx_fiu_select()
123 s->active_cs = cs_id; in npcm7xx_fiu_select()
127 DEVICE(s)->canonical_path, cs_id, s->cs_count); in npcm7xx_fiu_select()
128 s->active_cs = -1; in npcm7xx_fiu_select()
135 if (s->active_cs < 0) { in npcm7xx_fiu_deselect()
139 trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs); in npcm7xx_fiu_deselect()
141 qemu_irq_raise(s->cs_lines[s->active_cs]); in npcm7xx_fiu_deselect()
142 s->active_cs = -1; in npcm7xx_fiu_deselect()
145 /* Direct flash memory read handler. */
150 NPCM7xxFIUState *fiu = f->fiu; in npcm7xx_fiu_flash_read()
156 if (fiu->active_cs != -1) { in npcm7xx_fiu_flash_read()
158 "%s: direct flash read with CS%d already active", in npcm7xx_fiu_flash_read()
159 DEVICE(fiu)->canonical_path, fiu->active_cs); in npcm7xx_fiu_flash_read()
164 drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG]; in npcm7xx_fiu_flash_read()
165 ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg)); in npcm7xx_fiu_flash_read()
169 ssi_transfer(fiu->spi, extract32(addr, 24, 8)); in npcm7xx_fiu_flash_read()
172 ssi_transfer(fiu->spi, extract32(addr, 16, 8)); in npcm7xx_fiu_flash_read()
173 ssi_transfer(fiu->spi, extract32(addr, 8, 8)); in npcm7xx_fiu_flash_read()
174 ssi_transfer(fiu->spi, extract32(addr, 0, 8)); in npcm7xx_fiu_flash_read()
179 DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg)); in npcm7xx_fiu_flash_read()
183 /* Flash chip model expects one transfer per dummy bit, not byte */ in npcm7xx_fiu_flash_read()
187 ssi_transfer(fiu->spi, 0); in npcm7xx_fiu_flash_read()
191 value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0)); in npcm7xx_fiu_flash_read()
194 trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs, in npcm7xx_fiu_flash_read()
202 /* Direct flash memory write handler. */
207 NPCM7xxFIUState *fiu = f->fiu; in npcm7xx_fiu_flash_write()
212 if (fiu->active_cs != -1) { in npcm7xx_fiu_flash_write()
214 "%s: direct flash write with CS%d already active", in npcm7xx_fiu_flash_write()
215 DEVICE(fiu)->canonical_path, fiu->active_cs); in npcm7xx_fiu_flash_write()
219 trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr, in npcm7xx_fiu_flash_write()
223 dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG]; in npcm7xx_fiu_flash_write()
224 ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg)); in npcm7xx_fiu_flash_write()
228 ssi_transfer(fiu->spi, extract32(addr, 24, 8)); in npcm7xx_fiu_flash_write()
231 ssi_transfer(fiu->spi, extract32(addr, 16, 8)); in npcm7xx_fiu_flash_write()
232 ssi_transfer(fiu->spi, extract32(addr, 8, 8)); in npcm7xx_fiu_flash_write()
233 ssi_transfer(fiu->spi, extract32(addr, 0, 8)); in npcm7xx_fiu_flash_write()
238 DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg)); in npcm7xx_fiu_flash_write()
243 ssi_transfer(fiu->spi, extract64(v, i * 8, 8)); in npcm7xx_fiu_flash_write()
269 value = s->regs[reg]; in npcm7xx_fiu_ctrl_read()
273 DEVICE(s)->canonical_path, addr); in npcm7xx_fiu_ctrl_read()
277 trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value); in npcm7xx_fiu_ctrl_read()
283 static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr) in send_address() argument
287 ssi_transfer(spi, extract32(addr, 24, 8)); in send_address()
290 ssi_transfer(spi, extract32(addr, 16, 8)); in send_address()
293 ssi_transfer(spi, extract32(addr, 8, 8)); in send_address()
296 ssi_transfer(spi, extract32(addr, 0, 8)); in send_address()
304 static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd) in send_dummy_bits() argument
315 ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock)); in send_dummy_bits()
320 /* Perform a User-Mode Access transaction. */
323 uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS]; in npcm7xx_fiu_uma_transaction()
329 int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]); in npcm7xx_fiu_uma_transaction()
334 uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG]; in npcm7xx_fiu_uma_transaction()
336 ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8)); in npcm7xx_fiu_uma_transaction()
340 send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg), in npcm7xx_fiu_uma_transaction()
341 s->regs[NPCM7XX_FIU_UMA_ADDR]); in npcm7xx_fiu_uma_transaction()
349 ssi_transfer(s->spi, extract32(s->regs[reg], field, 8)); in npcm7xx_fiu_uma_transaction()
353 send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]); in npcm7xx_fiu_uma_transaction()
361 c = ssi_transfer(s->spi, 0); in npcm7xx_fiu_uma_transaction()
363 s->regs[reg] = deposit32(s->regs[reg], field, 8, c); in npcm7xx_fiu_uma_transaction()
373 s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST; in npcm7xx_fiu_uma_transaction()
375 s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE; in npcm7xx_fiu_uma_transaction()
386 trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value); in npcm7xx_fiu_ctrl_write()
390 if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) { in npcm7xx_fiu_ctrl_write()
392 value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK); in npcm7xx_fiu_ctrl_write()
397 if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) { in npcm7xx_fiu_ctrl_write()
400 DEVICE(s)->canonical_path, addr); in npcm7xx_fiu_ctrl_write()
403 s->regs[reg] = value; in npcm7xx_fiu_ctrl_write()
410 value |= s->regs[reg] & FIU_UMA_CTS_RDYST; in npcm7xx_fiu_ctrl_write()
412 if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) { in npcm7xx_fiu_ctrl_write()
418 if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) { in npcm7xx_fiu_ctrl_write()
422 int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]); in npcm7xx_fiu_ctrl_write()
426 s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE); in npcm7xx_fiu_ctrl_write()
434 "%s: write to read-only register @ 0x%" PRIx64 "\n", in npcm7xx_fiu_ctrl_write()
435 DEVICE(s)->canonical_path, addr); in npcm7xx_fiu_ctrl_write()
447 s->regs[reg] = value; in npcm7xx_fiu_ctrl_write()
453 DEVICE(s)->canonical_path, addr); in npcm7xx_fiu_ctrl_write()
473 trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type); in npcm7xx_fiu_enter_reset()
475 memset(s->regs, 0, sizeof(s->regs)); in npcm7xx_fiu_enter_reset()
477 s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b; in npcm7xx_fiu_enter_reset()
478 s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002; in npcm7xx_fiu_enter_reset()
479 s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400; in npcm7xx_fiu_enter_reset()
480 s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000; in npcm7xx_fiu_enter_reset()
481 s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b; in npcm7xx_fiu_enter_reset()
482 s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400; in npcm7xx_fiu_enter_reset()
483 s->regs[NPCM7XX_FIU_CFG] = 0x0000000b; in npcm7xx_fiu_enter_reset()
491 trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path); in npcm7xx_fiu_hold_reset()
493 for (i = 0; i < s->cs_count; i++) { in npcm7xx_fiu_hold_reset()
494 qemu_irq_raise(s->cs_lines[i]); in npcm7xx_fiu_hold_reset()
504 if (s->cs_count <= 0) { in npcm7xx_fiu_realize()
506 dev->canonical_path, s->cs_count); in npcm7xx_fiu_realize()
510 if (s->flash_size == 0) { in npcm7xx_fiu_realize()
511 error_setg(errp, "%s: flash size must be set", dev->canonical_path); in npcm7xx_fiu_realize()
515 if (s->flash_size > NPCM7XX_FIU_MAX_FLASH_WINDOW_SIZE) { in npcm7xx_fiu_realize()
516 error_setg(errp, "%s: flash size should not exceed 128 MiB", in npcm7xx_fiu_realize()
517 dev->canonical_path); in npcm7xx_fiu_realize()
521 s->spi = ssi_create_bus(dev, "spi"); in npcm7xx_fiu_realize()
522 s->cs_lines = g_new0(qemu_irq, s->cs_count); in npcm7xx_fiu_realize()
523 qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count); in npcm7xx_fiu_realize()
524 s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count); in npcm7xx_fiu_realize()
528 * or more direct flash access regions. in npcm7xx_fiu_realize()
530 memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl", in npcm7xx_fiu_realize()
532 sysbus_init_mmio(sbd, &s->mmio); in npcm7xx_fiu_realize()
534 for (i = 0; i < s->cs_count; i++) { in npcm7xx_fiu_realize()
535 NPCM7xxFIUFlash *flash = &s->flash[i]; in npcm7xx_fiu_realize() local
536 flash->fiu = s; in npcm7xx_fiu_realize()
537 memory_region_init_io(&flash->direct_access, OBJECT(s), in npcm7xx_fiu_realize()
538 &npcm7xx_fiu_flash_ops, &s->flash[i], "flash", in npcm7xx_fiu_realize()
539 s->flash_size); in npcm7xx_fiu_realize()
540 sysbus_init_mmio(sbd, &flash->direct_access); in npcm7xx_fiu_realize()
545 .name = "npcm7xx-fiu",
556 DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0),
557 DEFINE_PROP_SIZE("flash-size", NPCM7xxFIUState, flash_size, 0),
567 dc->desc = "NPCM7xx Flash Interface Unit"; in npcm7xx_fiu_class_init()
568 dc->realize = npcm7xx_fiu_realize; in npcm7xx_fiu_class_init()
569 dc->vmsd = &vmstate_npcm7xx_fiu; in npcm7xx_fiu_class_init()
570 rc->phases.enter = npcm7xx_fiu_enter_reset; in npcm7xx_fiu_class_init()
571 rc->phases.hold = npcm7xx_fiu_hold_reset; in npcm7xx_fiu_class_init()