For fields with single bit, it's easier to declare as DEFINE_BIT(name, bit) Change-Id: If20e6b1809073b2c0dc84190edc25b207bf332b7 Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/35787 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com>
182 lines
6 KiB
C
182 lines
6 KiB
C
/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; version 2 of
|
|
* the License.
|
|
*
|
|
* This program is distributed in the hope that 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.
|
|
*/
|
|
|
|
#ifndef __DEVICE_MMIO_H__
|
|
#define __DEVICE_MMIO_H__
|
|
|
|
#include <arch/mmio.h>
|
|
#include <endian.h>
|
|
#include <types.h>
|
|
|
|
#ifndef __ROMCC__
|
|
/*
|
|
* Reads a transfer buffer from 32-bit FIFO registers. fifo_stride is the
|
|
* distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit
|
|
* registers or 0 to read everything from the same register). fifo_width is
|
|
* the amount of bytes read per register (can be 1 through 4).
|
|
*/
|
|
void buffer_from_fifo32(void *buffer, size_t size, void *fifo,
|
|
int fifo_stride, int fifo_width);
|
|
|
|
/*
|
|
* Version of buffer_to_fifo32() that can prepend a prefix of up to fifo_width
|
|
* size to the transfer. This is often useful for protocols where a command word
|
|
* precedes the actual payload data. The prefix must be packed in the low-order
|
|
* bytes of the 'prefix' u32 parameter and any high-order bytes exceeding prefsz
|
|
* must be 0. Note that 'size' counts total bytes written, including 'prefsz'.
|
|
*/
|
|
void buffer_to_fifo32_prefix(void *buffer, u32 prefix, int prefsz, size_t size,
|
|
void *fifo, int fifo_stride, int fifo_width);
|
|
|
|
/*
|
|
* Writes a transfer buffer into 32-bit FIFO registers. fifo_stride is the
|
|
* distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit
|
|
* registers or 0 to write everything into the same register). fifo_width is
|
|
* the amount of bytes written per register (can be 1 through 4).
|
|
*/
|
|
static inline void buffer_to_fifo32(void *buffer, size_t size, void *fifo,
|
|
int fifo_stride, int fifo_width)
|
|
{
|
|
buffer_to_fifo32_prefix(buffer, size, 0, 0, fifo,
|
|
fifo_stride, fifo_width);
|
|
}
|
|
|
|
/*
|
|
* Utilities to help processing bit fields.
|
|
*
|
|
* To define a bit field (usually inside a register), do:
|
|
*
|
|
* DEFINE_BITFIELD(name, high_bit, low_bit)
|
|
*
|
|
* - name: Name of the field to access.
|
|
* - high_bit: highest bit that's part of the bit field.
|
|
* - low_bit: lowest bit in the bit field.
|
|
*
|
|
* To define a field with a single bit:
|
|
*
|
|
* DEFINE_BIT(name, bit)
|
|
*
|
|
* To extract one field value from a raw reg value:
|
|
*
|
|
* EXTRACT_BITFIELD(value, name);
|
|
*
|
|
* To read from an MMIO register and extract one field from it:
|
|
*
|
|
* READ32_BITFIELD(®, name);
|
|
*
|
|
* To write into an MMIO register, set given fields (by names) to specified
|
|
* values, and all other bits to zero (usually used for resetting a register):
|
|
*
|
|
* WRITE32_BITFIELDS(®, name, value, [name, value, ...])
|
|
*
|
|
* To write into an MMIO register, set given fields (by names) to specified
|
|
* values, and leaving all others "unchanged" (usually used for updating some
|
|
* settings):
|
|
*
|
|
* SET32_BITFIELDS(®, name, value, [name, value, ...])
|
|
*
|
|
* Examples:
|
|
*
|
|
* DEFINE_BITFIELD(DISP_TYPE, 2, 1)
|
|
* DEFINE_BIT(DISP_EN, 0)
|
|
*
|
|
* SET32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 2);
|
|
* SET32_BITFIELDS(&disp_regs.ctrl, DISP_EN, 0);
|
|
*
|
|
* SET32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 1, DISP_EN, 1);
|
|
* WRITE32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 1, DISP_EN, 1);
|
|
*
|
|
* READ32_BITFIELD(®, DISP_TYPE)
|
|
* EXTRACT_BITFIELD(value, DISP_TYPE)
|
|
*
|
|
* These will be translated to:
|
|
*
|
|
* clrsetbits_le32(&disp_regs.ctrl, 0x6, 0x4);
|
|
* clrsetbits_le32(&disp_regs.ctrl, 0x1, 0x0);
|
|
*
|
|
* clrsetbits_le32(&disp_regs.ctrl, 0x7, 0x3);
|
|
* write32(&disp_regs.ctrl, 0x3);
|
|
*
|
|
* (read32(®) & 0x6) >> 1
|
|
* (value & 0x6) >> 1
|
|
*
|
|
* The {WRITE,SET}32_BITFIELDS currently only allows setting up to 8 fields at
|
|
* one invocation.
|
|
*/
|
|
|
|
#define DEFINE_BITFIELD(name, high_bit, low_bit) \
|
|
_Static_assert(high_bit >= low_bit, "invalid bit field range"); \
|
|
enum { \
|
|
name##_BITFIELD_SHIFT = (low_bit), \
|
|
name##_BITFIELD_SIZE = (high_bit) - (low_bit) + 1, \
|
|
};
|
|
|
|
#define DEFINE_BIT(name, bit) DEFINE_BITFIELD(name, bit, bit)
|
|
|
|
#define _BF_MASK(name, value) \
|
|
(((1 << name##_BITFIELD_SIZE) - 1) << name##_BITFIELD_SHIFT)
|
|
|
|
#define _BF_VALUE(name, value) \
|
|
((value) << name##_BITFIELD_SHIFT)
|
|
|
|
#define _BF_APPLY1(op, name, value, ...) (op(name, value))
|
|
#define _BF_APPLY2(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY1(op, __VA_ARGS__))
|
|
#define _BF_APPLY3(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY2(op, __VA_ARGS__))
|
|
#define _BF_APPLY4(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY3(op, __VA_ARGS__))
|
|
#define _BF_APPLY5(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY4(op, __VA_ARGS__))
|
|
#define _BF_APPLY6(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY5(op, __VA_ARGS__))
|
|
#define _BF_APPLY7(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY6(op, __VA_ARGS__))
|
|
#define _BF_APPLY8(op, name, value, ...) ((op(name, value)) | \
|
|
_BF_APPLY7(op, __VA_ARGS__))
|
|
#define _BF_APPLYINVALID(...) \
|
|
_Static_assert(0, "Invalid arguments for {WRITE,SET}*_BITFIELDS")
|
|
|
|
#define _BF_IMPL2(op, addr, \
|
|
n1, v1, n2, v2, n3, v3, n4, v4, n5, v5, n6, v6, n7, v7, n8, v8, \
|
|
NARGS, ...) \
|
|
\
|
|
op(addr, \
|
|
_BF_APPLY##NARGS(_BF_MASK, n1, v1, n2, v2, n3, v3, n4, v4, \
|
|
n5, v5, n6, v6, n7, v7, n8, v8), \
|
|
_BF_APPLY##NARGS(_BF_VALUE, n1, v1, n2, v2, n3, v3, n4, v4, \
|
|
n5, v5, n6, v6, n7, v7, n8, v8))
|
|
|
|
#define _BF_IMPL(op, addr, ...) \
|
|
_BF_IMPL2(op, addr, __VA_ARGS__, \
|
|
8, INVALID, 7, INVALID, 6, INVALID, 5, INVALID, \
|
|
4, INVALID, 3, INVALID, 2, INVALID, 1, INVALID)
|
|
|
|
#define _WRITE32_BITFIELDS_IMPL(addr, masks, values) write32(addr, values)
|
|
|
|
#define WRITE32_BITFIELDS(addr, ...) \
|
|
_BF_IMPL(_WRITE32_BITFIELDS_IMPL, addr, __VA_ARGS__)
|
|
|
|
#define SET32_BITFIELDS(addr, ...) \
|
|
_BF_IMPL(clrsetbits_le32, addr, __VA_ARGS__)
|
|
|
|
#define EXTRACT_BITFIELD(value, name) \
|
|
(((value) & _BF_MASK(name, 0)) >> name##_BITFIELD_SHIFT)
|
|
|
|
#define READ32_BITFIELD(addr, name) \
|
|
EXTRACT_BITFIELD(read32(addr), name)
|
|
|
|
#endif /* !__ROMCC__ */
|
|
|
|
#endif /* __DEVICE_MMIO_H__ */
|