drm/rockchip: ebc: sy7636a: Add support for monitor power fault event

When a power failure occurs, the sy7636a power good(PGOOD) pin will be
pulled low and the fault flag will be set.

Change-Id: I69c090b61fefeea36a2481395ab02132d2fe565b
Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
This commit is contained in:
Chaoyi Chen
2024-09-21 17:21:40 +08:00
parent 82bd30d0c4
commit 4941fc326e
2 changed files with 69 additions and 2 deletions

View File

@@ -16,8 +16,11 @@
#define SY7636A_MAX_ENABLE_GPIO_NUM 4
struct sy7636a_data {
struct platform_device *pdev;
struct regmap *regmap;
struct gpio_descs *enable_gpio;
struct gpio_desc *pgood_gpio;
int pgood_irq;
/*
* When registering a new regulator, regulator core will try to
* call "set_suspend_disable" to check whether regulator device
@@ -28,6 +31,25 @@ struct sy7636a_data {
int vcom_uV;
};
static int sy7636a_power_enable(struct regulator_dev *rdev)
{
struct sy7636a_data *data = rdev->reg_data;
int ret;
ret = regulator_enable_regmap(rdev);
enable_irq(data->pgood_irq);
return ret;
}
static int sy7636a_power_disable(struct regulator_dev *rdev)
{
struct sy7636a_data *data = rdev->reg_data;
disable_irq(data->pgood_irq);
return regulator_disable_regmap(rdev);
}
static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)
{
int ret;
@@ -153,8 +175,8 @@ static int sy7636a_resume(struct regulator_dev *rdev)
static const struct regulator_ops sy7636a_vcom_volt_ops = {
.set_voltage = sy7636a_set_vcom_voltage_op,
.get_voltage = sy7636a_get_vcom_voltage_op,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.enable = sy7636a_power_enable,
.disable = sy7636a_power_disable,
.is_enabled = regulator_is_enabled_regmap,
.get_status = sy7636a_get_status,
.set_suspend_disable = sy7636a_set_suspend_disable,
@@ -173,6 +195,28 @@ static const struct regulator_desc desc = {
.of_match = of_match_ptr("vcom"),
};
static irqreturn_t sy7636a_power_good_irq_handler(int irq, void *dev_id)
{
struct sy7636a_data *data = dev_id;
struct regmap *regmap = data->regmap;
struct platform_device *pdev = data->pdev;
u32 val;
int ret;
ret = regmap_read(regmap, SY7636A_REG_FAULT_FLAG, &val);
if (ret) {
dev_err(pdev->dev.parent, "sy7636a failed to read fault flag\n");
goto out;
}
if (!(val & SY7636A_FAULT_FLAG_PG) || (val & SY7636A_FAULT_FLAG_FAULT))
dev_err(pdev->dev.parent, "sy7636a power fault flag:%d\n",
val >> SY7636A_FAULT_FLAG_FAULT_SHIFT);
out:
return IRQ_HANDLED;
}
static int sy7636a_regulator_probe(struct platform_device *pdev)
{
struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL);
@@ -188,6 +232,7 @@ static int sy7636a_regulator_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->pdev = pdev;
data->regmap = regmap;
data->initial_suspend = true;
@@ -199,6 +244,26 @@ static int sy7636a_regulator_probe(struct platform_device *pdev)
return PTR_ERR(data->enable_gpio);
}
data->pgood_irq = -1;
data->pgood_gpio = devm_gpiod_get(pdev->dev.parent, "pgood", GPIOD_IN);
if (IS_ERR(data->pgood_gpio)) {
dev_warn(pdev->dev.parent, "Failed to get sy7636a pgood gpio %ld\n",
PTR_ERR(data->pgood_gpio));
} else {
data->pgood_irq = gpiod_to_irq(data->pgood_gpio);
if (data->pgood_irq < 0) {
dev_err(pdev->dev.parent, "Failed to get sy7636a power good int irq\n");
} else {
ret = devm_request_threaded_irq(pdev->dev.parent, data->pgood_irq, NULL,
sy7636a_power_good_irq_handler,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT |
IRQF_NO_AUTOEN, "sy7636a", data);
if (ret)
dev_err(pdev->dev.parent, "Failed to request sy7636a irq\n");
}
}
/* sy7636a needs 2.5ms to enter active mode after enable */
usleep_range(2500, 2600);

View File

@@ -16,6 +16,8 @@
#define SY7636A_REG_VLDO_VOLTAGE_ADJULST_CTRL 0x03
#define SY7636A_REG_POWER_ON_DELAY_TIME 0x06
#define SY7636A_REG_FAULT_FLAG 0x07
#define SY7636A_FAULT_FLAG_FAULT GENMASK(4, 1)
#define SY7636A_FAULT_FLAG_FAULT_SHIFT 1
#define SY7636A_FAULT_FLAG_PG BIT(0)
#define SY7636A_REG_TERMISTOR_READOUT 0x08