pinctrl: renesas: Updates for v6.8 (take two)
- Add pinmux groups, power source, and input/output enable support for Ethernet pins on RZ/G2L SoCs, - Miscellaneous fixes and improvements. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCZXxCWwAKCRCKwlD9ZEnx cGH/APsEC7rILFNMeP4o25rQHbqf/xIx+6KBZIXjH+ia+4uFJwEAkljmLIupZ7BB L3QlxtdIk87wvzh5ZLfL9g4IK+ig2gk= =5+7i -----END PGP SIGNATURE----- Merge tag 'renesas-pinctrl-for-v6.8-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into devel pinctrl: renesas: Updates for v6.8 (take two) - Add pinmux groups, power source, and input/output enable support for Ethernet pins on RZ/G2L SoCs, - Miscellaneous fixes and improvements. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
commit
84e769e67e
@ -57,6 +57,7 @@
|
||||
#define PIN_CFG_FILCLKSEL BIT(12)
|
||||
#define PIN_CFG_IOLH_C BIT(13)
|
||||
#define PIN_CFG_SOFT_PS BIT(14)
|
||||
#define PIN_CFG_OEN BIT(15)
|
||||
|
||||
#define RZG2L_MPXED_COMMON_PIN_FUNCS(group) \
|
||||
(PIN_CFG_IOLH_##group | \
|
||||
@ -107,8 +108,11 @@
|
||||
#define IEN(off) (0x1800 + (off) * 8)
|
||||
#define ISEL(off) (0x2C00 + (off) * 8)
|
||||
#define SD_CH(off, ch) ((off) + (ch) * 4)
|
||||
#define ETH_POC(off, ch) ((off) + (ch) * 4)
|
||||
#define QSPI (0x3008)
|
||||
#define ETH_MODE (0x3018)
|
||||
|
||||
#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 */
|
||||
|
||||
@ -116,7 +120,6 @@
|
||||
#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
|
||||
|
||||
#define PM_MASK 0x03
|
||||
#define PVDD_MASK 0x01
|
||||
#define PFC_MASK 0x07
|
||||
#define IEN_MASK 0x01
|
||||
#define IOLH_MASK 0x03
|
||||
@ -135,10 +138,12 @@
|
||||
* struct rzg2l_register_offsets - specific register offsets
|
||||
* @pwpr: PWPR register offset
|
||||
* @sd_ch: SD_CH register offset
|
||||
* @eth_poc: ETH_POC register offset
|
||||
*/
|
||||
struct rzg2l_register_offsets {
|
||||
u16 pwpr;
|
||||
u16 sd_ch;
|
||||
u16 eth_poc;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -167,6 +172,8 @@ enum rzg2l_iolh_index {
|
||||
* @iolh_groupb_oi: IOLH group B output impedance specific values
|
||||
* @drive_strength_ua: drive strength in uA is supported (otherwise mA is supported)
|
||||
* @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
|
||||
*/
|
||||
struct rzg2l_hwcfg {
|
||||
const struct rzg2l_register_offsets regs;
|
||||
@ -176,6 +183,8 @@ struct rzg2l_hwcfg {
|
||||
u16 iolh_groupb_oi[4];
|
||||
bool drive_strength_ua;
|
||||
u8 func_base;
|
||||
u8 oen_max_pin;
|
||||
u8 oen_max_port;
|
||||
};
|
||||
|
||||
struct rzg2l_dedicated_configs {
|
||||
@ -376,8 +385,11 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (num_pinmux)
|
||||
if (num_pinmux) {
|
||||
nmaps += 1;
|
||||
if (num_configs)
|
||||
nmaps += 1;
|
||||
}
|
||||
|
||||
if (num_pins)
|
||||
nmaps += num_pins;
|
||||
@ -462,6 +474,16 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
maps[idx].data.mux.function = name;
|
||||
idx++;
|
||||
|
||||
if (num_configs) {
|
||||
ret = rzg2l_map_add_config(&maps[idx], name,
|
||||
PIN_MAP_TYPE_CONFIGS_GROUP,
|
||||
configs, num_configs);
|
||||
if (ret < 0)
|
||||
goto remove_group;
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
|
||||
ret = 0;
|
||||
goto done;
|
||||
@ -591,6 +613,10 @@ static int rzg2l_caps_to_pwr_reg(const struct rzg2l_register_offsets *regs, u32
|
||||
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;
|
||||
|
||||
@ -602,6 +628,7 @@ 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;
|
||||
int pwr_reg;
|
||||
u8 val;
|
||||
|
||||
if (caps & PIN_CFG_SOFT_PS)
|
||||
return pctrl->settings[pin].power_source;
|
||||
@ -610,7 +637,18 @@ static int rzg2l_get_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps
|
||||
if (pwr_reg < 0)
|
||||
return pwr_reg;
|
||||
|
||||
return (readl(pctrl->base + pwr_reg) & PVDD_MASK) ? 1800 : 3300;
|
||||
val = readb(pctrl->base + pwr_reg);
|
||||
switch (val) {
|
||||
case PVDD_1800:
|
||||
return 1800;
|
||||
case PVDD_2500:
|
||||
return 2500;
|
||||
case PVDD_3300:
|
||||
return 3300;
|
||||
default:
|
||||
/* Should not happen. */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps, u32 ps)
|
||||
@ -618,17 +656,32 @@ static int rzg2l_set_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;
|
||||
int pwr_reg;
|
||||
u8 val;
|
||||
|
||||
if (caps & PIN_CFG_SOFT_PS) {
|
||||
pctrl->settings[pin].power_source = ps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ps) {
|
||||
case 1800:
|
||||
val = PVDD_1800;
|
||||
break;
|
||||
case 2500:
|
||||
val = PVDD_2500;
|
||||
break;
|
||||
case 3300:
|
||||
val = PVDD_3300;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pwr_reg = rzg2l_caps_to_pwr_reg(regs, caps);
|
||||
if (pwr_reg < 0)
|
||||
return pwr_reg;
|
||||
|
||||
writel((ps == 1800) ? PVDD_1800 : PVDD_3300, pctrl->base + pwr_reg);
|
||||
writeb(val, pctrl->base + pwr_reg);
|
||||
pctrl->settings[pin].power_source = ps;
|
||||
|
||||
return 0;
|
||||
@ -735,6 +788,66 @@ static bool rzg2l_ds_is_supported(struct rzg2l_pinctrl *pctrl, u32 caps,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rzg2l_oen_is_supported(u32 caps, u8 pin, u8 max_pin)
|
||||
{
|
||||
if (!(caps & PIN_CFG_OEN))
|
||||
return false;
|
||||
|
||||
if (pin > max_pin)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u8 rzg2l_pin_to_oen_bit(u32 offset, u8 pin, u8 max_port)
|
||||
{
|
||||
if (pin)
|
||||
pin *= 2;
|
||||
|
||||
if (offset / RZG2L_PINS_PER_PORT == max_port)
|
||||
pin += 1;
|
||||
|
||||
return pin;
|
||||
}
|
||||
|
||||
static u32 rzg2l_read_oen(struct rzg2l_pinctrl *pctrl, u32 caps, u32 offset, u8 pin)
|
||||
{
|
||||
u8 max_port = pctrl->data->hwcfg->oen_max_port;
|
||||
u8 max_pin = pctrl->data->hwcfg->oen_max_pin;
|
||||
u8 bit;
|
||||
|
||||
if (!rzg2l_oen_is_supported(caps, pin, max_pin))
|
||||
return 0;
|
||||
|
||||
bit = rzg2l_pin_to_oen_bit(offset, pin, max_port);
|
||||
|
||||
return !(readb(pctrl->base + ETH_MODE) & BIT(bit));
|
||||
}
|
||||
|
||||
static int rzg2l_write_oen(struct rzg2l_pinctrl *pctrl, u32 caps, u32 offset, u8 pin, u8 oen)
|
||||
{
|
||||
u8 max_port = pctrl->data->hwcfg->oen_max_port;
|
||||
u8 max_pin = pctrl->data->hwcfg->oen_max_pin;
|
||||
unsigned long flags;
|
||||
u8 val, bit;
|
||||
|
||||
if (!rzg2l_oen_is_supported(caps, pin, max_pin))
|
||||
return -EINVAL;
|
||||
|
||||
bit = rzg2l_pin_to_oen_bit(offset, pin, max_port);
|
||||
|
||||
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_pinctrl_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int _pin,
|
||||
unsigned long *config)
|
||||
@ -772,6 +885,12 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
arg = rzg2l_read_oen(pctrl, cfg, _pin, bit);
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_POWER_SOURCE:
|
||||
ret = rzg2l_get_power_source(pctrl, _pin, cfg);
|
||||
if (ret < 0)
|
||||
@ -842,7 +961,7 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
struct rzg2l_pinctrl_pin_settings settings = pctrl->settings[_pin];
|
||||
unsigned int *pin_data = pin->drv_data;
|
||||
enum pin_config_param param;
|
||||
unsigned int i;
|
||||
unsigned int i, arg, index;
|
||||
u32 cfg, off;
|
||||
int ret;
|
||||
u8 bit;
|
||||
@ -864,24 +983,28 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(_configs[i]);
|
||||
switch (param) {
|
||||
case PIN_CONFIG_INPUT_ENABLE: {
|
||||
unsigned int arg =
|
||||
pinconf_to_config_argument(_configs[i]);
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
arg = pinconf_to_config_argument(_configs[i]);
|
||||
|
||||
if (!(cfg & PIN_CFG_IEN))
|
||||
return -EINVAL;
|
||||
|
||||
rzg2l_rmw_pin_config(pctrl, IEN(off), bit, IEN_MASK, !!arg);
|
||||
break;
|
||||
}
|
||||
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
arg = pinconf_to_config_argument(_configs[i]);
|
||||
ret = rzg2l_write_oen(pctrl, cfg, _pin, bit, !!arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_POWER_SOURCE:
|
||||
settings.power_source = pinconf_to_config_argument(_configs[i]);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_DRIVE_STRENGTH: {
|
||||
unsigned int arg = pinconf_to_config_argument(_configs[i]);
|
||||
unsigned int index;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
arg = pinconf_to_config_argument(_configs[i]);
|
||||
|
||||
if (!(cfg & PIN_CFG_IOLH_A) || hwcfg->drive_strength_ua)
|
||||
return -EINVAL;
|
||||
@ -896,7 +1019,6 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
|
||||
rzg2l_rmw_pin_config(pctrl, IOLH(off), bit, IOLH_MASK, index);
|
||||
break;
|
||||
}
|
||||
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
if (!(cfg & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C)) ||
|
||||
@ -906,9 +1028,8 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
settings.drive_strength_ua = pinconf_to_config_argument(_configs[i]);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS: {
|
||||
unsigned int arg = pinconf_to_config_argument(_configs[i]);
|
||||
unsigned int index;
|
||||
case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS:
|
||||
arg = pinconf_to_config_argument(_configs[i]);
|
||||
|
||||
if (!(cfg & PIN_CFG_IOLH_B) || !hwcfg->iolh_groupb_oi[0])
|
||||
return -EINVAL;
|
||||
@ -922,7 +1043,6 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
|
||||
rzg2l_rmw_pin_config(pctrl, IOLH(off), bit, IOLH_MASK, index);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@ -1323,7 +1443,8 @@ static const u32 r9a07g043_gpio_configs[] = {
|
||||
static const u32 r9a08g045_gpio_configs[] = {
|
||||
RZG2L_GPIO_PORT_PACK(4, 0x20, RZG3S_MPXED_PIN_FUNCS(A)), /* P0 */
|
||||
RZG2L_GPIO_PORT_PACK(5, 0x30, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_C |
|
||||
PIN_CFG_IO_VMC_ETH0)), /* P1 */
|
||||
PIN_CFG_IO_VMC_ETH0)) |
|
||||
PIN_CFG_OEN | PIN_CFG_IEN, /* P1 */
|
||||
RZG2L_GPIO_PORT_PACK(4, 0x31, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_C |
|
||||
PIN_CFG_IO_VMC_ETH0)), /* P2 */
|
||||
RZG2L_GPIO_PORT_PACK(4, 0x32, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_C |
|
||||
@ -1333,7 +1454,8 @@ static const u32 r9a08g045_gpio_configs[] = {
|
||||
RZG2L_GPIO_PORT_PACK(5, 0x21, RZG3S_MPXED_PIN_FUNCS(A)), /* P5 */
|
||||
RZG2L_GPIO_PORT_PACK(5, 0x22, RZG3S_MPXED_PIN_FUNCS(A)), /* P6 */
|
||||
RZG2L_GPIO_PORT_PACK(5, 0x34, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_C |
|
||||
PIN_CFG_IO_VMC_ETH1)), /* P7 */
|
||||
PIN_CFG_IO_VMC_ETH1)) |
|
||||
PIN_CFG_OEN | PIN_CFG_IEN, /* P7 */
|
||||
RZG2L_GPIO_PORT_PACK(5, 0x35, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_C |
|
||||
PIN_CFG_IO_VMC_ETH1)), /* P8 */
|
||||
RZG2L_GPIO_PORT_PACK(4, 0x36, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_C |
|
||||
@ -1878,6 +2000,7 @@ static const struct rzg2l_hwcfg rzg2l_hwcfg = {
|
||||
.regs = {
|
||||
.pwpr = 0x3014,
|
||||
.sd_ch = 0x3000,
|
||||
.eth_poc = 0x300c,
|
||||
},
|
||||
.iolh_groupa_ua = {
|
||||
/* 3v3 power source */
|
||||
@ -1890,6 +2013,7 @@ static const struct rzg2l_hwcfg rzg3s_hwcfg = {
|
||||
.regs = {
|
||||
.pwpr = 0x3000,
|
||||
.sd_ch = 0x3004,
|
||||
.eth_poc = 0x3010,
|
||||
},
|
||||
.iolh_groupa_ua = {
|
||||
/* 1v8 power source */
|
||||
@ -1913,6 +2037,8 @@ static const struct rzg2l_hwcfg rzg3s_hwcfg = {
|
||||
},
|
||||
.drive_strength_ua = true,
|
||||
.func_base = 1,
|
||||
.oen_max_pin = 1, /* Pin 1 of P0 and P7 is the maximum OEN pin. */
|
||||
.oen_max_port = 7, /* P7_1 is the maximum OEN port. */
|
||||
};
|
||||
|
||||
static struct rzg2l_pinctrl_data r9a07g043_data = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user