diff options
author | Josh Thielen <jtln@google.com> | 2022-10-11 20:14:24 +0000 |
---|---|---|
committer | Josh Thielen <jtln@google.com> | 2022-10-20 20:21:55 +0000 |
commit | bc1c07d307aada992290ddcf0b974dfd433b3df2 (patch) | |
tree | 10d6782c8667608dcbbda3ae0a1cf618f0e564fa | |
parent | 2e7f962c4cc6eb5ebade46c2da7092fb841de6a3 (diff) | |
download | rotary-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.c | 164 |
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; |