Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 64 additions & 36 deletions drivers/espi/espi_realtek_rts5912.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ LOG_MODULE_REGISTER(espi, CONFIG_ESPI_LOG_LEVEL);
#include "reg/reg_kbc.h"
#include "reg/reg_port80.h"

#ifdef CONFIG_PM
#include "reg/reg_gpio.h"
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#include "reg/reg_system.h"
#include "zephyr/drivers/gpio/gpio_rts5912.h"
#endif

BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "support only one espi compatible node");

struct espi_rts5912_config {
Expand Down Expand Up @@ -56,6 +64,9 @@ struct espi_rts5912_config {
volatile struct port80_reg *const port80_reg;
uint32_t port80_clk_grp;
uint32_t port80_clk_idx;
#endif
#ifdef CONFIG_PM
struct gpio_dt_spec cs_pin;
#endif
const struct device *clk_dev;
const struct pinctrl_dev_config *pcfg;
Expand Down Expand Up @@ -1197,7 +1208,6 @@ static void notify_host_warning(const struct device *dev, enum espi_vwire_signal
uint8_t status = 0;

espi_rts5912_receive_vwire(dev, signal, &status);
k_busy_wait(200);

switch (signal) {
case ESPI_VWIRE_SIGNAL_SUS_WARN:
Expand Down Expand Up @@ -1394,8 +1404,6 @@ static int espi_rts5912_send_vwire(const struct device *dev, enum espi_vwire_sig
static int espi_rts5912_receive_vwire(const struct device *dev, enum espi_vwire_signal signal,
uint8_t *level)
{
const struct espi_rts5912_config *const espi_config = dev->config;
volatile struct espi_reg *const espi_reg = espi_config->espi_reg;
uint8_t vw_idx, lev_msk, valid_msk;
uint8_t vw_data;

Expand All @@ -1412,9 +1420,6 @@ static int espi_rts5912_receive_vwire(const struct device *dev, enum espi_vwire_
vw_data = espi_vw_ch_cached_data.idx2;
break;
case VW_CH_IDX3:
if (espi_vw_ch_cached_data.idx3 != espi_reg->EVIDX3) {
espi_vw_ch_cached_data.idx3 = espi_reg->EVIDX3;
}
vw_data = espi_vw_ch_cached_data.idx3;
break;
case VW_CH_IDX4:
Expand All @@ -1427,60 +1432,33 @@ static int espi_rts5912_receive_vwire(const struct device *dev, enum espi_vwire_
vw_data = espi_vw_tx_cached_data.idx6;
break;
case VW_CH_IDX7:
if (espi_vw_ch_cached_data.idx7 != espi_reg->EVIDX7) {
espi_vw_ch_cached_data.idx7 = espi_reg->EVIDX7;
}
vw_data = espi_vw_ch_cached_data.idx7;
break;
case VW_CH_IDX40:
vw_data = espi_vw_tx_cached_data.idx40;
break;
case VW_CH_IDX41:
if (espi_vw_ch_cached_data.idx41 != espi_reg->EVIDX41) {
espi_vw_ch_cached_data.idx41 = espi_reg->EVIDX41;
}
vw_data = espi_vw_ch_cached_data.idx41;
break;
case VW_CH_IDX42:
if (espi_vw_ch_cached_data.idx42 != espi_reg->EVIDX42) {
espi_vw_ch_cached_data.idx42 = espi_reg->EVIDX42;
}
vw_data = espi_vw_ch_cached_data.idx42;
break;
case VW_CH_IDX43:
if (espi_vw_ch_cached_data.idx43 != espi_reg->EVIDX43) {
espi_vw_ch_cached_data.idx43 = espi_reg->EVIDX43;
}
vw_data = espi_vw_ch_cached_data.idx43;
break;
case VW_CH_IDX44:
if (espi_vw_ch_cached_data.idx44 != espi_reg->EVIDX44) {
espi_vw_ch_cached_data.idx44 = espi_reg->EVIDX44;
}
vw_data = espi_vw_ch_cached_data.idx44;
break;
case VW_CH_IDX47:
if (espi_vw_ch_cached_data.idx47 != espi_reg->EVIDX47) {
espi_vw_ch_cached_data.idx47 = espi_reg->EVIDX47;
}
vw_data = espi_vw_ch_cached_data.idx47;
break;
case VW_CH_IDX4A:
if (espi_vw_ch_cached_data.idx4a != espi_reg->EVIDX4A) {
espi_vw_ch_cached_data.idx4a = espi_reg->EVIDX4A;
}
vw_data = espi_vw_ch_cached_data.idx4a;
break;
case VW_CH_IDX51:
if (espi_vw_ch_cached_data.idx51 != espi_reg->EVIDX51) {
espi_vw_ch_cached_data.idx51 = espi_reg->EVIDX51;
}
vw_data = espi_vw_ch_cached_data.idx51;
break;
case VW_CH_IDX61:
if (espi_vw_ch_cached_data.idx61 != espi_reg->EVIDX61) {
espi_vw_ch_cached_data.idx61 = espi_reg->EVIDX61;
}
vw_data = espi_vw_ch_cached_data.idx61;
break;
default:
Expand Down Expand Up @@ -2293,7 +2271,18 @@ static void espi_bus_reset_setup(const struct device *dev)
DEVICE_DT_GET(DT_DRV_INST(0)), 0);
irq_enable(DT_IRQ_BY_NAME(DT_DRV_INST(0), bus_rst, irq));
}
#ifdef CONFIG_PM
void espi_cs_low_isr(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins)
{
gpio_flags_t cs_pin_config;

gpio_pin_get_config(port, pins, &cs_pin_config);
if (cs_pin_config & GPIO_INT_ENABLE) {
gpio_pin_interrupt_configure(port, (find_msb_set(pins) - 1),
GPIO_INT_MODE_DISABLED);
}
}
#endif
static int espi_rts5912_init(const struct device *dev)
{
const struct espi_rts5912_config *const espi_config = dev->config;
Expand Down Expand Up @@ -2393,13 +2382,44 @@ static int espi_rts5912_init(const struct device *dev)
goto exit;
}
#endif

#ifdef CONFIG_PM
static struct gpio_callback cb;
uint32_t cs_irq_nun = gpio_rts5912_get_pin_num(&espi_config->cs_pin);

NVIC_ClearPendingIRQ(cs_irq_nun);
gpio_init_callback(&cb, espi_cs_low_isr, BIT(espi_config->cs_pin.pin));
gpio_add_callback(espi_config->cs_pin.port, &cb);
irq_enable(cs_irq_nun);
#endif
exit:
return rc;
}
#ifdef CONFIG_PM
static inline int espi_rts5912_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct espi_rts5912_config *const espi_config = dev->config;
SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE;

PINCTRL_DT_INST_DEFINE(0);
switch (action) {
case PM_DEVICE_ACTION_RESUME:
sys_reg->SLPCTRL &= ~SYSTEM_SLPCTRL_GPIOWKEN_Msk;
gpio_pin_interrupt_configure_dt(&espi_config->cs_pin, GPIO_INT_MODE_DISABLED);
break;
case PM_DEVICE_ACTION_SUSPEND:
sys_reg->SLPCTRL |= SYSTEM_SLPCTRL_GPIOWKEN_Msk;
gpio_pin_interrupt_configure_dt(&espi_config->cs_pin,
GPIO_INT_MODE_EDGE | GPIO_INT_TRIG_LOW);
break;
default:
return -ENOTSUP;
}

return 0;
}
PM_DEVICE_DT_INST_DEFINE(0, espi_rts5912_pm_action);
#endif

PINCTRL_DT_INST_DEFINE(0);
static struct espi_rts5912_data espi_rts5912_data_0;

static const struct espi_rts5912_config espi_rts5912_config = {
Expand Down Expand Up @@ -2434,10 +2454,18 @@ static const struct espi_rts5912_config espi_rts5912_config = {
.port80_reg = (volatile struct port80_reg *const)DT_INST_REG_ADDR_BY_NAME(0, port80),
.port80_clk_grp = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), port80, clk_grp),
.port80_clk_idx = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), port80, clk_idx),
#endif
#ifdef CONFIG_PM
.cs_pin = GPIO_DT_SPEC_INST_GET(0, cs_gpios),
#endif
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
};

#ifdef CONFIG_PM
DEVICE_DT_INST_DEFINE(0, &espi_rts5912_init, PM_DEVICE_DT_INST_GET(0), &espi_rts5912_data_0,
&espi_rts5912_config, PRE_KERNEL_2, CONFIG_ESPI_INIT_PRIORITY,
&espi_rts5912_driver_api);
#else
DEVICE_DT_INST_DEFINE(0, &espi_rts5912_init, NULL, &espi_rts5912_data_0, &espi_rts5912_config,
PRE_KERNEL_2, CONFIG_ESPI_INIT_PRIORITY, &espi_rts5912_driver_api);
#endif
2 changes: 2 additions & 0 deletions dts/arm/realtek/ec/rts5912.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <mem.h>
#include <zephyr/dt-bindings/i2c/i2c.h>
#include <freq.h>
#include <zephyr/dt-bindings/gpio/realtek-gpio.h>

/ {
cpus {
Expand Down Expand Up @@ -167,6 +168,7 @@

espi0: espi0@400b1000 {
compatible = "realtek,rts5912-espi";
cs-gpios = <RTS5912_GPIO004 0>;
status = "disabled";

reg = <0x400b1000 0x200 /* espi target */
Expand Down
9 changes: 9 additions & 0 deletions dts/bindings/espi/realtek,rts5912-espi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ properties:

pinctrl-names:
required: true

cs-gpios:
description: |
select the cs pin to support the espi wakeup
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note that this property is required if CONFIG_PM is enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note now, thanks.

and it is required when CONFIG_PM is enabled.
please check include/zephyr/dt-bindings/gpio/realtek-gpio.h
For example:
cs-gpios = <RTS5912_GPIO004 0>;
type: phandle-array