2 * Nuvoton NPCM7xx Flash Interface Unit (FIU)
4 * Copyright 2020 Google LLC
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.
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
17 #include "qemu/osdep.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"
26 #include "qemu/module.h"
27 #include "qemu/units.h"
31 /* Up to 128 MiB of flash may be accessed directly as memory. */
32 #define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB)
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)
37 /* 32-bit FIU register indices. */
38 enum NPCM7xxFIURegister
{
46 NPCM7XX_FIU_UMA_DW0
= 0x0020 / sizeof(uint32_t),
64 NPCM7XX_FIU_CFG
= 0x78 / sizeof(uint32_t),
68 /* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */
69 #define NPCM7XX_FIU_CFG_LCK BIT(31)
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)
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)
83 /* User-Mode Access register fields. */
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
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)
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)
103 * Returns the index of flash in the fiu->flash array. This corresponds to the
104 * chip select ID of the flash.
106 static unsigned npcm7xx_fiu_cs_index(NPCM7xxFIUState
*fiu
,
107 NPCM7xxFIUFlash
*flash
)
109 int index
= flash
- fiu
->flash
;
111 g_assert(index
>= 0 && index
< fiu
->cs_count
);
116 /* Assert the chip select specified in the UMA Control/Status Register. */
117 static void npcm7xx_fiu_select(NPCM7xxFIUState
*s
, unsigned cs_id
)
119 trace_npcm7xx_fiu_select(DEVICE(s
)->canonical_path
, cs_id
);
121 if (cs_id
< s
->cs_count
) {
122 qemu_irq_lower(s
->cs_lines
[cs_id
]);
123 s
->active_cs
= cs_id
;
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
);
132 /* Deassert the currently active chip select. */
133 static void npcm7xx_fiu_deselect(NPCM7xxFIUState
*s
)
135 if (s
->active_cs
< 0) {
139 trace_npcm7xx_fiu_deselect(DEVICE(s
)->canonical_path
, s
->active_cs
);
141 qemu_irq_raise(s
->cs_lines
[s
->active_cs
]);
145 /* Direct flash memory read handler. */
146 static uint64_t npcm7xx_fiu_flash_read(void *opaque
, hwaddr addr
,
149 NPCM7xxFIUFlash
*f
= opaque
;
150 NPCM7xxFIUState
*fiu
= f
->fiu
;
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
);
162 npcm7xx_fiu_select(fiu
, npcm7xx_fiu_cs_index(fiu
, f
));
164 drd_cfg
= fiu
->regs
[NPCM7XX_FIU_DRD_CFG
];
165 ssi_transfer(fiu
->spi
, FIU_DRD_CFG_RDCMD(drd_cfg
));
167 switch (FIU_DRD_CFG_ADDSIZ(drd_cfg
)) {
168 case FIU_ADDSIZ_4BYTES
:
169 ssi_transfer(fiu
->spi
, extract32(addr
, 24, 8));
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));
178 qemu_log_mask(LOG_GUEST_ERROR
, "%s: bad address size %d\n",
179 DEVICE(fiu
)->canonical_path
, FIU_DRD_CFG_ADDSIZ(drd_cfg
));
183 /* Flash chip model expects one transfer per dummy bit, not byte */
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);
190 for (i
= 0; i
< size
; i
++) {
191 value
= deposit64(value
, 8 * i
, 8, ssi_transfer(fiu
->spi
, 0));
194 trace_npcm7xx_fiu_flash_read(DEVICE(fiu
)->canonical_path
, fiu
->active_cs
,
197 npcm7xx_fiu_deselect(fiu
);
202 /* Direct flash memory write handler. */
203 static void npcm7xx_fiu_flash_write(void *opaque
, hwaddr addr
, uint64_t v
,
206 NPCM7xxFIUFlash
*f
= opaque
;
207 NPCM7xxFIUState
*fiu
= f
->fiu
;
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
);
218 cs_id
= npcm7xx_fiu_cs_index(fiu
, f
);
219 trace_npcm7xx_fiu_flash_write(DEVICE(fiu
)->canonical_path
, cs_id
, addr
,
221 npcm7xx_fiu_select(fiu
, cs_id
);
223 dwr_cfg
= fiu
->regs
[NPCM7XX_FIU_DWR_CFG
];
224 ssi_transfer(fiu
->spi
, FIU_DWR_CFG_WRCMD(dwr_cfg
));
226 switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg
)) {
227 case FIU_ADDSIZ_4BYTES
:
228 ssi_transfer(fiu
->spi
, extract32(addr
, 24, 8));
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));
237 qemu_log_mask(LOG_GUEST_ERROR
, "%s: bad address size %d\n",
238 DEVICE(fiu
)->canonical_path
, FIU_DWR_CFG_ADDSIZ(dwr_cfg
));
242 for (i
= 0; i
< size
; i
++) {
243 ssi_transfer(fiu
->spi
, extract64(v
, i
* 8, 8));
246 npcm7xx_fiu_deselect(fiu
);
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
,
254 .min_access_size
= 1,
255 .max_access_size
= 8,
260 /* Control register read handler. */
261 static uint64_t npcm7xx_fiu_ctrl_read(void *opaque
, hwaddr addr
,
264 hwaddr reg
= addr
/ sizeof(uint32_t);
265 NPCM7xxFIUState
*s
= opaque
;
268 if (reg
< NPCM7XX_FIU_NR_REGS
) {
269 value
= s
->regs
[reg
];
271 qemu_log_mask(LOG_GUEST_ERROR
,
272 "%s: read from invalid offset 0x%" PRIx64
"\n",
273 DEVICE(s
)->canonical_path
, addr
);
277 trace_npcm7xx_fiu_ctrl_read(DEVICE(s
)->canonical_path
, addr
, value
);
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
)
287 ssi_transfer(spi
, extract32(addr
, 24, 8));
290 ssi_transfer(spi
, extract32(addr
, 16, 8));
293 ssi_transfer(spi
, extract32(addr
, 8, 8));
296 ssi_transfer(spi
, extract32(addr
, 0, 8));
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
)
306 unsigned int bits_per_clock
= 1U << FIU_UMA_CFG_DBPCK(uma_cfg
);
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;
314 for (j
= 0; j
< 8; j
+= bits_per_clock
) {
315 ssi_transfer(spi
, extract32(uma_cmd
, field
+ j
, bits_per_clock
));
320 /* Perform a User-Mode Access transaction. */
321 static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState
*s
)
323 uint32_t uma_cts
= s
->regs
[NPCM7XX_FIU_UMA_CTS
];
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
);
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));
339 /* Send address, if present. */
340 send_address(s
->spi
, FIU_UMA_CFG_ADDSIZ(uma_cfg
),
341 s
->regs
[NPCM7XX_FIU_UMA_ADDR
]);
343 /* Write data, if present. */
344 for (i
= 0; i
< FIU_UMA_CFG_WDATSIZ(uma_cfg
); i
++) {
346 (i
< 16) ? (NPCM7XX_FIU_UMA_DW0
+ i
/ 4) : NPCM7XX_FIU_UMA_DW3
;
347 unsigned int field
= (i
% 4) * 8;
349 ssi_transfer(s
->spi
, extract32(s
->regs
[reg
], field
, 8));
352 /* Send dummy bits, if present. */
353 send_dummy_bits(s
->spi
, uma_cfg
, s
->regs
[NPCM7XX_FIU_UMA_CMD
]);
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;
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
);
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
);
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
;
378 /* Control register write handler. */
379 static void npcm7xx_fiu_ctrl_write(void *opaque
, hwaddr addr
, uint64_t v
,
382 hwaddr reg
= addr
/ sizeof(uint32_t);
383 NPCM7xxFIUState
*s
= opaque
;
386 trace_npcm7xx_fiu_ctrl_write(DEVICE(s
)->canonical_path
, addr
, value
);
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
);
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
);
403 s
->regs
[reg
] = value
;
406 case NPCM7XX_FIU_UMA_CTS
:
407 if (value
& FIU_UMA_CTS_RDYST
) {
408 value
&= ~FIU_UMA_CTS_RDYST
;
410 value
|= s
->regs
[reg
] & FIU_UMA_CTS_RDYST
;
412 if ((s
->regs
[reg
] ^ value
) & FIU_UMA_CTS_SW_CS
) {
413 if (value
& FIU_UMA_CTS_SW_CS
) {
415 * Don't drop CS if there's a transfer in progress, or we're
416 * about to start one.
418 if (!((value
| s
->regs
[reg
]) & FIU_UMA_CTS_EXEC_DONE
)) {
419 npcm7xx_fiu_deselect(s
);
422 int cs_id
= FIU_UMA_CTS_DEV_NUM(s
->regs
[NPCM7XX_FIU_UMA_CTS
]);
423 npcm7xx_fiu_select(s
, cs_id
);
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
);
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
);
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__
);
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
;
451 qemu_log_mask(LOG_GUEST_ERROR
,
452 "%s: write to invalid offset 0x%" PRIx64
"\n",
453 DEVICE(s
)->canonical_path
, addr
);
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
,
463 .min_access_size
= 4,
464 .max_access_size
= 4,
469 static void npcm7xx_fiu_enter_reset(Object
*obj
, ResetType type
)
471 NPCM7xxFIUState
*s
= NPCM7XX_FIU(obj
);
473 trace_npcm7xx_fiu_enter_reset(DEVICE(obj
)->canonical_path
, type
);
475 memset(s
->regs
, 0, sizeof(s
->regs
));
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;
486 static void npcm7xx_fiu_hold_reset(Object
*obj
)
488 NPCM7xxFIUState
*s
= NPCM7XX_FIU(obj
);
491 trace_npcm7xx_fiu_hold_reset(DEVICE(obj
)->canonical_path
);
493 for (i
= 0; i
< s
->cs_count
; i
++) {
494 qemu_irq_raise(s
->cs_lines
[i
]);
498 static void npcm7xx_fiu_realize(DeviceState
*dev
, Error
**errp
)
500 NPCM7xxFIUState
*s
= NPCM7XX_FIU(dev
);
501 SysBusDevice
*sbd
= &s
->parent
;
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
);
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
);
516 * Register the control registers region first. It may be followed by one
517 * or more direct flash access regions.
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
);
523 for (i
= 0; i
< s
->cs_count
; i
++) {
524 NPCM7xxFIUFlash
*flash
= &s
->flash
[i
];
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
);
533 static const VMStateDescription vmstate_npcm7xx_fiu
= {
534 .name
= "npcm7xx-fiu",
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(),
544 static Property npcm7xx_fiu_properties
[] = {
545 DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState
, cs_count
, 0),
546 DEFINE_PROP_END_OF_LIST(),
549 static void npcm7xx_fiu_class_init(ObjectClass
*klass
, void *data
)
551 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
552 DeviceClass
*dc
= DEVICE_CLASS(klass
);
554 QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END
> NPCM7XX_FIU_NR_REGS
);
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
);
564 static const TypeInfo npcm7xx_fiu_types
[] = {
566 .name
= TYPE_NPCM7XX_FIU
,
567 .parent
= TYPE_SYS_BUS_DEVICE
,
568 .instance_size
= sizeof(NPCM7xxFIUState
),
569 .class_init
= npcm7xx_fiu_class_init
,
572 DEFINE_TYPES(npcm7xx_fiu_types
);