diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml index fb1fe1ea759f..ec5d6d52f07b 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml @@ -129,13 +129,15 @@ additionalProperties: enum: [ 33, 50, 66, 100 ] power-source: description: I/O voltage in millivolt. - enum: [ 1800, 2500, 3300 ] + enum: [ 1200, 1800, 2500, 3300 ] slew-rate: true gpio-hog: true gpios: true input: true input-enable: true + input-disable: true output-enable: true + output-disable: true output-high: true output-low: true line-name: true diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index be52d47d77ae..9bf3743dc1ce 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -69,6 +69,8 @@ #define PIN_CFG_PVDD1833_OTH_AWO_POC BIT(19) /* known on RZ/G3L only */ #define PIN_CFG_PVDD1833_OTH_ISO_POC BIT(20) /* known on RZ/G3L only */ #define PIN_CFG_WDTOVF_N_POC BIT(21) /* known on RZ/G3L only */ +#define PIN_CFG_IO_VMC_SD2 BIT(22) /* known on RZ/G3L only */ +#define PIN_CFG_IO_VMC_I3C BIT(23) #define RZG2L_SINGLE_PIN BIT_ULL(63) /* Dedicated pin */ #define RZG2L_VARIABLE_CFG BIT_ULL(62) /* Variable cfg for port pins */ @@ -180,12 +182,8 @@ #define SMT(off) (0x3400 + (off) * 8) #define SD_CH(off, ch) ((off) + (ch) * 4) #define ETH_POC(off, ch) ((off) + (ch) * 4) -#define QSPI (0x3008) /* known on RZ/{G2L,G2LC,G2UL,Five} only */ -#define OTHER_POC (0x3028) /* known on RZ/G3L only */ -#define PVDD_2500 2 /* I/O domain voltage 2.5V */ -#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ -#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */ +#define PVDD_MASK 0x3 #define PWPR_B0WI BIT(7) /* Bit Write Disable */ #define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */ @@ -254,28 +252,57 @@ static const struct pin_config_item renesas_rzv2h_conf_items[] = { * struct rzg2l_register_offsets - specific register offsets * @pwpr: PWPR register offset * @sd_ch: SD_CH register offset + * @sd_ch2: SD_CH2_POC register offset * @eth_poc: ETH_POC register offset * @oen: OEN register offset * @qspi: QSPI register offset * @other_poc: OTHER_POC register offset + * @i3c_set: I3C_SET register offset */ struct rzg2l_register_offsets { u16 pwpr; u16 sd_ch; + u16 sd_ch2; u16 eth_poc; u16 oen; u16 qspi; u16 other_poc; + u16 i3c_set; +}; + +/** + * struct rzg2l_register_masks - Masks for different RZ/G2L pinctrl functionalities + * @other_poc_pvdd1833_oth_awo_poc: PVDD1833_OTH_AWO_POC mask + * @other_poc_pvdd1833_oth_iso_poc: PVDD1833_OTH_ISO_POC mask + * @other_poc_wdtovf_n_poc: WDTOVF_N_POC mask + * @i3c_set_poc: I3C_SET_POC mask + */ +struct rzg2l_register_masks { + union { + /* RZ/G3L masks */ + struct { + u8 other_poc_pvdd1833_oth_awo_poc; + u8 other_poc_pvdd1833_oth_iso_poc; + u8 other_poc_wdtovf_n_poc; + }; + + /* RZ/G3S masks */ + struct { + u8 i3c_set_poc; + }; + }; }; /** * enum rzg2l_iolh_index - starting indices in IOLH specific arrays + * @RZG2L_IOLH_IDX_NA: index N/A (to be used for error checking) * @RZG2L_IOLH_IDX_1V8: starting index for 1V8 power source * @RZG2L_IOLH_IDX_2V5: starting index for 2V5 power source * @RZG2L_IOLH_IDX_3V3: starting index for 3V3 power source * @RZG2L_IOLH_IDX_MAX: maximum index */ enum rzg2l_iolh_index { + RZG2L_IOLH_IDX_NA = -1, RZG2L_IOLH_IDX_1V8 = 0, RZG2L_IOLH_IDX_2V5 = 4, RZG2L_IOLH_IDX_3V3 = 8, @@ -288,6 +315,8 @@ enum rzg2l_iolh_index { /** * struct rzg2l_hwcfg - hardware configuration data structure * @regs: hardware specific register offsets + * @masks: hardware specific masks for various functionalities available in + * the registers described by regs * @iolh_groupa_ua: IOLH group A uA specific values * @iolh_groupb_ua: IOLH group B uA specific values * @iolh_groupc_ua: IOLH group C uA specific values @@ -301,6 +330,7 @@ enum rzg2l_iolh_index { */ struct rzg2l_hwcfg { const struct rzg2l_register_offsets regs; + const struct rzg2l_register_masks masks; u16 iolh_groupa_ua[RZG2L_IOLH_IDX_MAX]; u16 iolh_groupb_ua[RZG2L_IOLH_IDX_MAX]; u16 iolh_groupc_ua[RZG2L_IOLH_IDX_MAX]; @@ -368,10 +398,12 @@ struct rzg2l_pinctrl_pin_settings { * @nod: NOD registers cache * @clone: Clone register cache * @sd_ch: SD_CH registers cache + * @sd_ch2: SD_CH2_POC registers cache * @eth_poc: ET_POC registers cache * @oen: Output Enable register cache * @other_poc: OTHER_POC register cache * @qspi: QSPI registers cache + * @i3c_set: I3C_SET register cache */ struct rzg2l_pinctrl_reg_cache { u8 *p; @@ -386,10 +418,12 @@ struct rzg2l_pinctrl_reg_cache { u32 *nod[2]; u32 clone; u8 sd_ch[2]; + u8 sd_ch2; u8 eth_poc[2]; u8 oen; u8 other_poc; u8 qspi; + u8 i3c_set; }; struct rzg2l_pinctrl { @@ -421,7 +455,89 @@ struct rzg2l_pinctrl { u32 clone_offset; }; -static const u16 available_ps[] = { 1800, 2500, 3300 }; +/** + * struct rzg2l_pinctrl_ps_desc - RZ/G2L power source descriptor + * @caps: Capabilities that applies to the power source + * @iolh_index: IOLH index + * @ps: Power source value + * @pwr_reg_val: Power source register value + */ +struct rzg2l_pinctrl_ps_desc { + u32 caps; + enum rzg2l_iolh_index iolh_index; + u16 ps; + u16 pwr_reg_val; +}; + +#define RZG2L_PINCTRL_PS_DESC(_ps, _pwr_reg_val, _caps, _iolh_index) \ + { \ + .ps = _ps, \ + .pwr_reg_val = _pwr_reg_val, \ + .caps = _caps, \ + .iolh_index = _iolh_index, \ + } + +static const struct rzg2l_pinctrl_ps_desc available_ps[] = { + /* Ethernet I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1, + RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(2500, 2, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1, + RZG2L_IOLH_IDX_2V5), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1, + RZG2L_IOLH_IDX_3V3), + + /* SD I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_IO_VMC_SD0 | PIN_CFG_IO_VMC_SD1 | + PIN_CFG_IO_VMC_SD2, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_IO_VMC_SD0 | PIN_CFG_IO_VMC_SD1 | + PIN_CFG_IO_VMC_SD2, RZG2L_IOLH_IDX_3V3), + + /* QSPI I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_IO_VMC_QSPI, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_IO_VMC_QSPI, RZG2L_IOLH_IDX_3V3), + + /* AWO I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_PVDD1833_OTH_AWO_POC, + RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_PVDD1833_OTH_AWO_POC, + RZG2L_IOLH_IDX_3V3), + + /* ISO I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_PVDD1833_OTH_ISO_POC, + RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_PVDD1833_OTH_ISO_POC, + RZG2L_IOLH_IDX_3V3), + + /* WDTOVF I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 1, PIN_CFG_WDTOVF_N_POC, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_WDTOVF_N_POC, RZG2L_IOLH_IDX_3V3), + + /* I3C I/O voltage domains */ + RZG2L_PINCTRL_PS_DESC(1200, 1, PIN_CFG_IO_VMC_I3C, RZG2L_IOLH_IDX_NA), + RZG2L_PINCTRL_PS_DESC(1800, 0, PIN_CFG_IO_VMC_I3C, RZG2L_IOLH_IDX_NA), + + /* Software voltage domains */ + RZG2L_PINCTRL_PS_DESC(1800, 0, PIN_CFG_SOFT_PS, RZG2L_IOLH_IDX_1V8), + RZG2L_PINCTRL_PS_DESC(2500, 0, PIN_CFG_SOFT_PS, RZG2L_IOLH_IDX_2V5), + RZG2L_PINCTRL_PS_DESC(3300, 0, PIN_CFG_SOFT_PS, RZG2L_IOLH_IDX_3V3), +}; + +#define RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(_name, _desc_member, _caps) \ +static const struct rzg2l_pinctrl_ps_desc *_name(u16 _desc_member, u32 _caps) \ +{ \ + for (unsigned int i = 0; i < ARRAY_SIZE(available_ps); i++) { \ + if (available_ps[i]._desc_member != _desc_member) \ + continue; \ + \ + if (available_ps[i].caps & _caps) \ + return &available_ps[i]; \ + } \ + \ + return NULL; \ +} + +RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(rzg2l_ps_to_desc, ps, caps) +RZG2L_PINCTRL_PS_DESC_MEMBER_TO_DESC_FUNC(rzg2l_pwr_reg_val_to_desc, pwr_reg_val, caps) static u64 rzg2l_pinctrl_get_variable_pin_cfg(struct rzg2l_pinctrl *pctrl, u64 pincfg, @@ -474,20 +590,32 @@ static const u64 r9a08g046_variable_pin_cfg[] = { RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PE, 5, RZG3L_MPXED_ETH_PIN_FUNCS(ETH1)), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PE, 6, RZG3L_MPXED_ETH_PIN_FUNCS(ETH1)), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PE, 7, RZG3L_MPXED_ETH_PIN_FUNCS(ETH1)), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 0, RZG3L_MPXED_PIN_FUNCS(B)), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 1, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 2, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 3, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 4, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 5, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 0, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IO_VMC_SD1), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 1, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 2, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 3, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | PIN_CFG_IEN | + PIN_CFG_IO_VMC_SD1), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 4, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 5, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 6, RZG3L_MPXED_PIN_FUNCS_POC(B, ISO)), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PG, 7, RZG3L_MPXED_PIN_FUNCS_POC(B, ISO)), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 0, RZG3L_MPXED_PIN_FUNCS(B)), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 1, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 2, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 3, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 4, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), - RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 5, RZG3L_MPXED_PIN_FUNCS(B) | PIN_CFG_IEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 0, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IO_VMC_SD2), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 1, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD2), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 2, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD2), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 3, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD2), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 4, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD2), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PH, 5, RZG2L_MPXED_COMMON_PIN_FUNCS(B) | + PIN_CFG_IEN | PIN_CFG_IO_VMC_SD2), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PJ, 0, RZG3L_MPXED_PIN_FUNCS(A) | PIN_CFG_IEN), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PJ, 1, RZG3L_MPXED_PIN_FUNCS(A)), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3L_PJ, 2, RZG3L_MPXED_PIN_FUNCS(A)), @@ -1047,106 +1175,125 @@ static void rzg2l_rmw_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset, } static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs, - u32 caps, u8 *mask) + const struct rzg2l_register_masks *masks, + u32 caps, u16 *offset, u8 *mask) { - if (caps & PIN_CFG_IO_VMC_SD0) - return SD_CH(regs->sd_ch, 0); - if (caps & PIN_CFG_IO_VMC_SD1) - return SD_CH(regs->sd_ch, 1); - if (caps & PIN_CFG_IO_VMC_ETH0) - return ETH_POC(regs->eth_poc, 0); - if (caps & PIN_CFG_IO_VMC_ETH1) - return ETH_POC(regs->eth_poc, 1); - if (caps & PIN_CFG_IO_VMC_QSPI) - return QSPI; - if (caps & PIN_CFG_OTHER_POC_MASK) { - if (caps & PIN_CFG_PVDD1833_OTH_AWO_POC) - *mask = BIT(0); - else if (caps & PIN_CFG_PVDD1833_OTH_ISO_POC) - *mask = BIT(1); - else - *mask = BIT(2); + *mask = PVDD_MASK; - return OTHER_POC; + if (caps & PIN_CFG_IO_VMC_SD0) { + *offset = SD_CH(regs->sd_ch, 0); + return 0; + } + if (caps & PIN_CFG_IO_VMC_SD1) { + *offset = SD_CH(regs->sd_ch, 1); + return 0; + } + if (caps & PIN_CFG_IO_VMC_SD2) { + *offset = regs->sd_ch2; + return 0; + } + if (caps & PIN_CFG_IO_VMC_ETH0) { + *offset = ETH_POC(regs->eth_poc, 0); + return 0; + } + if (caps & PIN_CFG_IO_VMC_ETH1) { + *offset = ETH_POC(regs->eth_poc, 1); + return 0; + } + if (caps & PIN_CFG_IO_VMC_QSPI) { + *offset = regs->qspi; + return 0; + } + if (caps & PIN_CFG_OTHER_POC_MASK) { + *offset = regs->other_poc; + if (caps & PIN_CFG_PVDD1833_OTH_AWO_POC) + *mask = masks->other_poc_pvdd1833_oth_awo_poc; + else if (caps & PIN_CFG_PVDD1833_OTH_ISO_POC) + *mask = masks->other_poc_pvdd1833_oth_iso_poc; + else + *mask = masks->other_poc_wdtovf_n_poc; + return 0; + } + if (caps & PIN_CFG_IO_VMC_I3C) { + *offset = regs->i3c_set; + *mask = masks->i3c_set_poc; + return 0; } return -EINVAL; } +static int rzg2l_pwr_reg_val_to_ps(u16 pwr_reg_val, u32 caps) +{ + const struct rzg2l_pinctrl_ps_desc *desc; + + desc = rzg2l_pwr_reg_val_to_desc(pwr_reg_val, caps); + if (!desc) + return -EINVAL; + + return desc->ps; +} + +static int rzg2l_ps_to_pwr_reg_val(u16 ps, u32 caps) +{ + const struct rzg2l_pinctrl_ps_desc *desc; + + desc = rzg2l_ps_to_desc(ps, caps); + if (!desc) + return -EINVAL; + + return desc->pwr_reg_val; +} + static int rzg2l_get_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps) { const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg; const struct rzg2l_register_offsets *regs = &hwcfg->regs; - u8 val, mask; - int pwr_reg; + const struct rzg2l_register_masks *masks = &hwcfg->masks; + u8 mask, val; + u16 offset; + int ret; if (caps & PIN_CFG_SOFT_PS) return pctrl->settings[pin].power_source; - pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps, &mask); - if (pwr_reg < 0) - return pwr_reg; + ret = rzg2l_caps_to_pwr_reg(regs, masks, caps, &offset, &mask); + if (ret) + return ret; - val = readb(pctrl->base + pwr_reg); - if (pwr_reg == OTHER_POC) - val = field_get(mask, val); + val = readb(pctrl->base + offset); - switch (val) { - case PVDD_1800: - return 1800; - case PVDD_2500: - return 2500; - case PVDD_3300: - return 3300; - default: - /* Should not happen. */ - return -EINVAL; - } + return rzg2l_pwr_reg_val_to_ps(field_get(mask, val), caps); } static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps, u32 ps) { const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg; const struct rzg2l_register_offsets *regs = &hwcfg->regs; - u8 poc_val, val, mask; - int pwr_reg; + const struct rzg2l_register_masks *masks = &hwcfg->masks; + u16 offset; + u8 mask; + int ret; if (caps & PIN_CFG_SOFT_PS) { pctrl->settings[pin].power_source = ps; return 0; } - switch (ps) { - case 1800: - poc_val = PVDD_1800; - break; - case 2500: - if (!(caps & (PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1))) - return -EINVAL; - poc_val = PVDD_2500; - break; - case 3300: - poc_val = PVDD_3300; - break; - default: - return -EINVAL; - } + ret = rzg2l_caps_to_pwr_reg(regs, masks, caps, &offset, &mask); + if (ret) + return ret; - pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps, &mask); - if (pwr_reg < 0) - return pwr_reg; + ret = rzg2l_ps_to_pwr_reg_val(ps, caps); + if (ret < 0) + return ret; - if (pwr_reg == OTHER_POC) { - scoped_guard(raw_spinlock_irqsave, &pctrl->lock) { - val = readb(pctrl->base + pwr_reg); - if (poc_val) - val |= mask; - else - val &= ~mask; - writeb(val, pctrl->base + pwr_reg); - } - } else { - writeb(poc_val, pctrl->base + pwr_reg); + scoped_guard(raw_spinlock_irqsave, &pctrl->lock) { + u8 tmp = readb(pctrl->base + offset); + + tmp &= ~mask; + tmp |= field_prep(mask, ret); + writeb(tmp, pctrl->base + offset); } pctrl->settings[pin].power_source = ps; @@ -1154,32 +1301,11 @@ static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps return 0; } -static bool rzg2l_ps_is_supported(u16 ps) +static enum rzg2l_iolh_index rzg2l_ps_to_iolh_idx(u16 ps, u32 caps) { - unsigned int i; + const struct rzg2l_pinctrl_ps_desc *desc = rzg2l_ps_to_desc(ps, caps); - for (i = 0; i < ARRAY_SIZE(available_ps); i++) { - if (available_ps[i] == ps) - return true; - } - - return false; -} - -static enum rzg2l_iolh_index rzg2l_ps_to_iolh_idx(u16 ps) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(available_ps); i++) { - if (available_ps[i] == ps) - break; - } - - /* - * We multiply with RZG2L_IOLH_MAX_DS_ENTRIES as we have - * RZG2L_IOLH_MAX_DS_ENTRIES DS values per power source - */ - return i * RZG2L_IOLH_MAX_DS_ENTRIES; + return desc ? desc->iolh_index : RZG2L_IOLH_IDX_NA; } static u16 rzg2l_iolh_val_to_ua(const struct rzg2l_hwcfg *hwcfg, u32 caps, u8 val) @@ -1564,7 +1690,11 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, ret = rzg2l_get_power_source(pctrl, _pin, cfg); if (ret < 0) return ret; - iolh_idx = rzg2l_ps_to_iolh_idx(ret); + + iolh_idx = rzg2l_ps_to_iolh_idx(ret, cfg); + if (iolh_idx == RZG2L_IOLH_IDX_NA) + return -EINVAL; + val = rzg2l_read_pin_config(pctrl, IOLH(off), bit, IOLH_MASK); arg = rzg2l_iolh_val_to_ua(hwcfg, cfg, iolh_idx + val); break; @@ -1760,8 +1890,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, /* Apply power source. */ if (settings.power_source != pctrl->settings[_pin].power_source) { - ret = rzg2l_ps_is_supported(settings.power_source); - if (!ret) + if (!rzg2l_ps_to_desc(settings.power_source, cfg)) return -EINVAL; /* Apply power source. */ @@ -1775,7 +1904,10 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, enum rzg2l_iolh_index iolh_idx; int val; - iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source); + iolh_idx = rzg2l_ps_to_iolh_idx(settings.power_source, cfg); + if (iolh_idx == RZG2L_IOLH_IDX_NA) + return -EINVAL; + ret = rzg2l_ds_is_supported(pctrl, cfg, iolh_idx, settings.drive_strength_ua); if (!ret) @@ -2458,6 +2590,8 @@ static const struct rzg2l_dedicated_configs rzg3s_dedicated_pins[] = { { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x2, 0, PIN_CFG_IEN) }, { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x2, 1, PIN_CFG_IEN) }, { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0x6, 0, PIN_CFG_IOLH_A | PIN_CFG_SOFT_PS) }, + { "I3C_SDA", RZG2L_SINGLE_PIN_PACK(0x9, 0, (PIN_CFG_IEN | PIN_CFG_IO_VMC_I3C)) }, + { "I3C_SCL", RZG2L_SINGLE_PIN_PACK(0x9, 1, (PIN_CFG_IEN | PIN_CFG_IO_VMC_I3C)) }, { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x10, 0, (PIN_CFG_IOLH_B | PIN_CFG_IO_VMC_SD0)) }, { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x10, 1, (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, @@ -2677,28 +2811,28 @@ static const struct rzg2l_dedicated_configs rzg3l_dedicated_pins[] = { (PIN_CFG_IOLH_A | PIN_CFG_PUPD | PIN_CFG_PVDD1833_OTH_AWO_POC)) }, { "SCIF0_TXD", RZG2L_SINGLE_PIN_PACK(0x6, 1, (PIN_CFG_IOLH_A | PIN_CFG_PUPD | PIN_CFG_PVDD1833_OTH_AWO_POC)) }, - { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x9, 0, PIN_CFG_IOLH_B) }, + { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x9, 0, PIN_CFG_IOLH_B | PIN_CFG_IO_VMC_SD0) }, { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x9, 1, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, - { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x9, 2, PIN_CFG_IOLH_B) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x9, 2, PIN_CFG_IOLH_B | PIN_CFG_IO_VMC_SD0) }, { "SD0_DS", RZG2L_SINGLE_PIN_PACK(0x9, 5, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT0", RZG2L_SINGLE_PIN_PACK(0x0a, 0, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT1", RZG2L_SINGLE_PIN_PACK(0x0a, 1, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT2", RZG2L_SINGLE_PIN_PACK(0x0a, 2, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT3", RZG2L_SINGLE_PIN_PACK(0x0a, 3, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT4", RZG2L_SINGLE_PIN_PACK(0x0a, 4, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT5", RZG2L_SINGLE_PIN_PACK(0x0a, 5, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT6", RZG2L_SINGLE_PIN_PACK(0x0a, 6, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, { "SD0_DAT7", RZG2L_SINGLE_PIN_PACK(0x0a, 7, - (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD)) }, + (PIN_CFG_IOLH_B | PIN_CFG_IEN | PIN_CFG_PUPD | PIN_CFG_IO_VMC_SD0)) }, }; static const u32 r9a08g046_clone_channel_data[] = { @@ -3672,11 +3806,16 @@ static int rzg2l_pinctrl_suspend_noirq(struct device *dev) cache->eth_poc[i] = readb(pctrl->base + ETH_POC(regs->eth_poc, i)); } + if (regs->sd_ch2) + cache->sd_ch2 = readb(pctrl->base + regs->sd_ch2); + if (regs->qspi) cache->qspi = readb(pctrl->base + regs->qspi); cache->oen = readb(pctrl->base + pctrl->data->hwcfg->regs.oen); if (regs->other_poc) cache->other_poc = readb(pctrl->base + regs->other_poc); + if (regs->i3c_set) + cache->i3c_set = readb(pctrl->base + regs->i3c_set); if (pctrl->syscon) { int ret; @@ -3719,11 +3858,16 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev) writeb(cache->qspi, pctrl->base + regs->qspi); if (regs->other_poc) writeb(cache->other_poc, pctrl->base + regs->other_poc); + if (regs->i3c_set) + writeb(cache->i3c_set, pctrl->base + regs->i3c_set); raw_spin_lock_irqsave(&pctrl->lock, flags); rzg2l_oen_write_with_pwpr(pctrl, cache->oen); raw_spin_unlock_irqrestore(&pctrl->lock, flags); + if (regs->sd_ch2) + writeb(cache->sd_ch2, pctrl->base + regs->sd_ch2); + for (u8 i = 0; i < 2; i++) { if (regs->sd_ch) writeb(cache->sd_ch[i], pctrl->base + SD_CH(regs->sd_ch, i)); @@ -3774,9 +3918,9 @@ static const struct rzg2l_hwcfg rzg2l_hwcfg = { .regs = { .pwpr = 0x3014, .sd_ch = 0x3000, + .qspi = 0x3008, .eth_poc = 0x300c, .oen = 0x3018, - .qspi = QSPI, }, .iolh_groupa_ua = { /* 3v3 power source */ @@ -3791,9 +3935,15 @@ static const struct rzg2l_hwcfg rzg3l_hwcfg = { .regs = { .pwpr = 0x3000, .sd_ch = 0x3004, + .sd_ch2 = 0x3024, .eth_poc = 0x3010, .oen = 0x3018, - .other_poc = OTHER_POC, + .other_poc = 0x3028, + }, + .masks = { + .other_poc_pvdd1833_oth_awo_poc = BIT(0), + .other_poc_pvdd1833_oth_iso_poc = BIT(1), + .other_poc_wdtovf_n_poc = BIT(2), }, .iolh_groupa_ua = { /* 1v8 power source */ @@ -3826,8 +3976,12 @@ static const struct rzg2l_hwcfg rzg3s_hwcfg = { .pwpr = 0x3000, .sd_ch = 0x3004, .eth_poc = 0x3010, + .i3c_set = 0x301c, .oen = 0x3018, }, + .masks = { + .i3c_set_poc = BIT(2), + }, .iolh_groupa_ua = { /* 1v8 power source */ [RZG2L_IOLH_IDX_1V8] = 2200, 4400, 9000, 10000, diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c index eb70aee39f1a..4872a208e0c3 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c +++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c @@ -94,8 +94,8 @@ struct rzt2h_pinctrl { void __iomem *base0, *base1; struct device *dev; struct gpio_chip gpio_chip; - struct pinctrl_gpio_range gpio_range; DECLARE_BITMAP(used_irqs, RZT2H_INTERRUPTS_NUM); + u8 saved_pm[RZT2H_INTERRUPTS_NUM]; raw_spinlock_t lock; /* lock read/write registers */ struct mutex mutex; /* serialize adding groups and functions */ bool safety_port_enabled; @@ -170,6 +170,43 @@ static int rzt2h_validate_pin(struct rzt2h_pinctrl *pctrl, unsigned int offset) return (pincfg & BIT(pin)) ? 0 : -EINVAL; } +static bool rzt2h_pin_mode_is_peripheral(struct rzt2h_pinctrl *pctrl, u8 port, u8 bit) +{ + return rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit); +} + +static u8 rzt2h_pin_read_pfc(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin) +{ + u64 reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port)); + + return field_get(PFC_PIN_MASK(pin), reg64); +} + +static bool rzt2h_pin_read_input(struct rzt2h_pinctrl *pctrl, u8 port, u8 bit) +{ + return rzt2h_pinctrl_readb(pctrl, port, PIN(port)) & BIT(bit); +} + +static u8 rzt2h_pin_read_pm(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin) +{ + u16 reg = rzt2h_pinctrl_readw(pctrl, port, PM(port)); + + return field_get(PM_PIN_MASK(pin), reg); +} + +static void rzt2h_pin_write_pm(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin, + unsigned int pm) +{ + u16 reg; + + guard(raw_spinlock_irqsave)(&pctrl->lock); + + reg = rzt2h_pinctrl_readw(pctrl, port, PM(port)); + reg &= ~PM_PIN_MASK(pin); + reg |= pm << (pin * 2); + rzt2h_pinctrl_writew(pctrl, port, reg, PM(port)); +} + static void rzt2h_pinctrl_set_gpio_en(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin, bool en) { @@ -193,7 +230,7 @@ static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl, reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port)); /* Check if pin is already configured to the desired function */ - if ((rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(pin)) && + if (rzt2h_pin_mode_is_peripheral(pctrl, port, pin) && field_get(PFC_PIN_MASK(pin), reg64) == func) return; @@ -747,15 +784,7 @@ static int rzt2h_gpio_request(struct gpio_chip *chip, unsigned int offset) static void rzt2h_gpio_set_direction(struct rzt2h_pinctrl *pctrl, u32 port, u8 bit, bool output) { - u16 reg; - - guard(raw_spinlock_irqsave)(&pctrl->lock); - - reg = rzt2h_pinctrl_readw(pctrl, port, PM(port)); - reg &= ~PM_PIN_MASK(bit); - - reg |= (output ? PM_OUTPUT : PM_INPUT) << (bit * 2); - rzt2h_pinctrl_writew(pctrl, port, reg, PM(port)); + rzt2h_pin_write_pm(pctrl, port, bit, output ? PM_OUTPUT : PM_INPUT); } static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) @@ -763,9 +792,8 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip); u8 port = RZT2H_PIN_ID_TO_PORT(offset); u8 bit = RZT2H_PIN_ID_TO_PIN(offset); - u64 reg64; - u16 reg; int ret; + u8 pm; ret = rzt2h_validate_pin(pctrl, offset); if (ret) @@ -773,7 +801,7 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) guard(raw_spinlock_irqsave)(&pctrl->lock); - if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit)) { + if (rzt2h_pin_mode_is_peripheral(pctrl, port, bit)) { /* * When a GPIO is being requested as an IRQ, the pinctrl * framework expects to be able to read the GPIO's direction. @@ -783,19 +811,16 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) * called to enable the IRQ function. * Default to input direction for IRQ function. */ - reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port)); - reg64 = (reg64 >> (bit * 8)) & PFC_MASK; - if (reg64 == PFC_FUNC_INTERRUPT) + if (rzt2h_pin_read_pfc(pctrl, port, bit) == PFC_FUNC_INTERRUPT) return GPIO_LINE_DIRECTION_IN; return -EINVAL; } - reg = rzt2h_pinctrl_readw(pctrl, port, PM(port)); - reg = (reg >> (bit * 2)) & PM_MASK; - if (reg & PM_OUTPUT) + pm = rzt2h_pin_read_pm(pctrl, port, bit); + if (pm & PM_OUTPUT) return GPIO_LINE_DIRECTION_OUT; - if (reg & PM_INPUT) + if (pm & PM_INPUT) return GPIO_LINE_DIRECTION_IN; return -EINVAL; @@ -825,13 +850,15 @@ static int rzt2h_gpio_get(struct gpio_chip *chip, unsigned int offset) struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip); u8 port = RZT2H_PIN_ID_TO_PORT(offset); u8 bit = RZT2H_PIN_ID_TO_PIN(offset); - u16 reg; + u8 pm; - reg = rzt2h_pinctrl_readw(pctrl, port, PM(port)); - reg = (reg >> (bit * 2)) & PM_MASK; - if (reg & PM_INPUT) - return !!(rzt2h_pinctrl_readb(pctrl, port, PIN(port)) & BIT(bit)); - if (reg & PM_OUTPUT) + if (rzt2h_pin_mode_is_peripheral(pctrl, port, bit)) + return rzt2h_pin_read_input(pctrl, port, bit); + + pm = rzt2h_pin_read_pm(pctrl, port, bit); + if (pm & PM_INPUT) + return rzt2h_pin_read_input(pctrl, port, bit); + if (pm & PM_OUTPUT) return !!(rzt2h_pinctrl_readb(pctrl, port, P(port)) & BIT(bit)); return -EINVAL; @@ -1000,6 +1027,66 @@ static int rzt2h_gpio_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } +static int rzt2h_gpio_irq_request_resources(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + u8 port = RZT2H_PIN_ID_TO_PORT(hwirq); + u8 pin = RZT2H_PIN_ID_TO_PIN(hwirq); + u8 parent_irq, irq_idx; + int ret; + + parent_irq = rzt2h_gpio_irq_map[hwirq]; + if (parent_irq < RZT2H_INTERRUPTS_START) + return -EINVAL; + + irq_idx = parent_irq - RZT2H_INTERRUPTS_START; + if (test_and_set_bit(irq_idx, pctrl->used_irqs)) + return -EBUSY; + + /* + * rzt2h_pinctrl_set_pfc_mode() sets PM to Hi-Z before switching to the + * interrupt function, losing the previous PM value. + * Save it so it can be restored when the IRQ is freed. + */ + pctrl->saved_pm[irq_idx] = rzt2h_pin_read_pm(pctrl, port, pin); + + rzt2h_pinctrl_set_pfc_mode(pctrl, port, pin, PFC_FUNC_INTERRUPT); + + ret = gpiochip_lock_as_irq(gc, hwirq); + if (ret) { + clear_bit(irq_idx, pctrl->used_irqs); + rzt2h_pin_write_pm(pctrl, port, pin, pctrl->saved_pm[irq_idx]); + rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, true); + return ret; + } + + return 0; +} + +static void rzt2h_gpio_irq_release_resources(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + u8 port = RZT2H_PIN_ID_TO_PORT(hwirq); + u8 pin = RZT2H_PIN_ID_TO_PIN(hwirq); + u8 parent_irq, irq_idx; + + parent_irq = rzt2h_gpio_irq_map[hwirq]; + if (parent_irq < RZT2H_INTERRUPTS_START) + return; + + irq_idx = parent_irq - RZT2H_INTERRUPTS_START; + if (test_and_clear_bit(irq_idx, pctrl->used_irqs)) { + rzt2h_pin_write_pm(pctrl, port, pin, pctrl->saved_pm[irq_idx]); + rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, true); + } + + gpiochip_unlock_as_irq(gc, hwirq); +} + static const struct irq_chip rzt2h_gpio_irqchip = { .name = "rzt2h-gpio", .irq_disable = rzt2h_gpio_irq_disable, @@ -1009,9 +1096,10 @@ static const struct irq_chip rzt2h_gpio_irqchip = { .irq_set_type = irq_chip_set_type_parent, .irq_set_wake = rzt2h_gpio_irq_set_wake, .irq_eoi = irq_chip_eoi_parent, + .irq_request_resources = rzt2h_gpio_irq_request_resources, + .irq_release_resources = rzt2h_gpio_irq_release_resources, .irq_set_affinity = irq_chip_set_affinity_parent, .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int rzt2h_gpio_child_to_parent_hwirq(struct gpio_chip *gc, @@ -1020,43 +1108,17 @@ static int rzt2h_gpio_child_to_parent_hwirq(struct gpio_chip *gc, unsigned int *parent, unsigned int *parent_type) { - struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc); - u8 port = RZT2H_PIN_ID_TO_PORT(child); - u8 pin = RZT2H_PIN_ID_TO_PIN(child); - u8 parent_irq; + u8 parent_irq = rzt2h_gpio_irq_map[child]; - parent_irq = rzt2h_gpio_irq_map[child]; if (parent_irq < RZT2H_INTERRUPTS_START) return -EINVAL; - if (test_and_set_bit(parent_irq - RZT2H_INTERRUPTS_START, - pctrl->used_irqs)) - return -EBUSY; - - rzt2h_pinctrl_set_pfc_mode(pctrl, port, pin, PFC_FUNC_INTERRUPT); - *parent = parent_irq; *parent_type = child_type; return 0; } -static void rzt2h_gpio_irq_domain_free(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs) -{ - struct irq_data *d = irq_domain_get_irq_data(domain, virq); - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct rzt2h_pinctrl *pctrl = container_of(gc, struct rzt2h_pinctrl, gpio_chip); - irq_hw_number_t hwirq = irqd_to_hwirq(d); - u8 port = RZT2H_PIN_ID_TO_PORT(hwirq); - u8 pin = RZT2H_PIN_ID_TO_PIN(hwirq); - - if (test_and_clear_bit(hwirq - RZT2H_INTERRUPTS_START, pctrl->used_irqs)) - rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, false); - - irq_domain_free_irqs_common(domain, virq, nr_irqs); -} - static void rzt2h_gpio_init_irq_valid_mask(struct gpio_chip *gc, unsigned long *valid_mask, unsigned int ngpios) @@ -1072,7 +1134,6 @@ static void rzt2h_gpio_init_irq_valid_mask(struct gpio_chip *gc, static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) { - struct pinctrl_gpio_range *range = &pctrl->gpio_range; struct gpio_chip *chip = &pctrl->gpio_chip; struct device_node *np = pctrl->dev->of_node; struct irq_domain *parent_domain; @@ -1113,6 +1174,7 @@ static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) chip->direction_output = rzt2h_gpio_direction_output; chip->get = rzt2h_gpio_get; chip->set = rzt2h_gpio_set; + chip->set_config = gpiochip_generic_config; chip->label = dev_name(dev); if (of_property_present(np, "interrupt-controller")) { @@ -1122,17 +1184,9 @@ static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = rzt2h_gpio_child_to_parent_hwirq; girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell; - girq->child_irq_domain_ops.free = rzt2h_gpio_irq_domain_free; girq->init_valid_mask = rzt2h_gpio_init_irq_valid_mask; } - range->id = 0; - range->pin_base = 0; - range->base = 0; - range->npins = chip->ngpio; - range->name = chip->label; - range->gc = chip; - ret = devm_gpiochip_add_data(dev, chip, pctrl); if (ret) return dev_err_probe(dev, ret, "gpiochip registration failed\n");