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
|
@ -7,3 +7,8 @@ config PINCTRL_RCAR_PFC
|
|||
depends on DT_HAS_RENESAS_RCAR_PFC_ENABLED
|
||||
help
|
||||
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
|
||||
#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.
|
||||
* 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;
|
||||
}
|
||||
|
||||
#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 ret = 0;
|
||||
|
@ -214,6 +326,12 @@ int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
|
|||
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 */
|
||||
if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) != 0U) {
|
||||
pfc_rcar_set_ipsr(pfc_base, &pin->func);
|
||||
|
|
|
@ -51,6 +51,7 @@ description: |
|
|||
- bias-pull-down
|
||||
- bias-pull-up
|
||||
- drive-strength
|
||||
- power-source
|
||||
|
||||
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:
|
||||
|
@ -82,6 +83,7 @@ child-binding:
|
|||
- bias-pull-down
|
||||
- bias-pull-up
|
||||
- drive-strength
|
||||
- power-source
|
||||
|
||||
properties:
|
||||
pin:
|
||||
|
|
|
@ -72,4 +72,8 @@
|
|||
#define IP2SR5(shift, func) IPnSR(2, 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_ */
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef struct pinctrl_soc_pin {
|
|||
struct rcar_pin_func func;
|
||||
uint8_t flags;
|
||||
uint8_t drive_strength;
|
||||
uint8_t voltage;
|
||||
} pinctrl_soc_pin_t;
|
||||
|
||||
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
|
||||
|
@ -66,6 +67,10 @@ typedef struct pinctrl_soc_pin {
|
|||
.drive_strength = \
|
||||
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
|
||||
(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;
|
||||
uint8_t flags;
|
||||
uint8_t drive_strength;
|
||||
uint8_t voltage;
|
||||
} pinctrl_soc_pin_t;
|
||||
|
||||
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
|
||||
|
@ -65,6 +66,10 @@ typedef struct pinctrl_soc_pin {
|
|||
.drive_strength = \
|
||||
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
|
||||
(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…
Reference in a new issue