summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2025-02-03 14:12:22 +0000
committerMark Brown <broonie@kernel.org>2025-02-03 14:12:22 +0000
commit3c32a4386909e8023b3c49253fec33d267be16bb (patch)
tree0b1f5a1e1ee85ed5295b8913d7d19c834a4fba4a
parentf5aab0438ef17f01c5ecd25e61ae6a03f82a4586 (diff)
parent5a6a461079decea452fdcae955bccecf92e07e97 (diff)
regulator: Add device tree support to AD5398
Merge series from Isaac Scott <isaac.scott@ideasonboard.com>: The AD5398 is a DAC that can be used to control current flow in circuits in a wide variety of applications such as motor control, or in my case, LED control. I found when working with the current driver that it did not work for my use case. It transpired that it only had support for platform_data, and didn't appear to be correctly implemented according to the datasheet, which can be found here: https://www.analog.com/media/en/technical-documentation/data-sheets/ad5398.pdf One example of this is the "soft power-down" bit being referred to in the driver as simply "enable", which gives the impression that the setting that bit will allow current through the regulator, which it does not. This series allows the regulator to be given its constraints via the device tree, and makes the function of the enable register much more obvious.
-rw-r--r--drivers/regulator/ad5398.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index 40f7dba42b5a..0274f41d0233 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -14,8 +14,9 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
-#define AD5398_CURRENT_EN_MASK 0x8000
+#define AD5398_SW_POWER_DOWN BIT(16)
struct ad5398_chip_info {
struct i2c_client *client;
@@ -113,7 +114,7 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int
/* prepare register data */
selector = (selector << chip->current_offset) & chip->current_mask;
- data = (unsigned short)selector | (data & AD5398_CURRENT_EN_MASK);
+ data = (unsigned short)selector | (data & AD5398_SW_POWER_DOWN);
/* write the new current value back as well as enable bit */
ret = ad5398_write_reg(client, data);
@@ -132,10 +133,10 @@ static int ad5398_is_enabled(struct regulator_dev *rdev)
if (ret < 0)
return ret;
- if (data & AD5398_CURRENT_EN_MASK)
- return 1;
- else
+ if (data & AD5398_SW_POWER_DOWN)
return 0;
+ else
+ return 1;
}
static int ad5398_enable(struct regulator_dev *rdev)
@@ -149,10 +150,10 @@ static int ad5398_enable(struct regulator_dev *rdev)
if (ret < 0)
return ret;
- if (data & AD5398_CURRENT_EN_MASK)
+ if (!(data & AD5398_SW_POWER_DOWN))
return 0;
- data |= AD5398_CURRENT_EN_MASK;
+ data &= ~AD5398_SW_POWER_DOWN;
ret = ad5398_write_reg(client, data);
@@ -170,10 +171,10 @@ static int ad5398_disable(struct regulator_dev *rdev)
if (ret < 0)
return ret;
- if (!(data & AD5398_CURRENT_EN_MASK))
+ if (data & AD5398_SW_POWER_DOWN)
return 0;
- data &= ~AD5398_CURRENT_EN_MASK;
+ data |= AD5398_SW_POWER_DOWN;
ret = ad5398_write_reg(client, data);
@@ -221,15 +222,20 @@ static int ad5398_probe(struct i2c_client *client)
const struct ad5398_current_data_format *df =
(struct ad5398_current_data_format *)id->driver_data;
- if (!init_data)
- return -EINVAL;
-
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
config.dev = &client->dev;
+ if (client->dev.of_node)
+ init_data = of_get_regulator_init_data(&client->dev,
+ client->dev.of_node,
+ &ad5398_reg);
+ if (!init_data)
+ return -EINVAL;
+
config.init_data = init_data;
+ config.of_node = client->dev.of_node;
config.driver_data = chip;
chip->client = client;