drivers: gpio: rts5912 support new features

add support new features for get/set configuration:
1. slew rate
2. output driving current
3. schmitt trigger
4. multi-function select

testing by blinky sample.

20250326: remove check interrupt mask to avoid interrupt disable.

Signed-off-by: Titan Chen <titan.chen@realtek.com>
This commit is contained in:
Titan Chen 2025-02-19 19:12:38 +08:00 committed by Benjamin Cabé
commit 2ede51b3e9
3 changed files with 145 additions and 7 deletions

View file

@ -95,9 +95,17 @@ static int gpio_rts5912_configuration(const struct device *port, gpio_pin_t pin,
if (flags & GPIO_INPUT) { if (flags & GPIO_INPUT) {
cfg_val &= ~GPIO_GCR_DIR_Msk; cfg_val &= ~GPIO_GCR_DIR_Msk;
cfg_val &= ~GPIO_GCR_OUTCTRL_Msk; cfg_val &= ~GPIO_GCR_OUTCTRL_Msk;
/* enable input detect */
cfg_val |= GPIO_GCR_INDETEN_Msk; cfg_val |= GPIO_GCR_INDETEN_Msk;
} }
if (flags & GPIO_DISCONNECTED) {
cfg_val &= ~GPIO_GCR_DIR_Msk;
cfg_val &= ~GPIO_GCR_OUTCTRL_Msk;
/* disable input detect */
cfg_val &= ~GPIO_GCR_INDETEN_Msk;
}
if (flags & GPIO_OPEN_DRAIN) { if (flags & GPIO_OPEN_DRAIN) {
cfg_val |= GPIO_GCR_OUTMD_Msk; cfg_val |= GPIO_GCR_OUTMD_Msk;
} else { } else {
@ -131,6 +139,42 @@ static int gpio_rts5912_configuration(const struct device *port, gpio_pin_t pin,
break; break;
} }
if (flags & RTS5912_GPIO_OUTDRV) {
cfg_val |= GPIO_GCR_OUTDRV_Msk;
} else {
cfg_val &= ~GPIO_GCR_OUTDRV_Msk;
}
if (flags & RTS5912_GPIO_SLEWRATE) {
cfg_val |= GPIO_GCR_SLEWRATE_Msk;
} else {
cfg_val &= ~GPIO_GCR_SLEWRATE_Msk;
}
if (flags & RTS5912_GPIO_SCHEN) {
cfg_val |= GPIO_GCR_SCHEN_Msk;
} else {
cfg_val &= ~GPIO_GCR_SCHEN_Msk;
}
cfg_val &= ~GPIO_GCR_MFCTRL_Msk;
switch (flags & RTS5912_GPIO_MFCTRL_MASK) {
case RTS5912_GPIO_MFCTRL_0:
cfg_val |= (0U << GPIO_GCR_MFCTRL_Pos);
break;
case RTS5912_GPIO_MFCTRL_1:
cfg_val |= (1U << GPIO_GCR_MFCTRL_Pos);
break;
case RTS5912_GPIO_MFCTRL_2:
cfg_val |= (2U << GPIO_GCR_MFCTRL_Pos);
break;
case RTS5912_GPIO_MFCTRL_3:
cfg_val |= (3U << GPIO_GCR_MFCTRL_Pos);
break;
default:
return -EINVAL;
}
*gcr = cfg_val; *gcr = cfg_val;
if (flags & GPIO_OUTPUT) { if (flags & GPIO_OUTPUT) {
@ -183,6 +227,73 @@ static int gpio_rts5912_get_configuration(const struct device *port, gpio_pin_t
cfg_flag |= GPIO_PULL_DOWN; cfg_flag |= GPIO_PULL_DOWN;
} }
if (*gcr & GPIO_GCR_INDETEN_Msk) {
cfg_flag |= RTS5912_GPIO_INDETEN;
} else {
cfg_flag &= ~RTS5912_GPIO_INDETEN;
}
if (*gcr & GPIO_GCR_OUTDRV_Msk) {
cfg_flag |= RTS5912_GPIO_OUTDRV;
} else {
cfg_flag &= ~RTS5912_GPIO_OUTDRV;
}
if (*gcr & GPIO_GCR_SLEWRATE_Msk) {
cfg_flag |= RTS5912_GPIO_SLEWRATE;
} else {
cfg_flag &= ~RTS5912_GPIO_SLEWRATE;
}
if (*gcr & GPIO_GCR_SCHEN_Msk) {
cfg_flag |= RTS5912_GPIO_SCHEN;
} else {
cfg_flag &= ~RTS5912_GPIO_SCHEN;
}
switch ((*gcr & GPIO_GCR_MFCTRL_Msk) >> GPIO_GCR_MFCTRL_Pos) {
case 0:
cfg_flag |= RTS5912_GPIO_MFCTRL_0;
break;
case 1:
cfg_flag |= RTS5912_GPIO_MFCTRL_1;
break;
case 2:
cfg_flag |= RTS5912_GPIO_MFCTRL_2;
break;
case 3:
cfg_flag |= RTS5912_GPIO_MFCTRL_3;
break;
default:
cfg_flag |= RTS5912_GPIO_MFCTRL_0;
break;
}
if (*gcr & GPIO_GCR_INTEN_Msk) {
switch (*gcr & GPIO_GCR_INTCTRL_Msk) {
case GPIO_GCR_INTCTRL_TRIG_EDGE_HIGH:
cfg_flag |= GPIO_INT_EDGE_RISING;
break;
case GPIO_GCR_INTCTRL_TRIG_EDGE_LOW:
cfg_flag |= GPIO_INT_EDGE_FALLING;
break;
case GPIO_GCR_INTCTRL_TRIG_EDGE_BOTH:
cfg_flag |= GPIO_INT_EDGE_BOTH;
break;
case GPIO_GCR_INTCTRL_TRIG_LEVEL_LOW:
cfg_flag |= GPIO_INT_LEVEL_LOW;
break;
case GPIO_GCR_INTCTRL_TRIG_LEVEL_HIGH:
cfg_flag |= GPIO_INT_LEVEL_HIGH;
break;
default:
cfg_flag |= GPIO_INT_LEVEL_LOW;
break;
}
} else {
cfg_flag |= GPIO_INT_DISABLE;
}
*flags = cfg_flag; *flags = cfg_flag;
return 0; return 0;
@ -357,11 +468,11 @@ static int gpio_rts5912_intr_config(const struct device *port, gpio_pin_t pin,
switch (trig) { switch (trig) {
case GPIO_INT_TRIG_LOW: case GPIO_INT_TRIG_LOW:
cfg_val &= ~GPIO_GCR_INTCTRL_Msk; cfg_val &= ~GPIO_GCR_INTCTRL_Msk;
cfg_val |= 0x03UL << GPIO_GCR_INTCTRL_Pos; cfg_val |= GPIO_GCR_INTCTRL_TRIG_LEVEL_LOW;
break; break;
case GPIO_INT_TRIG_HIGH: case GPIO_INT_TRIG_HIGH:
cfg_val &= ~GPIO_GCR_INTCTRL_Msk; cfg_val &= ~GPIO_GCR_INTCTRL_Msk;
cfg_val |= 0x04UL << GPIO_GCR_INTCTRL_Pos; cfg_val |= GPIO_GCR_INTCTRL_TRIG_LEVEL_HIGH;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -371,15 +482,15 @@ static int gpio_rts5912_intr_config(const struct device *port, gpio_pin_t pin,
switch (trig) { switch (trig) {
case GPIO_INT_TRIG_LOW: case GPIO_INT_TRIG_LOW:
cfg_val &= ~GPIO_GCR_INTCTRL_Msk; cfg_val &= ~GPIO_GCR_INTCTRL_Msk;
cfg_val |= 0x01UL << GPIO_GCR_INTCTRL_Pos; cfg_val |= GPIO_GCR_INTCTRL_TRIG_EDGE_LOW;
break; break;
case GPIO_INT_TRIG_HIGH: case GPIO_INT_TRIG_HIGH:
cfg_val &= ~GPIO_GCR_INTCTRL_Msk; cfg_val &= ~GPIO_GCR_INTCTRL_Msk;
cfg_val |= 0x00UL << GPIO_GCR_INTCTRL_Pos; cfg_val |= GPIO_GCR_INTCTRL_TRIG_EDGE_HIGH;
break; break;
case GPIO_INT_TRIG_BOTH: case GPIO_INT_TRIG_BOTH:
cfg_val &= ~GPIO_GCR_INTCTRL_Msk; cfg_val &= ~GPIO_GCR_INTCTRL_Msk;
cfg_val |= 0x2UL << GPIO_GCR_INTCTRL_Pos; cfg_val |= GPIO_GCR_INTCTRL_TRIG_EDGE_BOTH;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -389,7 +500,9 @@ static int gpio_rts5912_intr_config(const struct device *port, gpio_pin_t pin,
return -EINVAL; return -EINVAL;
} }
/* enable interrupt */
cfg_val |= GPIO_GCR_INTEN_Msk; cfg_val |= GPIO_GCR_INTEN_Msk;
/* set value to GPIO register */
*gcr = cfg_val; *gcr = cfg_val;
irq_enable(pin_index); irq_enable(pin_index);

View file

@ -8,9 +8,17 @@
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_REALTEK_GPIO_H_ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_REALTEK_GPIO_H_
#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_REALTEK_GPIO_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_REALTEK_GPIO_H_
#define RTS5912_GPIO_VOLTAGE_POS 11 /** Enable input detect */
#define RTS5912_GPIO_VOLTAGE_MASK (3U << RTS5912_GPIO_VOLTAGE_POS) #define RTS5912_GPIO_INDETEN BIT(8)
/** Set pin driving current */
#define RTS5912_GPIO_OUTDRV BIT(9)
/** Set GPIO slew rate */
#define RTS5912_GPIO_SLEWRATE BIT(10)
/** Enable Schmitt-trigger */
#define RTS5912_GPIO_SCHEN BIT(11)
#define RTS5912_GPIO_VOLTAGE_POS 12
#define RTS5912_GPIO_VOLTAGE_MASK GENMASK(13, 12)
/** Set pin at the default voltage level */ /** Set pin at the default voltage level */
#define RTS5912_GPIO_VOLTAGE_DEFAULT (0U << RTS5912_GPIO_VOLTAGE_POS) #define RTS5912_GPIO_VOLTAGE_DEFAULT (0U << RTS5912_GPIO_VOLTAGE_POS)
/** Set pin voltage level at 1.8 V */ /** Set pin voltage level at 1.8 V */
@ -20,4 +28,15 @@
/** Set pin voltage level at 5.0 V */ /** Set pin voltage level at 5.0 V */
#define RTS5912_GPIO_VOLTAGE_5V0 (3U << RTS5912_GPIO_VOLTAGE_POS) #define RTS5912_GPIO_VOLTAGE_5V0 (3U << RTS5912_GPIO_VOLTAGE_POS)
/** Multi function */
#define RTS5912_GPIO_MFCTRL_POS 14
#define RTS5912_GPIO_MFCTRL_MASK GENMASK(15, 14)
/** 0x00:Function 0 0x01: Function 1 0x02: Function 2 0x03: Function 3 */
#define RTS5912_GPIO_MFCTRL_0 (0U << RTS5912_GPIO_MFCTRL_POS)
#define RTS5912_GPIO_MFCTRL_1 (1U << RTS5912_GPIO_MFCTRL_POS)
#define RTS5912_GPIO_MFCTRL_2 (2U << RTS5912_GPIO_MFCTRL_POS)
#define RTS5912_GPIO_MFCTRL_3 (3U << RTS5912_GPIO_MFCTRL_POS)
/** Interrupt Mask since rts5912 does not support GPIO_INT_LEVELS_LOGICAL*/
#define RTS5912_GPIO_INTR_MASK (1U << 21 | 1U << 22 | 1U << 24 | 1U << 25 | 1U << 26)
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_REALTEK_GPIO_H_ */ #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_REALTEK_GPIO_H_ */

View file

@ -47,4 +47,10 @@ typedef struct {
#define GPIO_GCR_INTSTS_Pos (31UL) #define GPIO_GCR_INTSTS_Pos (31UL)
#define GPIO_GCR_INTSTS_Msk BIT(GPIO_GCR_INTSTS_Pos) #define GPIO_GCR_INTSTS_Msk BIT(GPIO_GCR_INTSTS_Pos)
#define GPIO_GCR_INTCTRL_TRIG_EDGE_HIGH (0U << GPIO_GCR_INTCTRL_Pos)
#define GPIO_GCR_INTCTRL_TRIG_EDGE_LOW (1U << GPIO_GCR_INTCTRL_Pos)
#define GPIO_GCR_INTCTRL_TRIG_EDGE_BOTH (2U << GPIO_GCR_INTCTRL_Pos)
#define GPIO_GCR_INTCTRL_TRIG_LEVEL_LOW (3U << GPIO_GCR_INTCTRL_Pos)
#define GPIO_GCR_INTCTRL_TRIG_LEVEL_HIGH (4U << GPIO_GCR_INTCTRL_Pos)
#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_GPIO_H */ #endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_GPIO_H */