pinctrl: renesas: rzg2l: Add output enable support
Some of the Ethernet pins on RZ/G3S (but also valid for RZ/G2L) need to have the direction of the IO buffer set as output for Ethernet to work properly. On RZ/G3S, these pins are P1_0/P7_0, P1_1/P7_1, and can have the following Ethernet functions: TXC/TX_CLK or TX_CTL/TX_EN. As the pins supporting output enable are SoC specific, and there is a limited number of these pins (TXC/TX_CLK and/or TX_CTL/TX_EN), specify output enable capable port limits in the platform-based configuration data structure, to ensure proper validation. The OEN support has been intantiated for RZ/G3S at the moment. Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/r/20231207070700.4156557-7-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
parent
51996952b8
commit
1bbc8ee408
@ -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 | \
|
||||
@ -109,6 +110,7 @@
|
||||
#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 */
|
||||
@ -170,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;
|
||||
@ -179,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 {
|
||||
@ -782,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)
|
||||
@ -819,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)
|
||||
@ -920,6 +992,13 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
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;
|
||||
@ -1364,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, /* 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 |
|
||||
@ -1374,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, /* 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 |
|
||||
@ -1956,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