Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.

+18 -12
+18 -12
drivers/regulator/ad5398.c
··· 14 14 #include <linux/platform_device.h> 15 15 #include <linux/regulator/driver.h> 16 16 #include <linux/regulator/machine.h> 17 + #include <linux/regulator/of_regulator.h> 17 18 18 - #define AD5398_CURRENT_EN_MASK 0x8000 19 + #define AD5398_SW_POWER_DOWN BIT(16) 19 20 20 21 struct ad5398_chip_info { 21 22 struct i2c_client *client; ··· 114 113 115 114 /* prepare register data */ 116 115 selector = (selector << chip->current_offset) & chip->current_mask; 117 - data = (unsigned short)selector | (data & AD5398_CURRENT_EN_MASK); 116 + data = (unsigned short)selector | (data & AD5398_SW_POWER_DOWN); 118 117 119 118 /* write the new current value back as well as enable bit */ 120 119 ret = ad5398_write_reg(client, data); ··· 133 132 if (ret < 0) 134 133 return ret; 135 134 136 - if (data & AD5398_CURRENT_EN_MASK) 137 - return 1; 138 - else 135 + if (data & AD5398_SW_POWER_DOWN) 139 136 return 0; 137 + else 138 + return 1; 140 139 } 141 140 142 141 static int ad5398_enable(struct regulator_dev *rdev) ··· 150 149 if (ret < 0) 151 150 return ret; 152 151 153 - if (data & AD5398_CURRENT_EN_MASK) 152 + if (!(data & AD5398_SW_POWER_DOWN)) 154 153 return 0; 155 154 156 - data |= AD5398_CURRENT_EN_MASK; 155 + data &= ~AD5398_SW_POWER_DOWN; 157 156 158 157 ret = ad5398_write_reg(client, data); 159 158 ··· 171 170 if (ret < 0) 172 171 return ret; 173 172 174 - if (!(data & AD5398_CURRENT_EN_MASK)) 173 + if (data & AD5398_SW_POWER_DOWN) 175 174 return 0; 176 175 177 - data &= ~AD5398_CURRENT_EN_MASK; 176 + data |= AD5398_SW_POWER_DOWN; 178 177 179 178 ret = ad5398_write_reg(client, data); 180 179 ··· 222 221 const struct ad5398_current_data_format *df = 223 222 (struct ad5398_current_data_format *)id->driver_data; 224 223 225 - if (!init_data) 226 - return -EINVAL; 227 - 228 224 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 229 225 if (!chip) 230 226 return -ENOMEM; 231 227 232 228 config.dev = &client->dev; 229 + if (client->dev.of_node) 230 + init_data = of_get_regulator_init_data(&client->dev, 231 + client->dev.of_node, 232 + &ad5398_reg); 233 + if (!init_data) 234 + return -EINVAL; 235 + 233 236 config.init_data = init_data; 237 + config.of_node = client->dev.of_node; 234 238 config.driver_data = chip; 235 239 236 240 chip->client = client;