Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: renesas: Add support for R-Car SoCs with pull-down only pins

Currently, the common R-Car bias handling supports pin controllers with
either:
1. Separate pin Pull-Enable (PUEN) and pin Pull-Up/Down control (PUD)
registers, for controlling both pin pull-up and pin pull-down,
2. A single pin Pull-Up control register (PUPR), for controlling pin
pull-up.

Add support for a variant of #2, where some bits in the single pin
Pull-Up control register (PUPR) control pin pull-down instead of pin
pull-up. This is the case for the "ASEBRK#/ACK" pin on R-Car M2-W,
M2-N, and E2, and the "ACK" pin on RZ/G1M, RZ/G1N, RZ/G1E, and RZ/G1C.
To describe such a register, SoC-specific drivers need to provide two
instances of pinmux_bias_reg: a first one with the puen field filled in,
listing pins with pull-up functionality, and a second one with the pud
field filled in, listing pins with pull-down functionality.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Link: https://lore.kernel.org/r/20210303132619.3938128-6-geert+renesas@glider.be

+34 -19
+32 -17
drivers/pinctrl/renesas/pinctrl.c
··· 847 847 { 848 848 unsigned int i, j; 849 849 850 - for (i = 0; pfc->info->bias_regs[i].puen; i++) { 850 + for (i = 0; pfc->info->bias_regs[i].puen || pfc->info->bias_regs[i].pud; i++) { 851 851 for (j = 0; j < ARRAY_SIZE(pfc->info->bias_regs[i].pins); j++) { 852 852 if (pfc->info->bias_regs[i].pins[j] == pin) { 853 853 *bit = j; ··· 870 870 if (!reg) 871 871 return PIN_CONFIG_BIAS_DISABLE; 872 872 873 - if (!(sh_pfc_read(pfc, reg->puen) & BIT(bit))) 874 - return PIN_CONFIG_BIAS_DISABLE; 875 - else if (!reg->pud || (sh_pfc_read(pfc, reg->pud) & BIT(bit))) 876 - return PIN_CONFIG_BIAS_PULL_UP; 877 - else 878 - return PIN_CONFIG_BIAS_PULL_DOWN; 873 + if (reg->puen) { 874 + if (!(sh_pfc_read(pfc, reg->puen) & BIT(bit))) 875 + return PIN_CONFIG_BIAS_DISABLE; 876 + else if (!reg->pud || (sh_pfc_read(pfc, reg->pud) & BIT(bit))) 877 + return PIN_CONFIG_BIAS_PULL_UP; 878 + else 879 + return PIN_CONFIG_BIAS_PULL_DOWN; 880 + } else { 881 + if (sh_pfc_read(pfc, reg->pud) & BIT(bit)) 882 + return PIN_CONFIG_BIAS_PULL_DOWN; 883 + else 884 + return PIN_CONFIG_BIAS_DISABLE; 885 + } 879 886 } 880 887 881 888 void rcar_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, ··· 896 889 if (!reg) 897 890 return; 898 891 899 - enable = sh_pfc_read(pfc, reg->puen) & ~BIT(bit); 900 - if (bias != PIN_CONFIG_BIAS_DISABLE) 901 - enable |= BIT(bit); 892 + if (reg->puen) { 893 + enable = sh_pfc_read(pfc, reg->puen) & ~BIT(bit); 894 + if (bias != PIN_CONFIG_BIAS_DISABLE) 895 + enable |= BIT(bit); 902 896 903 - if (reg->pud) { 904 - updown = sh_pfc_read(pfc, reg->pud) & ~BIT(bit); 905 - if (bias == PIN_CONFIG_BIAS_PULL_UP) 906 - updown |= BIT(bit); 897 + if (reg->pud) { 898 + updown = sh_pfc_read(pfc, reg->pud) & ~BIT(bit); 899 + if (bias == PIN_CONFIG_BIAS_PULL_UP) 900 + updown |= BIT(bit); 907 901 908 - sh_pfc_write(pfc, reg->pud, updown); 902 + sh_pfc_write(pfc, reg->pud, updown); 903 + } 904 + 905 + sh_pfc_write(pfc, reg->puen, enable); 906 + } else { 907 + enable = sh_pfc_read(pfc, reg->pud) & ~BIT(bit); 908 + if (bias == PIN_CONFIG_BIAS_PULL_DOWN) 909 + enable |= BIT(bit); 910 + 911 + sh_pfc_write(pfc, reg->pud, enable); 909 912 } 910 - 911 - sh_pfc_write(pfc, reg->puen, enable); 912 913 } 913 914 914 915 #define PORTnCR_PULMD_OFF (0 << 6)
+2 -2
drivers/pinctrl/renesas/sh_pfc.h
··· 188 188 .reg = r, \ 189 189 .fields = 190 190 191 - struct pinmux_bias_reg { 191 + struct pinmux_bias_reg { /* At least one of puen/pud must exist */ 192 192 u32 puen; /* Pull-enable or pull-up control register */ 193 - u32 pud; /* Pull-up/down control register (optional) */ 193 + u32 pud; /* Pull-up/down or pull-down control register */ 194 194 const u16 pins[32]; 195 195 }; 196 196