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 descriptor 16 * @offset: Register offset relative to base of register memory 17 * @stride: Distance between two instances, if parameterized 18 * @fcount: Number of entries in the @fmask array 19 * @fmask: Array of mask values defining position and width of fields 20 * @name: Upper-case name of the register 21 */ 22 struct 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 hardware 56 * @reg_count: Number of registers in the @reg[] array 57 * @reg: Array of register descriptors 58 */ 59 struct regs { 60 u32 reg_count; 61 const struct reg **reg; 62 }; 63 64 static 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 */ 74 static 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 */ 83 static 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 */ 94 static 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 */ 102 static 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 */ 117 static 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 */ 125 static 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 */ 131 static 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