From afb3141c660f3dca38227901c5c62cef7af86647 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 27 Jan 2017 15:20:21 +0000 Subject: hw/registerfields.h: Pull FIELD etc macros out of hw/register.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hw/register.h provides macros like FIELD which make it easy to define shift, mask and length constants for the fields within a register. Unfortunately register.h also includes a lot of other things, some of which will only compile in the softmmu build. Pull the FIELD macro and friends out into a separate header file, so they can be used in places like target/arm files which also get built in the user-only configs. Signed-off-by: Peter Maydell Reviewed-by: Alistair Francis Reviewed-by: Alex Bennée Message-id: 1484937883-1068-5-git-send-email-peter.maydell@linaro.org --- include/hw/register.h | 47 +---------------------------------- include/hw/registerfields.h | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 46 deletions(-) create mode 100644 include/hw/registerfields.h (limited to 'include') diff --git a/include/hw/register.h b/include/hw/register.h index 5b6dc32..de2414e 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -13,6 +13,7 @@ #include "hw/qdev-core.h" #include "exec/memory.h" +#include "hw/registerfields.h" typedef struct RegisterInfo RegisterInfo; typedef struct RegisterAccessInfo RegisterAccessInfo; @@ -206,50 +207,4 @@ RegisterInfoArray *register_init_block32(DeviceState *owner, void register_finalize_block(RegisterInfoArray *r_array); -/* Define constants for a 32 bit register */ - -/* This macro will define A_FOO, for the byte address of a register - * as well as R_FOO for the uint32_t[] register number (A_FOO / 4). - */ -#define REG32(reg, addr) \ - enum { A_ ## reg = (addr) }; \ - enum { R_ ## reg = (addr) / 4 }; - -/* Define SHIFT, LENGTH and MASK constants for a field within a register */ - -/* This macro will define FOO_BAR_MASK, FOO_BAR_SHIFT and FOO_BAR_LENGTH - * constants for field BAR in register FOO. - */ -#define FIELD(reg, field, shift, length) \ - enum { R_ ## reg ## _ ## field ## _SHIFT = (shift)}; \ - enum { R_ ## reg ## _ ## field ## _LENGTH = (length)}; \ - enum { R_ ## reg ## _ ## field ## _MASK = \ - MAKE_64BIT_MASK(shift, length)}; - -/* Extract a field from a register */ -#define FIELD_EX32(storage, reg, field) \ - extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ - R_ ## reg ## _ ## field ## _LENGTH) - -/* Extract a field from an array of registers */ -#define ARRAY_FIELD_EX32(regs, reg, field) \ - FIELD_EX32((regs)[R_ ## reg], reg, field) - -/* Deposit a register field. - * Assigning values larger then the target field will result in - * compilation warnings. - */ -#define FIELD_DP32(storage, reg, field, val) ({ \ - struct { \ - unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ - } v = { .v = val }; \ - uint32_t d; \ - d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ - R_ ## reg ## _ ## field ## _LENGTH, v.v); \ - d; }) - -/* Deposit a field to array of registers. */ -#define ARRAY_FIELD_DP32(regs, reg, field, val) \ - (regs)[R_ ## reg] = FIELD_DP32((regs)[R_ ## reg], reg, field, val); - #endif diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h new file mode 100644 index 0000000..af101d5 --- /dev/null +++ b/include/hw/registerfields.h @@ -0,0 +1,60 @@ +/* + * Register Definition API: field macros + * + * Copyright (c) 2016 Xilinx Inc. + * Copyright (c) 2013 Peter Crosthwaite + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef REGISTERFIELDS_H +#define REGISTERFIELDS_H + +/* Define constants for a 32 bit register */ + +/* This macro will define A_FOO, for the byte address of a register + * as well as R_FOO for the uint32_t[] register number (A_FOO / 4). + */ +#define REG32(reg, addr) \ + enum { A_ ## reg = (addr) }; \ + enum { R_ ## reg = (addr) / 4 }; + +/* Define SHIFT, LENGTH and MASK constants for a field within a register */ + +/* This macro will define FOO_BAR_MASK, FOO_BAR_SHIFT and FOO_BAR_LENGTH + * constants for field BAR in register FOO. + */ +#define FIELD(reg, field, shift, length) \ + enum { R_ ## reg ## _ ## field ## _SHIFT = (shift)}; \ + enum { R_ ## reg ## _ ## field ## _LENGTH = (length)}; \ + enum { R_ ## reg ## _ ## field ## _MASK = \ + MAKE_64BIT_MASK(shift, length)}; + +/* Extract a field from a register */ +#define FIELD_EX32(storage, reg, field) \ + extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH) + +/* Extract a field from an array of registers */ +#define ARRAY_FIELD_EX32(regs, reg, field) \ + FIELD_EX32((regs)[R_ ## reg], reg, field) + +/* Deposit a register field. + * Assigning values larger then the target field will result in + * compilation warnings. + */ +#define FIELD_DP32(storage, reg, field, val) ({ \ + struct { \ + unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ + } v = { .v = val }; \ + uint32_t d; \ + d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, v.v); \ + d; }) + +/* Deposit a field to array of registers. */ +#define ARRAY_FIELD_DP32(regs, reg, field, val) \ + (regs)[R_ ## reg] = FIELD_DP32((regs)[R_ ## reg], reg, field, val); + +#endif -- cgit v1.1 From feb0b1aa11f14ee71660aba46b46387d1f923c9e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 27 Jan 2017 15:20:22 +0000 Subject: pflash_cfi01: fix per-device sector length in CFI table For configurations of the pflash_cfi01 device which set it up with a device-width not equal to the width (ie where we are emulating multiple narrow flash devices wired up in parallel), we were giving incorrect values in the CFI data table: (1) the sector length entry should specify the sector length for a single device, not the length for the overall collection of devices (2) the number of blocks per device must not be divided by the number of devices because the resulting device size would not match the overall size (3) this then means that the overall write block size must be modified depending on the number of devices because the entry is per device and when the guest writes into the flash it calculates the write size by using the CFI entry (write size per device) multiplied by the number of chips. (It would alternatively be possible to modify the write block size in the CFI table (currently hardcoded at 2048) and leave the overall write block size alone.) This commit corrects these bugs, and adds a hw-compat property to retain the old behaviour on 2.8 and earlier versions. (The only board we have which uses this sort of flash config and has machine versioning is the "virt" board -- the PC uses a single flash device and so behaviour is unaffected whether using old-multiple-chip-handling or not.) Here is a configuration example from the vexpress board: VEXPRESS_FLASH_SIZE = 64M VEXPRESS_FLASH_SECT_SIZE 256K num-blocks = VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE = 256 sector-length = 256K width = 4 device-width = 2 The code will fill the CFI entry with the following entries: num-blocks = 256 sector-length = 128K writeblock_size = 2048 This results in two chips, each with 256 * 128K = 32M device size and a write block size of 2048. A sector erase will be sent to both chips, thus 256K must be erased. When the guest sends a block write command, it will write 4096 bytes data at once (2048 per device). Signed-off-by: David Engraf Reviewed-by: Peter Maydell [PMM: cleaned up and expanded commit message] Signed-off-by: Peter Maydell --- include/hw/compat.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/hw/compat.h b/include/hw/compat.h index 34e9b4a..ee0dd1b 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -10,6 +10,10 @@ .driver = "fw_cfg_io",\ .property = "x-file-slots",\ .value = stringify(0x10),\ + },{\ + .driver = "pflash_cfi01",\ + .property = "old-multiple-chip-handling",\ + .value = "on",\ }, #define HW_COMPAT_2_7 \ -- cgit v1.1