diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2021-12-23 15:56:23 +0100 |
---|---|---|
committer | Geert Uytterhoeven <geert+renesas@glider.be> | 2022-02-22 09:57:19 +0100 |
commit | 854476b8562a1567fe640360e03d8e3a4d6b8d80 (patch) | |
tree | a972f945c2ce4ce90b4b4886923c9a98d0b6ea31 | |
parent | 4eb5a6eee7d1949f097af060e81e053026e0c8b2 (diff) | |
download | linux-854476b8562a1567fe640360e03d8e3a4d6b8d80.tar.bz2 |
pinctrl: renesas: checker: Validate drive strength configs consistency
Validate consistency of the pin control tables for pins with drive
strength capabilities. If a pin has drive strength register bits
declarations in drive_regs[], the SH_PFC_PIN_CFG_DRIVE_STRENGTH flag
should be set in the pin's configs, and vice versa.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/0d5de01b5fe2c5fd23c3bea41077dc57ad105b9e.1640270559.git.geert+renesas@glider.be
-rw-r--r-- | drivers/pinctrl/renesas/core.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c index dce511a22b31..1789c96ad2aa 100644 --- a/drivers/pinctrl/renesas/core.c +++ b/drivers/pinctrl/renesas/core.c @@ -746,6 +746,7 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } static unsigned int sh_pfc_errors __initdata; static unsigned int sh_pfc_warnings __initdata; static bool sh_pfc_bias_done __initdata; +static bool sh_pfc_drive_done __initdata; static struct { u32 reg; u32 bits; @@ -901,6 +902,8 @@ check_enum_ids: static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, const struct pinmux_drive_reg *drive) { + const char *drvname = info->name; + const struct sh_pfc_pin *pin; unsigned int i; for (i = 0; i < ARRAY_SIZE(drive->fields); i++) { @@ -913,7 +916,10 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, GENMASK(field->offset + field->size - 1, field->offset)); - sh_pfc_find_pin(info, drive->reg, field->pin); + pin = sh_pfc_find_pin(info, drive->reg, field->pin); + if (pin && !(pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH)) + sh_pfc_err("drive_reg 0x%x: field %u: pin %s lacks SH_PFC_PIN_CFG_DRIVE_STRENGTH flag\n", + drive->reg, i, pin->name); } } @@ -992,6 +998,7 @@ static void __init sh_pfc_compare_groups(const char *drvname, static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) { + const struct pinmux_drive_reg *drive_regs = info->drive_regs; const struct pinmux_bias_reg *bias_regs = info->bias_regs; const char *drvname = info->name; unsigned int *refcnts; @@ -1001,6 +1008,7 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) sh_pfc_num_regs = 0; sh_pfc_num_enums = 0; sh_pfc_bias_done = false; + sh_pfc_drive_done = false; /* Check pins */ for (i = 0; i < info->nr_pins; i++) { @@ -1054,6 +1062,26 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) sh_pfc_err("pin %s: SH_PFC_PIN_CFG_PULL_DOWN flag set but pin not in bias_regs\n", pin->name); } + + if (pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH) { + if (!drive_regs) { + sh_pfc_err_once(drive, "SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but drive_regs missing\n"); + } else { + for (j = 0; drive_regs[j / 8].reg; j++) { + if (!drive_regs[j / 8].fields[j % 8].pin && + !drive_regs[j / 8].fields[j % 8].offset && + !drive_regs[j / 8].fields[j % 8].size) + continue; + + if (drive_regs[j / 8].fields[j % 8].pin == pin->pin) + break; + } + + if (!drive_regs[j / 8].reg) + sh_pfc_err("pin %s: SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but not in drive_regs\n", + pin->name); + } + } } /* Check groups and functions */ |