drivers: pinctrl: pfc_rcar: add support of voltage control to pfc driver
Add support of voltage control to Renesas PFC driver. Voltage register mappings have been added to r8a77951 and r8a77961 SoCs. Allow 'power-source' property for 'renesas,rcar-pfc' node. This property will be used for configuring IO voltage on appropriate pin. For now it is possible to have only two voltages: 1.8 and 3.3. Note: it is possible to change voltage only for SD/MMC pins on r8a77951 and r8a77961 SoCs. Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
This commit is contained in:
parent
b8008c4727
commit
72758f96d1
6 changed files with 139 additions and 0 deletions
|
@ -7,3 +7,8 @@ config PINCTRL_RCAR_PFC
|
||||||
depends on DT_HAS_RENESAS_RCAR_PFC_ENABLED
|
depends on DT_HAS_RENESAS_RCAR_PFC_ENABLED
|
||||||
help
|
help
|
||||||
Enable pin controller driver for Renesas RCar SoC
|
Enable pin controller driver for Renesas RCar SoC
|
||||||
|
|
||||||
|
config PINCTRL_RCAR_VOLTAGE_CONTROL
|
||||||
|
bool "Voltage control functionality of Renesas R-Car PFC driver"
|
||||||
|
default y if SOC_SERIES_RCAR_GEN3
|
||||||
|
depends on PINCTRL_RCAR_PFC
|
||||||
|
|
|
@ -35,6 +35,14 @@ static const uintptr_t reg_base[] = {
|
||||||
#error Unsupported SoC Series
|
#error Unsupported SoC Series
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PINCTRL_RCAR_VOLTAGE_CONTROL
|
||||||
|
/* POC Control Register can control IO voltage level that is supplied to the pin */
|
||||||
|
struct pfc_pocctrl_reg {
|
||||||
|
uint32_t offset;
|
||||||
|
const uint16_t pins[32];
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_PINCTRL_RCAR_VOLTAGE_CONTROL */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each drive step is either encoded in 2 or 3 bits.
|
* Each drive step is either encoded in 2 or 3 bits.
|
||||||
* So based on a 24 mA maximum value each step is either
|
* So based on a 24 mA maximum value each step is either
|
||||||
|
@ -189,6 +197,110 @@ int pfc_rcar_set_bias(uintptr_t pfc_base, uint16_t pin, uint16_t flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PINCTRL_RCAR_VOLTAGE_CONTROL
|
||||||
|
|
||||||
|
const struct pfc_pocctrl_reg pfc_r8a77951_r8a77961_volt_regs[] = {
|
||||||
|
{
|
||||||
|
.offset = 0x0380,
|
||||||
|
.pins = {
|
||||||
|
[0] = RCAR_GP_PIN(3, 0), /* SD0_CLK */
|
||||||
|
[1] = RCAR_GP_PIN(3, 1), /* SD0_CMD */
|
||||||
|
[2] = RCAR_GP_PIN(3, 2), /* SD0_DAT0 */
|
||||||
|
[3] = RCAR_GP_PIN(3, 3), /* SD0_DAT1 */
|
||||||
|
[4] = RCAR_GP_PIN(3, 4), /* SD0_DAT2 */
|
||||||
|
[5] = RCAR_GP_PIN(3, 5), /* SD0_DAT3 */
|
||||||
|
[6] = RCAR_GP_PIN(3, 6), /* SD1_CLK */
|
||||||
|
[7] = RCAR_GP_PIN(3, 7), /* SD1_CMD */
|
||||||
|
[8] = RCAR_GP_PIN(3, 8), /* SD1_DAT0 */
|
||||||
|
[9] = RCAR_GP_PIN(3, 9), /* SD1_DAT1 */
|
||||||
|
[10] = RCAR_GP_PIN(3, 10), /* SD1_DAT2 */
|
||||||
|
[11] = RCAR_GP_PIN(3, 11), /* SD1_DAT3 */
|
||||||
|
[12] = RCAR_GP_PIN(4, 0), /* SD2_CLK */
|
||||||
|
[13] = RCAR_GP_PIN(4, 1), /* SD2_CMD */
|
||||||
|
[14] = RCAR_GP_PIN(4, 2), /* SD2_DAT0 */
|
||||||
|
[15] = RCAR_GP_PIN(4, 3), /* SD2_DAT1 */
|
||||||
|
[16] = RCAR_GP_PIN(4, 4), /* SD2_DAT2 */
|
||||||
|
[17] = RCAR_GP_PIN(4, 5), /* SD2_DAT3 */
|
||||||
|
[18] = RCAR_GP_PIN(4, 6), /* SD2_DS */
|
||||||
|
[19] = RCAR_GP_PIN(4, 7), /* SD3_CLK */
|
||||||
|
[20] = RCAR_GP_PIN(4, 8), /* SD3_CMD */
|
||||||
|
[21] = RCAR_GP_PIN(4, 9), /* SD3_DAT0 */
|
||||||
|
[22] = RCAR_GP_PIN(4, 10), /* SD3_DAT1 */
|
||||||
|
[23] = RCAR_GP_PIN(4, 11), /* SD3_DAT2 */
|
||||||
|
[24] = RCAR_GP_PIN(4, 12), /* SD3_DAT3 */
|
||||||
|
[25] = RCAR_GP_PIN(4, 13), /* SD3_DAT4 */
|
||||||
|
[26] = RCAR_GP_PIN(4, 14), /* SD3_DAT5 */
|
||||||
|
[27] = RCAR_GP_PIN(4, 15), /* SD3_DAT6 */
|
||||||
|
[28] = RCAR_GP_PIN(4, 16), /* SD3_DAT7 */
|
||||||
|
[29] = RCAR_GP_PIN(4, 17), /* SD3_DS */
|
||||||
|
[30] = -1,
|
||||||
|
[31] = -1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ /* sentinel */ },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pfc_pocctrl_reg *pfc_rcar_get_io_voltage_regs(void)
|
||||||
|
{
|
||||||
|
return pfc_r8a77951_r8a77961_volt_regs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pfc_pocctrl_reg *pfc_rcar_get_pocctrl_reg(uint16_t pin, uint8_t *bit)
|
||||||
|
{
|
||||||
|
const struct pfc_pocctrl_reg *voltage_regs = pfc_rcar_get_io_voltage_regs();
|
||||||
|
|
||||||
|
BUILD_ASSERT(ARRAY_SIZE(voltage_regs->pins) < UINT8_MAX);
|
||||||
|
|
||||||
|
/* Loop around all the registers to find the bit for a given pin */
|
||||||
|
while (voltage_regs && voltage_regs->offset) {
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0U; i < ARRAY_SIZE(voltage_regs->pins); i++) {
|
||||||
|
if (voltage_regs->pins[i] == pin) {
|
||||||
|
*bit = i;
|
||||||
|
return voltage_regs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
voltage_regs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pfc_rcar_set_voltage(uintptr_t pfc_base, uint16_t pin, uint16_t voltage)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
uint8_t bit;
|
||||||
|
const struct pfc_pocctrl_reg *voltage_reg;
|
||||||
|
|
||||||
|
voltage_reg = pfc_rcar_get_pocctrl_reg(pin, &bit);
|
||||||
|
if (!voltage_reg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = sys_read32(pfc_base + voltage_reg->offset);
|
||||||
|
|
||||||
|
switch (voltage) {
|
||||||
|
case PIN_VOLTAGE_1P8V:
|
||||||
|
if (!(val & BIT(bit))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
val &= ~BIT(bit);
|
||||||
|
break;
|
||||||
|
case PIN_VOLTAGE_3P3V:
|
||||||
|
if (val & BIT(bit)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
val |= BIT(bit);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfc_rcar_write(pfc_base, voltage_reg->offset, val);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PINCTRL_RCAR_VOLTAGE_CONTROL */
|
||||||
|
|
||||||
int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
|
int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -214,6 +326,12 @@ int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PINCTRL_RCAR_VOLTAGE_CONTROL
|
||||||
|
if (pin->voltage != PIN_VOLTAGE_NONE) {
|
||||||
|
pfc_rcar_set_voltage(pfc_base, pin->pin, pin->voltage);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Select function for pin */
|
/* Select function for pin */
|
||||||
if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) != 0U) {
|
if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) != 0U) {
|
||||||
pfc_rcar_set_ipsr(pfc_base, &pin->func);
|
pfc_rcar_set_ipsr(pfc_base, &pin->func);
|
||||||
|
|
|
@ -51,6 +51,7 @@ description: |
|
||||||
- bias-pull-down
|
- bias-pull-down
|
||||||
- bias-pull-up
|
- bias-pull-up
|
||||||
- drive-strength
|
- drive-strength
|
||||||
|
- power-source
|
||||||
|
|
||||||
To link pin configurations with a device, use a pinctrl-N property for some
|
To link pin configurations with a device, use a pinctrl-N property for some
|
||||||
number N, like this example you could place in your board's DTS file:
|
number N, like this example you could place in your board's DTS file:
|
||||||
|
@ -82,6 +83,7 @@ child-binding:
|
||||||
- bias-pull-down
|
- bias-pull-down
|
||||||
- bias-pull-up
|
- bias-pull-up
|
||||||
- drive-strength
|
- drive-strength
|
||||||
|
- power-source
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
pin:
|
pin:
|
||||||
|
|
|
@ -72,4 +72,8 @@
|
||||||
#define IP2SR5(shift, func) IPnSR(2, 5, shift, func)
|
#define IP2SR5(shift, func) IPnSR(2, 5, shift, func)
|
||||||
#define IP3SR5(shift, func) IPnSR(3, 5, shift, func)
|
#define IP3SR5(shift, func) IPnSR(3, 5, shift, func)
|
||||||
|
|
||||||
|
#define PIN_VOLTAGE_NONE 0
|
||||||
|
#define PIN_VOLTAGE_1P8V 1
|
||||||
|
#define PIN_VOLTAGE_3P3V 2
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RCAR_COMMON_H_ */
|
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RCAR_COMMON_H_ */
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef struct pinctrl_soc_pin {
|
||||||
struct rcar_pin_func func;
|
struct rcar_pin_func func;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t drive_strength;
|
uint8_t drive_strength;
|
||||||
|
uint8_t voltage;
|
||||||
} pinctrl_soc_pin_t;
|
} pinctrl_soc_pin_t;
|
||||||
|
|
||||||
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
|
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
|
||||||
|
@ -66,6 +67,10 @@ typedef struct pinctrl_soc_pin {
|
||||||
.drive_strength = \
|
.drive_strength = \
|
||||||
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
|
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
|
||||||
(DT_PROP(node_id, drive_strength)), (0)), \
|
(DT_PROP(node_id, drive_strength)), (0)), \
|
||||||
|
.voltage = COND_CODE_1(DT_NODE_HAS_PROP(node_id, \
|
||||||
|
power_source), \
|
||||||
|
(DT_PROP(node_id, power_source)), \
|
||||||
|
(PIN_VOLTAGE_NONE)), \
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef struct pinctrl_soc_pin {
|
||||||
struct rcar_pin_func func;
|
struct rcar_pin_func func;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t drive_strength;
|
uint8_t drive_strength;
|
||||||
|
uint8_t voltage;
|
||||||
} pinctrl_soc_pin_t;
|
} pinctrl_soc_pin_t;
|
||||||
|
|
||||||
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
|
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
|
||||||
|
@ -65,6 +66,10 @@ typedef struct pinctrl_soc_pin {
|
||||||
.drive_strength = \
|
.drive_strength = \
|
||||||
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
|
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
|
||||||
(DT_PROP(node_id, drive_strength)), (0)), \
|
(DT_PROP(node_id, drive_strength)), (0)), \
|
||||||
|
.voltage = COND_CODE_1(DT_NODE_HAS_PROP(node_id, \
|
||||||
|
power_source), \
|
||||||
|
(DT_PROP(node_id, power_source)), \
|
||||||
|
(PIN_VOLTAGE_NONE)), \
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue