summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Thielen <jtln@google.com>2022-10-11 20:14:24 +0000
committerJosh Thielen <jtln@google.com>2022-10-20 20:21:55 +0000
commitbc1c07d307aada992290ddcf0b974dfd433b3df2 (patch)
tree10d6782c8667608dcbbda3ae0a1cf618f0e564fa
parent2e7f962c4cc6eb5ebade46c2da7092fb841de6a3 (diff)
downloadrotary-encoders-bc1c07d307aada992290ddcf0b974dfd433b3df2.tar.gz
Crown - SW Vote for LDO20 and L28
- Add regulator votes and loads for Crown sensor VLD (L28) and VDD (L20) - Regulators are voted on during probe and voted off during remove - Active/sleep load set in resume/suspend for Run/Low-frequency mode. Test: Verified expected load and regulator mode for L20 and L28 using: cat /sys/class/regulator/regulator.27/requested_microamps cat /sys/class/regulator/regulator.35/requested_microamps cat /sys/class/regulator/regulator.27/opmode cat /sys/class/regulator/regulator.35/opmode With sensor in Power Down: echo 1 > /sys/devices/platform/soc/4a80000.i2c/i2c-0/0-0075/pd And active: echo 0 > /sys/devices/platform/soc/4a80000.i2c/i2c-0/0-0075/pd Bug: 239047870 Change-Id: I62c93ea5ce876a17c7e3465389b55c312c5cd03f Signed-off-by: Josh Thielen <jtln@google.com>
-rw-r--r--ots_pat9126/pat9126.c164
1 files changed, 163 insertions, 1 deletions
diff --git a/ots_pat9126/pat9126.c b/ots_pat9126/pat9126.c
index ef344fc..ba78f58 100644
--- a/ots_pat9126/pat9126.c
+++ b/ots_pat9126/pat9126.c
@@ -36,6 +36,10 @@ struct pixart_pat9126_data {
bool press_en;
bool inverse_x;
bool inverse_y;
+ u32 vdd_active_load;
+ u32 vld_active_load;
+ u32 vdd_sleep_load;
+ u32 vld_sleep_load;
int state;
int display_mode;
struct work_struct work;
@@ -44,6 +48,8 @@ struct pixart_pat9126_data {
struct delayed_work resume_work;
struct notifier_block fb_notif;
struct mutex mtx;
+ struct regulator *vdd_supply;
+ struct regulator *vld_supply;
};
#define PAT9126_STATE_OFF 0
@@ -64,6 +70,78 @@ static int pat9126_fb_callback(struct notifier_block *nb, unsigned long type, vo
static int pat9126_display_suspend(struct device *dev);
static int pat9126_display_resume(struct device *dev);
+static int pat9126_set_loads_active(struct pixart_pat9126_data *data)
+{
+ int ret;
+
+ ret = regulator_set_load(data->vdd_supply, data->vdd_active_load);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to set vdd regulator load\n");
+ return ret;
+ }
+
+ ret = regulator_set_load(data->vld_supply, data->vld_active_load);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to set vld regulator load\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pat9126_set_loads_sleep(struct pixart_pat9126_data *data)
+{
+ int ret;
+
+ ret = regulator_set_load(data->vdd_supply, data->vdd_sleep_load);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to set vdd regulator load\n");
+ return ret;
+ }
+
+ ret = regulator_set_load(data->vld_supply, data->vld_sleep_load);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to set vld regulator load\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pat9126_enable_regulators(struct pixart_pat9126_data *data)
+{
+ int ret;
+
+ ret = regulator_enable(data->vdd_supply);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to enable vdd regulator\n");
+ return ret;
+ }
+
+ ret = regulator_enable(data->vld_supply);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to enable vld regulator\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void pat9126_disable_regulators(struct pixart_pat9126_data *data)
+{
+ int ret;
+
+ ret = regulator_disable(data->vld_supply);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to disable vld regulator\n");
+ }
+
+ ret = regulator_disable(data->vdd_supply);
+ if (ret) {
+ pr_err("[PAT9126]: Failed to disable vdd regulator\n");
+ }
+}
+
static int pat9126_write(struct i2c_client *client, u8 addr, u8 data)
{
u8 buf[BUF_SIZE];
@@ -568,11 +646,22 @@ static ssize_t pat9126_pd_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count) {
+ struct pixart_pat9126_data *data =
+ (struct pixart_pat9126_data *) dev_get_drvdata(dev);
u8 tmp;
if (!kstrtou8(buf, 0, &tmp)) {
dev_dbg(dev, "power down: %d\n", (tmp ? 1 : 0));
+
+ if (!tmp) {
+ pat9126_set_loads_active(data);
+ }
+
pat9126_pd_write(dev, tmp);
+
+ if (tmp) {
+ pat9126_set_loads_sleep(data);
+ }
} else {
dev_warn(dev, "failed to parse sysfs arg: '%s'\n", buf);
}
@@ -601,6 +690,7 @@ static void pat9126_complete_resume(struct work_struct *work) {
struct delayed_work *dw = to_delayed_work(work);
struct pixart_pat9126_data *data =
container_of(dw, struct pixart_pat9126_data, resume_work);
+ int ret = 0;
mutex_lock(&data->mtx);
@@ -616,6 +706,11 @@ static void pat9126_complete_resume(struct work_struct *work) {
goto end_complete_resume;
}
+ ret = pat9126_set_loads_active(data);
+ if (ret) {
+ goto end_complete_resume;
+ }
+
pat9126_enable_mot_write_protected(data->client);
data->state = PAT9126_STATE_ON;
@@ -674,6 +769,56 @@ static int pat9126_parse_dt(struct device *dev,
}
}
+ ret = of_property_read_u32(np, "pixart,vdd-active-load",
+ &temp_val);
+ if (!ret) {
+ data->vdd_active_load = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse vdd-active-load\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "pixart,vld-active-load",
+ &temp_val);
+ if (!ret) {
+ data->vld_active_load = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse vld-active-load\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "pixart,vdd-sleep-load",
+ &temp_val);
+ if (!ret) {
+ data->vdd_sleep_load = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse vdd-sleep-load\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "pixart,vld-sleep-load",
+ &temp_val);
+ if (!ret) {
+ data->vld_sleep_load = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse vld-sleep-load\n");
+ return ret;
+ }
+
+ data->vld_supply = devm_regulator_get(dev, "pixart,vld");
+ if (IS_ERR(data->vld_supply)) {
+ ret = PTR_ERR(data->vld_supply);
+ dev_err(dev, "get vld regulator failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ data->vdd_supply = devm_regulator_get(dev, "pixart,vdd");
+ if (IS_ERR(data->vdd_supply)) {
+ ret = PTR_ERR(data->vdd_supply);
+ dev_err(dev, "get vdd regulator failed, ret=%d\n", ret);
+ return ret;
+ }
+
return 0;
}
@@ -727,6 +872,16 @@ static int pat9126_i2c_probe(struct i2c_client *client,
if (ret < 0)
dev_err(dev, "Could not set pin to active state %d\n", ret);
+ ret = pat9126_set_loads_active(data);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = pat9126_enable_regulators(data);
+ if (ret < 0) {
+ goto err_regulators;
+ }
+
usleep_range(DELAY_BETWEEN_REG_US, DELAY_BETWEEN_REG_US + 1);
/*
@@ -736,7 +891,7 @@ static int pat9126_i2c_probe(struct i2c_client *client,
if (pat9126_sensor_init(data->client) < 0) {
ret = -ENODEV;
dev_err(dev, "Failed to initialize sensor %d\n", ret);
- return ret;
+ goto err_regulators;
}
mutex_init(&data->mtx);
@@ -775,12 +930,18 @@ err_sysfs_create:
err_request_threaded_irq:
cancel_work_sync(&data->work);
destroy_workqueue(data->workqueue);
+err_regulators:
+ pat9126_disable_regulators(data);
return ret;
}
static int pat9126_i2c_remove(struct i2c_client *client)
{
+ struct pixart_pat9126_data *data = i2c_get_clientdata(client);
+
+ pat9126_disable_regulators(data);
+
return 0;
}
@@ -836,6 +997,7 @@ static int pat9126_display_suspend(struct device *dev)
disable_irq(data->client->irq);
pat9126_disable_mot_write_protected(data->client);
+ pat9126_set_loads_sleep(data);
end_suspend:
data->state = PAT9126_STATE_OFF;