diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2022-04-13 20:23:24 +0300 |
---|---|---|
committer | Geert Uytterhoeven <geert+renesas@glider.be> | 2022-05-05 13:02:25 +0300 |
commit | 6210905586ae7f40e6f581e963cbf298dd13d462 (patch) | |
tree | 3276ab8b6869d9764984c45e60dcb033eaabef50 /drivers/pinctrl/renesas/core.c | |
parent | 7fefb7c0594fc8f4eb88646e5eb767a56529a5a0 (diff) | |
download | linux-6210905586ae7f40e6f581e963cbf298dd13d462.tar.xz |
pinctrl: renesas: Add shorthand for reserved register fields
Currently, reserved register fields must be fully described using dummy
enum IDs (zeroes), one for each possible state (2^bits states).
Add support for describing reserved fields using negative field width
values as shorthands, thus removing the need for dummy values. Apart
from the obvious size reduction due to the removal of the dummy values,
this will also enable merging adjacent reserved fields into a single
field, reducing the number of fields to describe, and thus kernel size.
Update the checker accordingly.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/cad7c92ef039d9a4d039807efc15886a7aa862be.1649865241.git.geert+renesas@glider.be
Diffstat (limited to 'drivers/pinctrl/renesas/core.c')
-rw-r--r-- | drivers/pinctrl/renesas/core.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c index f05991eea27f..ec88fe867f09 100644 --- a/drivers/pinctrl/renesas/core.c +++ b/drivers/pinctrl/renesas/core.c @@ -13,10 +13,11 @@ #include <linux/bitops.h> #include <linux/err.h> #include <linux/errno.h> +#include <linux/init.h> #include <linux/io.h> #include <linux/ioport.h> #include <linux/kernel.h> -#include <linux/init.h> +#include <linux/math.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/machine.h> @@ -213,7 +214,7 @@ static void sh_pfc_config_reg_helper(struct sh_pfc *pfc, *maskp = (1 << crp->var_field_width[in_pos]) - 1; *posp = crp->reg_width; for (k = 0; k <= in_pos; k++) - *posp -= crp->var_field_width[k]; + *posp -= abs(crp->var_field_width[k]); } } @@ -261,14 +262,17 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id, if (!r_width) break; - for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) { + for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width, m++) { u32 ncomb; u32 n; - if (f_width) + if (f_width) { curr_width = f_width; - else - curr_width = config_reg->var_field_width[m]; + } else { + curr_width = abs(config_reg->var_field_width[m]); + if (config_reg->var_field_width[m] < 0) + continue; + } ncomb = 1 << curr_width; for (n = 0; n < ncomb; n++) { @@ -280,7 +284,6 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id, } } pos += ncomb; - m++; } k++; } @@ -874,7 +877,8 @@ static const struct sh_pfc_pin __init *sh_pfc_find_pin( static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { - unsigned int i, n, rw, fw; + unsigned int i, n, rw; + int fw; sh_pfc_check_reg(drvname, cfg_reg->reg, GENMASK(cfg_reg->reg_width - 1, 0)); @@ -887,11 +891,15 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname, } for (i = 0, n = 0, rw = 0; (fw = cfg_reg->var_field_width[i]); i++) { - if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw)) - sh_pfc_warn("reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n", - cfg_reg->reg, rw, rw + fw - 1); - n += 1 << fw; - rw += fw; + if (fw < 0) { + rw += -fw; + } else { + if (is0s(&cfg_reg->enum_ids[n], 1 << fw)) + sh_pfc_warn("reg 0x%x: field [%u:%u] can be described as reserved\n", + cfg_reg->reg, rw, rw + fw - 1); + n += 1 << fw; + rw += fw; + } } if (rw != cfg_reg->reg_width) |