mirror of
https://github.com/armbian/build.git
synced 2025-09-19 20:51:12 +02:00
I have changed the way the patches are generated a bit. Instead of using orange-pi branch from megous tree for 6.6 kernel, I have used the following kernel branches a83t-suspend, af8133j, anx, audio, axp, cam, drm, err, fixes, mbus, modem, opi3, pb, pinetab, pp, ppkb, samuel, speed, tbs-a711, ths These branches were carefully chosen to include only allwinner related patches and remove importing of the rockchip related patches into the allwinner kernel. Following patches are modified to fix patch application failure - patches.armbian/arm64-dts-sun50i-h616-orangepi-zero2-reg_usb1_vbus-status-ok.patch - patches.armbian/arm64-dts-sun50i-h616-orangepi-zero2-Enable-GPU-mali.patch - patches.armbian/arm64-dts-allwinner-h616-Add-efuse_xlate-cpu-frequency-scaling-v1_6_2.patch - patches.armbian/arm64-dts-allwinner-h616-LED-green_power_on-red_status_heartbeat.patch - patches.armbian/arm64-dts-allwinner-overlay-Add-Overlays-for-sunxi64.patch - patches.armbian/arm64-dts-sun50i-h616-bigtreetech-cb1.patch Following patches are modified because of kernel api change to fix compilation failure - patches.armbian/drv-gpu-drm-sun4i-Add-HDMI-audio-sun4i-hdmi-encoder.patch - patches.armbian/drv-of-Device-Tree-Overlay-ConfigFS-interface.patch
250 lines
7.2 KiB
Diff
250 lines
7.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
|
|
Date: Thu, 10 Feb 2022 02:09:24 +0100
|
|
Subject: iio: af8133j: Add runtime power management
|
|
|
|
Power down the sensor when not in use and during system sleep.
|
|
|
|
Signed-off-by: Ondrej Jirman <megi@xff.cz>
|
|
---
|
|
drivers/iio/magnetometer/af8133j.c | 100 ++++++++--
|
|
1 file changed, 81 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/drivers/iio/magnetometer/af8133j.c b/drivers/iio/magnetometer/af8133j.c
|
|
index 5fc684802663..5b84859a85ea 100644
|
|
--- a/drivers/iio/magnetometer/af8133j.c
|
|
+++ b/drivers/iio/magnetometer/af8133j.c
|
|
@@ -11,6 +11,7 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/gpio/consumer.h>
|
|
+#include <linux/pm_runtime.h>
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
#include <linux/iio/iio.h>
|
|
@@ -54,6 +55,7 @@ struct af8133j_data {
|
|
struct gpio_desc *reset_gpiod;
|
|
struct iio_mount_matrix orientation;
|
|
struct regulator_bulk_data supplies[AF8133J_NUM_SUPPLIES];
|
|
+ bool powered;
|
|
};
|
|
|
|
enum af8133j_axis {
|
|
@@ -97,6 +99,9 @@ static int af8133j_power_up(struct af8133j_data *data)
|
|
unsigned int val;
|
|
int ret;
|
|
|
|
+ if (data->powered)
|
|
+ return 0;
|
|
+
|
|
ret = regulator_bulk_enable(AF8133J_NUM_SUPPLIES, data->supplies);
|
|
if (ret) {
|
|
dev_err(dev, "Could not enable regulators\n");
|
|
@@ -144,6 +149,7 @@ static int af8133j_power_up(struct af8133j_data *data)
|
|
goto out_assert_reset;
|
|
}
|
|
|
|
+ data->powered = true;
|
|
return 0;
|
|
|
|
out_assert_reset:
|
|
@@ -154,8 +160,14 @@ static int af8133j_power_up(struct af8133j_data *data)
|
|
|
|
static void af8133j_power_down(struct af8133j_data *data)
|
|
{
|
|
+ struct device *dev = &data->client->dev;
|
|
+
|
|
+ if (!data->powered)
|
|
+ return;
|
|
+
|
|
gpiod_set_value_cansleep(data->reset_gpiod, 1);
|
|
regulator_bulk_disable(AF8133J_NUM_SUPPLIES, data->supplies);
|
|
+ data->powered = false;
|
|
}
|
|
|
|
static int af8133j_take_measurement(struct af8133j_data *data)
|
|
@@ -185,14 +197,29 @@ static int af8133j_take_measurement(struct af8133j_data *data)
|
|
|
|
static int af8133j_read_measurement(struct af8133j_data *data, __le16 buf[3])
|
|
{
|
|
+ struct device *dev = &data->client->dev;
|
|
int ret;
|
|
|
|
- ret = af8133j_take_measurement(data);
|
|
- if (ret < 0)
|
|
+ ret = pm_runtime_resume_and_get(dev);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "failed to power on\n");
|
|
return ret;
|
|
+ }
|
|
|
|
- return regmap_bulk_read(data->regmap, AF8133J_REG_OUT, buf,
|
|
- 3 * sizeof(__le16));
|
|
+ mutex_lock(&data->mutex);
|
|
+
|
|
+ ret = af8133j_take_measurement(data);
|
|
+ if (ret == 0)
|
|
+ ret = regmap_bulk_read(data->regmap, AF8133J_REG_OUT, buf,
|
|
+ 3 * sizeof(__le16));
|
|
+
|
|
+ mutex_unlock(&data->mutex);
|
|
+
|
|
+ pm_runtime_mark_last_busy(dev);
|
|
+ if (pm_runtime_put_autosuspend(dev))
|
|
+ dev_err(dev, "failed to power off\n");
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int af8133j_read_raw(struct iio_dev *indio_dev,
|
|
@@ -200,16 +227,15 @@ static int af8133j_read_raw(struct iio_dev *indio_dev,
|
|
int *val2, long mask)
|
|
{
|
|
struct af8133j_data *data = iio_priv(indio_dev);
|
|
- int ret;
|
|
__le16 buf[3];
|
|
+ int ret;
|
|
|
|
switch (mask) {
|
|
case IIO_CHAN_INFO_RAW:
|
|
- mutex_lock(&data->mutex);
|
|
ret = af8133j_read_measurement(data, buf);
|
|
- mutex_unlock(&data->mutex);
|
|
if (ret < 0)
|
|
return ret;
|
|
+
|
|
*val = sign_extend32(le16_to_cpu(buf[chan->address]), 15);
|
|
return IIO_VAL_INT;
|
|
case IIO_CHAN_INFO_SCALE:
|
|
@@ -238,18 +264,19 @@ static const struct regmap_config af8133j_regmap_config = {
|
|
|
|
static int af8133j_probe(struct i2c_client *client)
|
|
{
|
|
+ struct device *dev = &client->dev;
|
|
struct af8133j_data *data;
|
|
struct iio_dev *indio_dev;
|
|
struct regmap *regmap;
|
|
int ret, i;
|
|
|
|
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
|
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
|
if (!indio_dev)
|
|
return -ENOMEM;
|
|
|
|
regmap = devm_regmap_init_i2c(client, &af8133j_regmap_config);
|
|
if (IS_ERR(regmap))
|
|
- return dev_err_probe(&client->dev, PTR_ERR(regmap),
|
|
+ return dev_err_probe(dev, PTR_ERR(regmap),
|
|
"regmap initialization failed\n");
|
|
|
|
data = iio_priv(indio_dev);
|
|
@@ -258,20 +285,20 @@ static int af8133j_probe(struct i2c_client *client)
|
|
data->regmap = regmap;
|
|
mutex_init(&data->mutex);
|
|
|
|
- data->reset_gpiod = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
|
|
+ data->reset_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
|
if (IS_ERR(data->reset_gpiod))
|
|
- return dev_err_probe(&client->dev, PTR_ERR(data->reset_gpiod),
|
|
+ return dev_err_probe(dev, PTR_ERR(data->reset_gpiod),
|
|
"Failed to get reset gpio\n");
|
|
|
|
for (i = 0; i < AF8133J_NUM_SUPPLIES; i++)
|
|
data->supplies[i].supply = af8133j_supply_names[i];
|
|
- ret = devm_regulator_bulk_get(&client->dev, AF8133J_NUM_SUPPLIES, data->supplies);
|
|
+ ret = devm_regulator_bulk_get(dev, AF8133J_NUM_SUPPLIES, data->supplies);
|
|
if (ret)
|
|
return ret;
|
|
|
|
- ret = iio_read_mount_matrix(&client->dev, &data->orientation);
|
|
+ ret = iio_read_mount_matrix(dev, &data->orientation);
|
|
if (ret)
|
|
- return dev_err_probe(&client->dev, ret,
|
|
+ return dev_err_probe(dev, ret,
|
|
"Failed to read mount matrix\n");
|
|
|
|
/*
|
|
@@ -281,17 +308,23 @@ static int af8133j_probe(struct i2c_client *client)
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ af8133j_power_down(data);
|
|
+
|
|
indio_dev->info = &af8133j_info;
|
|
indio_dev->name = AF8133J_DRV_NAME;
|
|
indio_dev->channels = af8133j_channels;
|
|
indio_dev->num_channels = ARRAY_SIZE(af8133j_channels);
|
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
|
|
|
- ret = devm_iio_device_register(&client->dev, indio_dev);
|
|
+ ret = devm_iio_device_register(dev, indio_dev);
|
|
if (ret)
|
|
- return dev_err_probe(&client->dev, ret,
|
|
+ return dev_err_probe(dev, ret,
|
|
"Failed to register iio device");
|
|
|
|
+ pm_runtime_enable(dev);
|
|
+ pm_runtime_set_autosuspend_delay(dev, 500);
|
|
+ pm_runtime_use_autosuspend(dev);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -299,10 +332,38 @@ static void af8133j_remove(struct i2c_client *client)
|
|
{
|
|
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
|
struct af8133j_data *data = iio_priv(indio_dev);
|
|
+ struct device *dev = &data->client->dev;
|
|
+
|
|
+ pm_runtime_disable(dev);
|
|
+ pm_runtime_set_suspended(dev);
|
|
+ pm_runtime_put_noidle(dev);
|
|
+
|
|
+ af8133j_power_down(data);
|
|
+}
|
|
+
|
|
+static int __maybe_unused af8133j_runtime_suspend(struct device *dev)
|
|
+{
|
|
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
|
+ struct af8133j_data *data = iio_priv(indio_dev);
|
|
|
|
af8133j_power_down(data);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
+static int __maybe_unused af8133j_runtime_resume(struct device *dev)
|
|
+{
|
|
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
|
+ struct af8133j_data *data = iio_priv(indio_dev);
|
|
+
|
|
+ return af8133j_power_up(data);
|
|
+}
|
|
+
|
|
+const struct dev_pm_ops af8133j_pm_ops = {
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
|
+ SET_RUNTIME_PM_OPS(af8133j_runtime_suspend, af8133j_runtime_resume, NULL)
|
|
+};
|
|
+
|
|
static const struct of_device_id af8133j_of_match[] = {
|
|
{ .compatible = "voltafield,af8133j", },
|
|
{ }
|
|
@@ -319,10 +380,11 @@ static struct i2c_driver af8133j_driver = {
|
|
.driver = {
|
|
.name = AF8133J_DRV_NAME,
|
|
.of_match_table = af8133j_of_match,
|
|
+ .pm = &af8133j_pm_ops,
|
|
},
|
|
- .probe = af8133j_probe,
|
|
- .remove = af8133j_remove,
|
|
- .id_table = af8133j_id,
|
|
+ .probe = af8133j_probe,
|
|
+ .remove = af8133j_remove,
|
|
+ .id_table = af8133j_id,
|
|
};
|
|
|
|
module_i2c_driver(af8133j_driver);
|
|
--
|
|
Armbian
|
|
|