diff options
Diffstat (limited to 'drivers/pinctrl/renesas/pinctrl-rzg2l.c')
-rw-r--r-- | drivers/pinctrl/renesas/pinctrl-rzg2l.c | 271 |
1 files changed, 141 insertions, 130 deletions
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index 78fa08ff0faa..f524af6f586f 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -146,8 +146,6 @@ #define SD_CH(off, ch) ((off) + (ch) * 4) #define ETH_POC(off, ch) ((off) + (ch) * 4) #define QSPI (0x3008) -#define ETH_MODE (0x3018) -#define PFC_OEN (0x3C40) /* known on RZ/V2H(P) only */ #define PVDD_2500 2 /* I/O domain voltage 2.5V */ #define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ @@ -221,11 +219,13 @@ static const struct pin_config_item renesas_rzv2h_conf_items[] = { * @pwpr: PWPR register offset * @sd_ch: SD_CH register offset * @eth_poc: ETH_POC register offset + * @oen: OEN register offset */ struct rzg2l_register_offsets { u16 pwpr; u16 sd_ch; u16 eth_poc; + u16 oen; }; /** @@ -254,6 +254,7 @@ enum rzg2l_iolh_index { * @iolh_groupb_oi: IOLH group B output impedance specific values * @tint_start_index: the start index for the TINT interrupts * @drive_strength_ua: drive strength in uA is supported (otherwise mA is supported) + * @oen_pwpr_lock: flag indicating if the OEN register is locked by PWPR * @func_base: base number for port function (see register PFC) * @oen_max_pin: the maximum pin number supporting output enable * @oen_max_port: the maximum port number supporting output enable @@ -266,6 +267,7 @@ struct rzg2l_hwcfg { u16 iolh_groupb_oi[4]; u16 tint_start_index; bool drive_strength_ua; + bool oen_pwpr_lock; u8 func_base; u8 oen_max_pin; u8 oen_max_port; @@ -295,8 +297,7 @@ struct rzg2l_pinctrl_data { #endif void (*pwpr_pfc_lock_unlock)(struct rzg2l_pinctrl *pctrl, bool lock); void (*pmc_writeb)(struct rzg2l_pinctrl *pctrl, u8 val, u16 offset); - u32 (*oen_read)(struct rzg2l_pinctrl *pctrl, unsigned int _pin); - int (*oen_write)(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oen); + int (*pin_to_oen_bit)(struct rzg2l_pinctrl *pctrl, unsigned int _pin); int (*hw_to_bias_param)(unsigned int val); int (*bias_param_to_hw)(enum pin_config_param param); }; @@ -320,9 +321,10 @@ struct rzg2l_pinctrl_pin_settings { * @iolh: IOLH registers cache * @pupd: PUPD registers cache * @ien: IEN registers cache + * @smt: SMT registers cache * @sd_ch: SD_CH registers cache * @eth_poc: ET_POC registers cache - * @eth_mode: ETH_MODE register cache + * @oen: Output Enable register cache * @qspi: QSPI registers cache */ struct rzg2l_pinctrl_reg_cache { @@ -333,9 +335,10 @@ struct rzg2l_pinctrl_reg_cache { u32 *iolh[2]; u32 *ien[2]; u32 *pupd[2]; + u32 *smt; u8 sd_ch[2]; u8 eth_poc[2]; - u8 eth_mode; + u8 oen; u8 qspi; }; @@ -394,6 +397,14 @@ static const u64 r9a09g047_variable_pin_cfg[] = { RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PA, 5, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PA, 6, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PA, 7, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 0, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 1, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_OEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 2, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 3, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 4, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 5, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 6, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PB, 7, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PD, 0, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_IEN), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PD, 1, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PD, 2, RZV2H_MPXED_PIN_FUNCS), @@ -402,6 +413,14 @@ static const u64 r9a09g047_variable_pin_cfg[] = { RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PD, 5, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PD, 6, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PD, 7, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 0, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 1, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_OEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 2, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 3, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 4, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 5, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 6, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PE, 7, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PG, 0, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PG, 1, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_IEN), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PG, 2, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_IEN), @@ -421,6 +440,14 @@ static const u64 r9a09g047_variable_pin_cfg[] = { RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PJ, 2, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PJ, 3, RZV2H_MPXED_PIN_FUNCS), RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PJ, 4, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 0, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_OEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 1, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_OEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 2, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_OEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 3, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 4, RZV2H_MPXED_PIN_FUNCS | PIN_CFG_OEN), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 5, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 6, RZV2H_MPXED_PIN_FUNCS), + RZG2L_VARIABLE_PIN_CFG_PACK(RZG3E_PL, 7, RZV2H_MPXED_PIN_FUNCS), }; static const u64 r9a09g057_variable_pin_cfg[] = { @@ -493,6 +520,23 @@ static void rzv2h_pmc_writeb(struct rzg2l_pinctrl *pctrl, u8 val, u16 offset) writeb(pwpr & ~PWPR_REGWE_A, pctrl->base + regs->pwpr); } +static int rzg2l_validate_pin(struct rzg2l_pinctrl *pctrl, + u64 cfg, u32 port, u8 bit) +{ + u8 pinmap = FIELD_GET(PIN_CFG_PIN_MAP_MASK, cfg); + u32 off = RZG2L_PIN_CFG_TO_PORT_OFFSET(cfg); + u64 data; + + if (!(pinmap & BIT(bit)) || port >= pctrl->data->n_port_pins) + return -EINVAL; + + data = pctrl->data->port_pin_configs[port]; + if (off != RZG2L_PIN_CFG_TO_PORT_OFFSET(data)) + return -EINVAL; + + return 0; +} + static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, u8 pin, u8 off, u8 func) { @@ -532,10 +576,11 @@ static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev, { struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg; - struct function_desc *func; + const struct function_desc *func; unsigned int i, *psel_val; struct group_desc *group; const unsigned int *pins; + int ret; func = pinmux_generic_get_function(pctldev, func_selector); if (!func) @@ -552,6 +597,10 @@ static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev, u32 off = RZG2L_PIN_CFG_TO_PORT_OFFSET(*pin_data); u32 pin = RZG2L_PIN_ID_TO_PIN(pins[i]); + ret = rzg2l_validate_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(pins[i]), pin); + if (ret) + return ret; + dev_dbg(pctrl->dev, "port:%u pin: %u off:%x PSEL:%u\n", RZG2L_PIN_ID_TO_PORT(pins[i]), pin, off, psel_val[i] - hwcfg->func_base); @@ -806,23 +855,6 @@ done: return ret; } -static int rzg2l_validate_gpio_pin(struct rzg2l_pinctrl *pctrl, - u64 cfg, u32 port, u8 bit) -{ - u8 pinmap = FIELD_GET(PIN_CFG_PIN_MAP_MASK, cfg); - u32 off = RZG2L_PIN_CFG_TO_PORT_OFFSET(cfg); - u64 data; - - if (!(pinmap & BIT(bit)) || port >= pctrl->data->n_port_pins) - return -EINVAL; - - data = pctrl->data->port_pin_configs[port]; - if (off != RZG2L_PIN_CFG_TO_PORT_OFFSET(data)) - return -EINVAL; - - return 0; -} - static u32 rzg2l_read_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset, u8 bit, u32 mask) { @@ -1060,34 +1092,48 @@ static int rzg2l_pin_to_oen_bit(struct rzg2l_pinctrl *pctrl, unsigned int _pin) return -EINVAL; } -static u32 rzg2l_read_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin) +static int rzg2l_read_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin) { int bit; - bit = rzg2l_pin_to_oen_bit(pctrl, _pin); + if (!pctrl->data->pin_to_oen_bit) + return -EOPNOTSUPP; + + bit = pctrl->data->pin_to_oen_bit(pctrl, _pin); if (bit < 0) - return 0; + return -EINVAL; - return !(readb(pctrl->base + ETH_MODE) & BIT(bit)); + return !(readb(pctrl->base + pctrl->data->hwcfg->regs.oen) & BIT(bit)); } static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oen) { + const struct rzg2l_register_offsets *regs = &pctrl->data->hwcfg->regs; + u16 oen_offset = pctrl->data->hwcfg->regs.oen; unsigned long flags; + u8 val, pwpr; int bit; - u8 val; - bit = rzg2l_pin_to_oen_bit(pctrl, _pin); + if (!pctrl->data->pin_to_oen_bit) + return -EOPNOTSUPP; + + bit = pctrl->data->pin_to_oen_bit(pctrl, _pin); if (bit < 0) - return bit; + return -EINVAL; spin_lock_irqsave(&pctrl->lock, flags); - val = readb(pctrl->base + ETH_MODE); + val = readb(pctrl->base + oen_offset); if (oen) val &= ~BIT(bit); else val |= BIT(bit); - writeb(val, pctrl->base + ETH_MODE); + if (pctrl->data->hwcfg->oen_pwpr_lock) { + pwpr = readb(pctrl->base + regs->pwpr); + writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); + } + writeb(val, pctrl->base + oen_offset); + if (pctrl->data->hwcfg->oen_pwpr_lock) + writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); spin_unlock_irqrestore(&pctrl->lock, flags); return 0; @@ -1113,39 +1159,6 @@ static int rzg3s_pin_to_oen_bit(struct rzg2l_pinctrl *pctrl, unsigned int _pin) return bit; } -static u32 rzg3s_oen_read(struct rzg2l_pinctrl *pctrl, unsigned int _pin) -{ - int bit; - - bit = rzg3s_pin_to_oen_bit(pctrl, _pin); - if (bit < 0) - return bit; - - return !(readb(pctrl->base + ETH_MODE) & BIT(bit)); -} - -static int rzg3s_oen_write(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oen) -{ - unsigned long flags; - int bit; - u8 val; - - bit = rzg3s_pin_to_oen_bit(pctrl, _pin); - if (bit < 0) - return bit; - - spin_lock_irqsave(&pctrl->lock, flags); - val = readb(pctrl->base + ETH_MODE); - if (oen) - val &= ~BIT(bit); - else - val |= BIT(bit); - writeb(val, pctrl->base + ETH_MODE); - spin_unlock_irqrestore(&pctrl->lock, flags); - - return 0; -} - static int rzg2l_hw_to_bias_param(unsigned int bias) { switch (bias) { @@ -1211,55 +1224,37 @@ static int rzv2h_bias_param_to_hw(enum pin_config_param param) return -EINVAL; } -static u8 rzv2h_pin_to_oen_bit(struct rzg2l_pinctrl *pctrl, unsigned int _pin) +static int rzg2l_pin_names_to_oen_bit(struct rzg2l_pinctrl *pctrl, unsigned int _pin, + const char * const pin_names[], unsigned int count) { - static const char * const pin_names[] = { "ET0_TXC_TXCLK", "ET1_TXC_TXCLK", - "XSPI0_RESET0N", "XSPI0_CS0N", - "XSPI0_CKN", "XSPI0_CKP" }; const struct pinctrl_pin_desc *pin_desc = &pctrl->desc.pins[_pin]; unsigned int i; - for (i = 0; i < ARRAY_SIZE(pin_names); i++) { + for (i = 0; i < count; i++) { if (!strcmp(pin_desc->name, pin_names[i])) return i; } - /* Should not happen. */ - return 0; + return -EINVAL; } -static u32 rzv2h_oen_read(struct rzg2l_pinctrl *pctrl, unsigned int _pin) +static int rzv2h_pin_to_oen_bit(struct rzg2l_pinctrl *pctrl, unsigned int _pin) { - u8 bit; - - bit = rzv2h_pin_to_oen_bit(pctrl, _pin); + static const char * const pin_names[] = { + "ET0_TXC_TXCLK", "ET1_TXC_TXCLK", "XSPI0_RESET0N", + "XSPI0_CS0N", "XSPI0_CKN", "XSPI0_CKP" + }; - return !(readb(pctrl->base + PFC_OEN) & BIT(bit)); + return rzg2l_pin_names_to_oen_bit(pctrl, _pin, pin_names, ARRAY_SIZE(pin_names)); } -static int rzv2h_oen_write(struct rzg2l_pinctrl *pctrl, unsigned int _pin, u8 oen) +static int rzg3e_pin_to_oen_bit(struct rzg2l_pinctrl *pctrl, unsigned int _pin) { - const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg; - const struct rzg2l_register_offsets *regs = &hwcfg->regs; - unsigned long flags; - u8 val, bit; - u8 pwpr; + static const char * const pin_names[] = { + "PB1", "PE1", "PL4", "PL1", "PL2", "PL0" + }; - bit = rzv2h_pin_to_oen_bit(pctrl, _pin); - spin_lock_irqsave(&pctrl->lock, flags); - val = readb(pctrl->base + PFC_OEN); - if (oen) - val &= ~BIT(bit); - else - val |= BIT(bit); - - pwpr = readb(pctrl->base + regs->pwpr); - writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); - writeb(val, pctrl->base + PFC_OEN); - writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); - spin_unlock_irqrestore(&pctrl->lock, flags); - - return 0; + return rzg2l_pin_names_to_oen_bit(pctrl, _pin, pin_names, ARRAY_SIZE(pin_names)); } static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, @@ -1287,7 +1282,7 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, } else { bit = RZG2L_PIN_ID_TO_PIN(_pin); - if (rzg2l_validate_gpio_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit)) + if (rzg2l_validate_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit)) return -EINVAL; } @@ -1303,11 +1298,10 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, case PIN_CONFIG_OUTPUT_ENABLE: if (!(cfg & PIN_CFG_OEN)) return -EINVAL; - if (!pctrl->data->oen_read) - return -EOPNOTSUPP; - arg = pctrl->data->oen_read(pctrl, _pin); - if (!arg) - return -EINVAL; + ret = rzg2l_read_oen(pctrl, _pin); + if (ret < 0) + return ret; + arg = ret; break; case PIN_CONFIG_POWER_SOURCE: @@ -1447,7 +1441,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, } else { bit = RZG2L_PIN_ID_TO_PIN(_pin); - if (rzg2l_validate_gpio_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit)) + if (rzg2l_validate_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit)) return -EINVAL; } @@ -1466,9 +1460,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, case PIN_CONFIG_OUTPUT_ENABLE: if (!(cfg & PIN_CFG_OEN)) return -EINVAL; - if (!pctrl->data->oen_write) - return -EOPNOTSUPP; - ret = pctrl->data->oen_write(pctrl, _pin, !!arg); + ret = rzg2l_write_oen(pctrl, _pin, !!arg); if (ret) return ret; break; @@ -1687,7 +1679,7 @@ static int rzg2l_gpio_request(struct gpio_chip *chip, unsigned int offset) u8 reg8; int ret; - ret = rzg2l_validate_gpio_pin(pctrl, *pin_data, port, bit); + ret = rzg2l_validate_pin(pctrl, *pin_data, port, bit); if (ret) return ret; @@ -1758,8 +1750,8 @@ static int rzg2l_gpio_direction_input(struct gpio_chip *chip, return 0; } -static void rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) +static int rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); const struct pinctrl_pin_desc *pin_desc = &pctrl->desc.pins[offset]; @@ -1779,6 +1771,8 @@ static void rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset, writeb(reg8 & ~BIT(bit), pctrl->base + P(off)); spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; } static int rzg2l_gpio_direction_output(struct gpio_chip *chip, @@ -2051,17 +2045,17 @@ static const u64 r9a09g047_gpio_configs[] = { RZG2L_GPIO_PORT_PACK(6, 0x28, RZV2H_MPXED_PIN_FUNCS), /* P8 */ 0x0, RZG2L_GPIO_PORT_PACK_VARIABLE(8, 0x2a), /* PA */ - RZG2L_GPIO_PORT_PACK(8, 0x2b, RZV2H_MPXED_PIN_FUNCS), /* PB */ + RZG2L_GPIO_PORT_PACK_VARIABLE(8, 0x2b), /* PB */ RZG2L_GPIO_PORT_PACK(3, 0x2c, RZV2H_MPXED_PIN_FUNCS), /* PC */ RZG2L_GPIO_PORT_PACK_VARIABLE(8, 0x2d), /* PD */ - RZG2L_GPIO_PORT_PACK(8, 0x2e, RZV2H_MPXED_PIN_FUNCS), /* PE */ + RZG2L_GPIO_PORT_PACK_VARIABLE(8, 0x2e), /* PE */ RZG2L_GPIO_PORT_PACK(3, 0x2f, RZV2H_MPXED_PIN_FUNCS), /* PF */ RZG2L_GPIO_PORT_PACK_VARIABLE(8, 0x30), /* PG */ RZG2L_GPIO_PORT_PACK_VARIABLE(6, 0x31), /* PH */ 0x0, RZG2L_GPIO_PORT_PACK_VARIABLE(5, 0x33), /* PJ */ RZG2L_GPIO_PORT_PACK(4, 0x34, RZV2H_MPXED_PIN_FUNCS), /* PK */ - RZG2L_GPIO_PORT_PACK(8, 0x35, RZV2H_MPXED_PIN_FUNCS), /* PL */ + RZG2L_GPIO_PORT_PACK_VARIABLE(8, 0x35), /* PL */ RZG2L_GPIO_PORT_PACK(8, 0x36, RZV2H_MPXED_PIN_FUNCS), /* PM */ 0x0, 0x0, @@ -2712,6 +2706,10 @@ static int rzg2l_pinctrl_reg_cache_alloc(struct rzg2l_pinctrl *pctrl) if (!cache->pfc) return -ENOMEM; + cache->smt = devm_kcalloc(pctrl->dev, nports, sizeof(*cache->smt), GFP_KERNEL); + if (!cache->smt) + return -ENOMEM; + for (u8 i = 0; i < 2; i++) { u32 n_dedicated_pins = pctrl->data->n_dedicated_pins; @@ -2973,7 +2971,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; for (u32 port = 0; port < nports; port++) { - bool has_iolh, has_ien, has_pupd; + bool has_iolh, has_ien, has_pupd, has_smt; u32 off, caps; u8 pincnt; u64 cfg; @@ -2986,6 +2984,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen has_iolh = !!(caps & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C)); has_ien = !!(caps & PIN_CFG_IEN); has_pupd = !!(caps & PIN_CFG_PUPD); + has_smt = !!(caps & PIN_CFG_SMT); if (suspend) RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PFC(off), cache->pfc[port]); @@ -3024,6 +3023,9 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen cache->ien[1][port]); } } + + if (has_smt) + RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + SMT(off), cache->smt[port]); } } @@ -3157,7 +3159,7 @@ static int rzg2l_pinctrl_suspend_noirq(struct device *dev) } cache->qspi = readb(pctrl->base + QSPI); - cache->eth_mode = readb(pctrl->base + ETH_MODE); + cache->oen = readb(pctrl->base + pctrl->data->hwcfg->regs.oen); if (!atomic_read(&pctrl->wakeup_path)) clk_disable_unprepare(pctrl->clk); @@ -3173,6 +3175,8 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev) const struct rzg2l_hwcfg *hwcfg = pctrl->data->hwcfg; const struct rzg2l_register_offsets *regs = &hwcfg->regs; struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; + unsigned long flags; + u8 pwpr; int ret; if (!atomic_read(&pctrl->wakeup_path)) { @@ -3182,7 +3186,16 @@ static int rzg2l_pinctrl_resume_noirq(struct device *dev) } writeb(cache->qspi, pctrl->base + QSPI); - writeb(cache->eth_mode, pctrl->base + ETH_MODE); + if (pctrl->data->hwcfg->oen_pwpr_lock) { + spin_lock_irqsave(&pctrl->lock, flags); + pwpr = readb(pctrl->base + regs->pwpr); + writeb(pwpr | PWPR_REGWE_B, pctrl->base + regs->pwpr); + } + writeb(cache->oen, pctrl->base + pctrl->data->hwcfg->regs.oen); + if (pctrl->data->hwcfg->oen_pwpr_lock) { + writeb(pwpr & ~PWPR_REGWE_B, pctrl->base + regs->pwpr); + spin_unlock_irqrestore(&pctrl->lock, flags); + } for (u8 i = 0; i < 2; i++) { if (regs->sd_ch) writeb(cache->sd_ch[i], pctrl->base + SD_CH(regs->sd_ch, i)); @@ -3234,6 +3247,7 @@ static const struct rzg2l_hwcfg rzg2l_hwcfg = { .pwpr = 0x3014, .sd_ch = 0x3000, .eth_poc = 0x300c, + .oen = 0x3018, }, .iolh_groupa_ua = { /* 3v3 power source */ @@ -3249,6 +3263,7 @@ static const struct rzg2l_hwcfg rzg3s_hwcfg = { .pwpr = 0x3000, .sd_ch = 0x3004, .eth_poc = 0x3010, + .oen = 0x3018, }, .iolh_groupa_ua = { /* 1v8 power source */ @@ -3280,8 +3295,10 @@ static const struct rzg2l_hwcfg rzg3s_hwcfg = { static const struct rzg2l_hwcfg rzv2h_hwcfg = { .regs = { .pwpr = 0x3c04, + .oen = 0x3c40, }, .tint_start_index = 17, + .oen_pwpr_lock = true, }; static struct rzg2l_pinctrl_data r9a07g043_data = { @@ -3298,8 +3315,7 @@ static struct rzg2l_pinctrl_data r9a07g043_data = { #endif .pwpr_pfc_lock_unlock = &rzg2l_pwpr_pfc_lock_unlock, .pmc_writeb = &rzg2l_pmc_writeb, - .oen_read = &rzg2l_read_oen, - .oen_write = &rzg2l_write_oen, + .pin_to_oen_bit = &rzg2l_pin_to_oen_bit, .hw_to_bias_param = &rzg2l_hw_to_bias_param, .bias_param_to_hw = &rzg2l_bias_param_to_hw, }; @@ -3315,8 +3331,7 @@ static struct rzg2l_pinctrl_data r9a07g044_data = { .hwcfg = &rzg2l_hwcfg, .pwpr_pfc_lock_unlock = &rzg2l_pwpr_pfc_lock_unlock, .pmc_writeb = &rzg2l_pmc_writeb, - .oen_read = &rzg2l_read_oen, - .oen_write = &rzg2l_write_oen, + .pin_to_oen_bit = &rzg2l_pin_to_oen_bit, .hw_to_bias_param = &rzg2l_hw_to_bias_param, .bias_param_to_hw = &rzg2l_bias_param_to_hw, }; @@ -3331,8 +3346,7 @@ static struct rzg2l_pinctrl_data r9a08g045_data = { .hwcfg = &rzg3s_hwcfg, .pwpr_pfc_lock_unlock = &rzg2l_pwpr_pfc_lock_unlock, .pmc_writeb = &rzg2l_pmc_writeb, - .oen_read = &rzg3s_oen_read, - .oen_write = &rzg3s_oen_write, + .pin_to_oen_bit = &rzg3s_pin_to_oen_bit, .hw_to_bias_param = &rzg2l_hw_to_bias_param, .bias_param_to_hw = &rzg2l_bias_param_to_hw, }; @@ -3354,8 +3368,7 @@ static struct rzg2l_pinctrl_data r9a09g047_data = { #endif .pwpr_pfc_lock_unlock = &rzv2h_pwpr_pfc_lock_unlock, .pmc_writeb = &rzv2h_pmc_writeb, - .oen_read = &rzv2h_oen_read, - .oen_write = &rzv2h_oen_write, + .pin_to_oen_bit = &rzg3e_pin_to_oen_bit, .hw_to_bias_param = &rzv2h_hw_to_bias_param, .bias_param_to_hw = &rzv2h_bias_param_to_hw, }; @@ -3377,8 +3390,7 @@ static struct rzg2l_pinctrl_data r9a09g056_data = { #endif .pwpr_pfc_lock_unlock = &rzv2h_pwpr_pfc_lock_unlock, .pmc_writeb = &rzv2h_pmc_writeb, - .oen_read = &rzv2h_oen_read, - .oen_write = &rzv2h_oen_write, + .pin_to_oen_bit = &rzv2h_pin_to_oen_bit, .hw_to_bias_param = &rzv2h_hw_to_bias_param, .bias_param_to_hw = &rzv2h_bias_param_to_hw, }; @@ -3401,8 +3413,7 @@ static struct rzg2l_pinctrl_data r9a09g057_data = { #endif .pwpr_pfc_lock_unlock = &rzv2h_pwpr_pfc_lock_unlock, .pmc_writeb = &rzv2h_pmc_writeb, - .oen_read = &rzv2h_oen_read, - .oen_write = &rzv2h_oen_write, + .pin_to_oen_bit = &rzv2h_pin_to_oen_bit, .hw_to_bias_param = &rzv2h_hw_to_bias_param, .bias_param_to_hw = &rzv2h_bias_param_to_hw, }; |