137 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2 3/* Copyright (C) 2022-2024 Linaro Ltd. */4 5#ifndef _REG_H_6#define _REG_H_7 8#include <linux/array_size.h>9#include <linux/bits.h>10#include <linux/bug.h>11#include <linux/log2.h>12#include <linux/types.h>13 14/**15 * struct reg - A register descriptor16 * @offset: Register offset relative to base of register memory17 * @stride: Distance between two instances, if parameterized18 * @fcount: Number of entries in the @fmask array19 * @fmask: Array of mask values defining position and width of fields20 * @name: Upper-case name of the register21 */22struct reg {23 u32 offset;24 u32 stride;25 u32 fcount;26 const u32 *fmask; /* BIT(nr) or GENMASK(h, l) */27 const char *name;28};29 30/* Helper macro for defining "simple" (non-parameterized) registers */31#define REG(__NAME, __reg_id, __offset) \32 REG_STRIDE(__NAME, __reg_id, __offset, 0)33 34/* Helper macro for defining parameterized registers, specifying stride */35#define REG_STRIDE(__NAME, __reg_id, __offset, __stride) \36 static const struct reg reg_ ## __reg_id = { \37 .name = #__NAME, \38 .offset = __offset, \39 .stride = __stride, \40 }41 42#define REG_FIELDS(__NAME, __name, __offset) \43 REG_STRIDE_FIELDS(__NAME, __name, __offset, 0)44 45#define REG_STRIDE_FIELDS(__NAME, __name, __offset, __stride) \46 static const struct reg reg_ ## __name = { \47 .name = #__NAME, \48 .offset = __offset, \49 .stride = __stride, \50 .fcount = ARRAY_SIZE(reg_ ## __name ## _fmask), \51 .fmask = reg_ ## __name ## _fmask, \52 }53 54/**55 * struct regs - Description of registers supported by hardware56 * @reg_count: Number of registers in the @reg[] array57 * @reg: Array of register descriptors58 */59struct regs {60 u32 reg_count;61 const struct reg **reg;62};63 64static inline const struct reg *reg(const struct regs *regs, u32 reg_id)65{66 if (WARN(reg_id >= regs->reg_count,67 "reg out of range (%u > %u)\n", reg_id, regs->reg_count - 1))68 return NULL;69 70 return regs->reg[reg_id];71}72 73/* Return the field mask for a field in a register, or 0 on error */74static inline u32 reg_fmask(const struct reg *reg, u32 field_id)75{76 if (!reg || WARN_ON(field_id >= reg->fcount))77 return 0;78 79 return reg->fmask[field_id];80}81 82/* Return the mask for a single-bit field in a register, or 0 on error */83static inline u32 reg_bit(const struct reg *reg, u32 field_id)84{85 u32 fmask = reg_fmask(reg, field_id);86 87 if (WARN_ON(!is_power_of_2(fmask)))88 return 0;89 90 return fmask;91}92 93/* Return the maximum value representable by the given field; always 2^n - 1 */94static inline u32 reg_field_max(const struct reg *reg, u32 field_id)95{96 u32 fmask = reg_fmask(reg, field_id);97 98 return fmask ? fmask >> __ffs(fmask) : 0;99}100 101/* Encode a value into the given field of a register */102static inline u32 reg_encode(const struct reg *reg, u32 field_id, u32 val)103{104 u32 fmask = reg_fmask(reg, field_id);105 106 if (!fmask)107 return 0;108 109 val <<= __ffs(fmask);110 if (WARN_ON(val & ~fmask))111 return 0;112 113 return val;114}115 116/* Given a register value, decode (extract) the value in the given field */117static inline u32 reg_decode(const struct reg *reg, u32 field_id, u32 val)118{119 u32 fmask = reg_fmask(reg, field_id);120 121 return fmask ? (val & fmask) >> __ffs(fmask) : 0;122}123 124/* Returns 0 for NULL reg; warning should have already been issued */125static inline u32 reg_offset(const struct reg *reg)126{127 return reg ? reg->offset : 0;128}129 130/* Returns 0 for NULL reg; warning should have already been issued */131static inline u32 reg_n_offset(const struct reg *reg, u32 n)132{133 return reg ? reg->offset + n * reg->stride : 0;134}135 136#endif /* _REG_H_ */137