From a8d792c24865acafb01b84f299b2850dfe00eb62 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Fri, 19 Dec 2025 23:26:01 +0000 Subject: [PATCH] firmware: add RegGen API header Change-Id: Ifb79416f91a40d0a6538ba0b4a3c7b0496543a5f --- firmware/export/reggen.h | 247 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 firmware/export/reggen.h diff --git a/firmware/export/reggen.h b/firmware/export/reggen.h new file mode 100644 index 0000000000..ce66bd718b --- /dev/null +++ b/firmware/export/reggen.h @@ -0,0 +1,247 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2025 Aidan MacDonald + * Based on headergen_v2 macro.h (see utils/regtools) + * + * 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; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __REGGEN_H__ +#define __REGGEN_H__ + +#include + +#define __REGGEN_VAR_OR1(p, s1) \ + ((p ## s1)) +#define __REGGEN_VAR_OR2(p, s1, s2) \ + ((p ## s1) | (p ## s2)) +#define __REGGEN_VAR_OR3(p, s1, s2, s3) \ + ((p ## s1) | (p ## s2) | (p ## s3)) +#define __REGGEN_VAR_OR4(p, s1, s2, s3, s4) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4)) +#define __REGGEN_VAR_OR5(p, s1, s2, s3, s4, s5) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5)) +#define __REGGEN_VAR_OR6(p, s1, s2, s3, s4, s5, s6) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6)) +#define __REGGEN_VAR_OR7(p, s1, s2, s3, s4, s5, s6, s7) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7)) +#define __REGGEN_VAR_OR8(p, s1, s2, s3, s4, s5, s6, s7, s8) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8)) +#define __REGGEN_VAR_OR9(p, s1, s2, s3, s4, s5, s6, s7, s8, s9) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9)) +#define __REGGEN_VAR_OR10(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10)) +#define __REGGEN_VAR_OR11(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11)) +#define __REGGEN_VAR_OR12(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12)) +#define __REGGEN_VAR_OR13(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13)) +#define __REGGEN_VAR_OR14(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14)) +#define __REGGEN_VAR_OR15(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14) | (p ## s15)) +#define __REGGEN_VAR_OR16(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14) | (p ## s15) | (p ## s16)) +#define __REGGEN_VAR_OR17(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14) | (p ## s15) | (p ## s16) | (p ## s17)) +#define __REGGEN_VAR_OR18(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14) | (p ## s15) | (p ## s16) | (p ## s17) | (p ## s18)) +#define __REGGEN_VAR_OR19(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14) | (p ## s15) | (p ## s16) | (p ## s17) | (p ## s18) | \ + (p ## s19)) +#define __REGGEN_VAR_OR20(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20) \ + ((p ## s1) | (p ## s2) | (p ## s3) | (p ## s4) | (p ## s5) | (p ## s6) | \ + (p ## s7) | (p ## s8) | (p ## s9) | (p ## s10) | (p ## s11) | (p ## s12) | \ + (p ## s13) | (p ## s14) | (p ## s15) | (p ## s16) | (p ## s17) | (p ## s18) | \ + (p ## s19) | (p ## s20)) + +#define __REGGEN_VAR_NARGS(...) __REGGEN_VAR_NARGS_(__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) +#define __REGGEN_VAR_NARGS_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N + +#define __REGGEN_VAR_EXPAND(macro, prefix, ...) \ + __REGGEN_VAR_EXPAND_(macro, __REGGEN_VAR_NARGS(__VA_ARGS__), prefix, __VA_ARGS__) +#define __REGGEN_VAR_EXPAND_(macro, cnt, prefix, ...) \ + __REGGEN_VAR_EXPAND__(macro, cnt, prefix, __VA_ARGS__) +#define __REGGEN_VAR_EXPAND__(macro, cnt, prefix, ...) \ + __REGGEN_VAR_EXPAND___(macro##cnt, prefix, __VA_ARGS__) +#define __REGGEN_VAR_EXPAND___(macro, prefix, ...) \ + macro(prefix, __VA_ARGS__) + +/* + * Usage: __reg_orf(register, f1(v1), f2(v2), ...) + * + * Expands to the register value where each field fi has value vi. + * Enumerated values can be obtained using the syntax: f1_V(name). + */ +#define __reg_orf(reg, ...) \ + __REGGEN_VAR_EXPAND(__REGGEN_VAR_OR, BF_##reg##_, __VA_ARGS__) + +/* + * Usage: __reg_orm(register, f1, f2, ...) + * + * Expands to a bitwise OR of the bitmask of each field fi. + */ +#define __reg_orm(reg, ...) \ + __REGGEN_VAR_EXPAND(__REGGEN_VAR_OR, BM_##reg##_, __VA_ARGS__) + +/* + * Usage: __reg_orm(register, f1(v1), f2(v2), ...) + * + * Expands to a bitwise OR of the bitmask of each field fi; the + * arguments vi are ignored. + */ +#define __reg_orfm(reg, ...) \ + __REGGEN_VAR_EXPAND(__REGGEN_VAR_OR, BFM_##reg##_, __VA_ARGS__) + +/* + * Usage: __reg_fmask(register, field) + * + * Expands to the bitmask of the specified register field. + */ +#define __reg_fmask(reg, field) \ + BM_ ## reg ## _ ## field + +/* + * Usage: __reg_fpos(register, field) + * + * Expands to the LSB bit position of the specified register field. + */ +#define __reg_fpos(reg, field) \ + BP_ ## reg ## _ ## field + +/* + * Usage: reg_vreadf(value, register, field) + * + * Extract a field of the specified register type from the + * unsigned integer 'value'. + */ +#define reg_vreadf(val, reg, field) \ + (((val) & __reg_fmask(reg, field)) >> __reg_fpos(reg, field)) + +/* + * Usage: reg_vwritef(value, register, f1(v1), f2(v2), ...) + * + * Perform a read-modify-write operation on the variable 'value', + * setting the field fi to value vi while leaving other bits of + * 'value' unchanged. 'value' will be evaluated twice, once to + * read it and once to write it. + */ +#define reg_vwritef(val, reg, ...) \ + ((val) = ((val) & ~__reg_orfm(reg, __VA_ARGS__)) | __reg_orf(reg, __VA_ARGS__)) + +/* + * Usage: reg_vassignf(value, register, f1(v1), f2(v2), ...) + * + * Perform an assignment to the variable 'value', setting the + * field fi to value vi. All uninitialized bits are set to 0. + * 'value' will be evaluated once on the left hand side of an + * assignment. + */ +#define reg_vassignf(val, reg, ...) \ + ((val) = __reg_orf(reg, __VA_ARGS__)) + +/* + * Usage: reg_var(instance) + * reg_varl(base, instance) + * + * Expands to an lvalue which can be used to read or write the + * specified register instance. The instance must have a unique + * address calculation from a root instance. If any arrayed + * instances are present in the address calculation then all + * index parameters must be provided, eg: reg_var(GPIO_MODER(0)). + * + * With the "*l" suffix, the register address is calculated by + * an offset relative to the provided base address. + */ +#define reg_var(inst) \ + (*(volatile ITTA_##inst*)ITA_##inst) +#define reg_varl(base, inst) \ + (*(volatile ITTO_##inst*)((((void*)(base)) + ITO_##inst))) + +/* + * Usage: reg_ptr(instance) + * reg_ptrl(base, instance) + * + * Like reg_var() but expands to a pointer to the register + * address instead of an lvalue. The pointer will be typed + * according to the register's word type (eg. uint32_t). + */ +#define reg_ptr(inst) \ + (®_var(inst)) +#define reg_ptrl(base, inst) \ + (®_varl((base), inst)) + +/* + * Usage: reg_read(instance) + * reg_readl(base, instance) + * + * Like reg_var() but expands to an rvalue which can be used + * to read the register instance. + */ +#define reg_read(inst) \ + (*(const volatile ITTA_##inst*)ITA_##inst) +#define reg_readl(base, inst) \ + (*(const volatile ITTO_##inst*)((((void*)(base)) + ITO_##inst))) + +/* + * Usage: reg_readf(instance, field) + * reg_readlf(base, instance, field) + */ +#define reg_readf(inst, field) \ + reg_vreadf(reg_read(inst), ITNA_##inst, field) +#define reg_readlf(base, inst, field) \ + reg_vreadf(reg_readl((base), inst), ITNO_##inst, field) + +/* + * Usage: reg_writef(instance, f1(v1), f2(v2), ...) + * reg_writelf(base, instance, f1(v1), f2(v2), ...) + */ +#define reg_writef(inst, ...) \ + reg_vwritef(reg_var(inst), ITNA_##inst, __VA_ARGS__) +#define reg_writelf(base, inst, ...) \ + reg_vwritef(reg_varl((base), inst), ITNO_##inst, __VA_ARGS__) + +/* + * Usage: reg_assignf(instance, f1(v1), f2(v2), ...) + * reg_assignlf(base, instance, f1(v1), f2(v2), ...) + */ +#define reg_assignf(inst, ...) \ + reg_vassignf(reg_var(inst), ITNA_##inst, __VA_ARGS__) +#define reg_assignlf(base, inst, ...) \ + reg_vassignf(reg_varl((base), inst), ITNO_##inst, __VA_ARGS__) + +#endif /* __REGGEN_H__ */