summaryrefslogtreecommitdiff
path: root/drivers/iio/dac/mcp4725.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/dac/mcp4725.c')
-rw-r--r--drivers/iio/dac/mcp4725.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 46bf758760f8..23b9e3a09ec8 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -24,15 +24,18 @@
#include <linux/iio/dac/mcp4725.h>
-#define MCP4725_DRV_NAME "mcp4725"
-
#define MCP472X_REF_VDD 0x00
#define MCP472X_REF_VREF_UNBUFFERED 0x02
#define MCP472X_REF_VREF_BUFFERED 0x03
+struct mcp4725_chip_info {
+ const struct iio_chan_spec *chan_spec;
+ u8 dac_reg_offset;
+ bool use_ext_ref_voltage;
+};
+
struct mcp4725_data {
struct i2c_client *client;
- int id;
unsigned ref_mode;
bool vref_buffered;
u16 dac_value;
@@ -47,12 +50,18 @@ static int mcp4725_suspend(struct device *dev)
struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
to_i2c_client(dev)));
u8 outbuf[2];
+ int ret;
outbuf[0] = (data->powerdown_mode + 1) << 4;
outbuf[1] = 0;
data->powerdown = true;
- return i2c_master_send(data->client, outbuf, 2);
+ ret = i2c_master_send(data->client, outbuf, 2);
+ if (ret < 0)
+ return ret;
+ else if (ret != 2)
+ return -EIO;
+ return 0;
}
static int mcp4725_resume(struct device *dev)
@@ -60,13 +69,19 @@ static int mcp4725_resume(struct device *dev)
struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
to_i2c_client(dev)));
u8 outbuf[2];
+ int ret;
/* restore previous DAC value */
outbuf[0] = (data->dac_value >> 8) & 0xf;
outbuf[1] = data->dac_value & 0xff;
data->powerdown = false;
- return i2c_master_send(data->client, outbuf, 2);
+ ret = i2c_master_send(data->client, outbuf, 2);
+ if (ret < 0)
+ return ret;
+ else if (ret != 2)
+ return -EIO;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend,
mcp4725_resume);
@@ -224,7 +239,7 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
&mcp472x_powerdown_mode_enum[MCP4725]),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
&mcp472x_powerdown_mode_enum[MCP4725]),
- { },
+ { }
};
static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = {
@@ -238,7 +253,7 @@ static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = {
&mcp472x_powerdown_mode_enum[MCP4726]),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
&mcp472x_powerdown_mode_enum[MCP4726]),
- { },
+ { }
};
static const struct iio_chan_spec mcp472x_channel[] = {
@@ -362,7 +377,7 @@ static int mcp4725_probe_dt(struct device *dev,
struct mcp4725_platform_data *pdata)
{
/* check if is the vref-supply defined */
- pdata->use_vref = device_property_read_bool(dev, "vref-supply");
+ pdata->use_vref = device_property_present(dev, "vref-supply");
pdata->vref_buffered =
device_property_read_bool(dev, "microchip,vref-buffered");
@@ -372,6 +387,7 @@ static int mcp4725_probe_dt(struct device *dev,
static int mcp4725_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ const struct mcp4725_chip_info *info;
struct mcp4725_data *data;
struct iio_dev *indio_dev;
struct mcp4725_platform_data *pdata, pdata_dt;
@@ -386,10 +402,7 @@ static int mcp4725_probe(struct i2c_client *client)
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
- if (dev_fwnode(&client->dev))
- data->id = (uintptr_t)device_get_match_data(&client->dev);
- else
- data->id = id->driver_data;
+ info = i2c_get_match_data(client);
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
@@ -402,7 +415,7 @@ static int mcp4725_probe(struct i2c_client *client)
pdata = &pdata_dt;
}
- if (data->id == MCP4725 && pdata->use_vref) {
+ if (info->use_ext_ref_voltage && pdata->use_vref) {
dev_err(&client->dev,
"external reference is unavailable on MCP4725");
return -EINVAL;
@@ -443,12 +456,12 @@ static int mcp4725_probe(struct i2c_client *client)
indio_dev->name = id->name;
indio_dev->info = &mcp4725_info;
- indio_dev->channels = &mcp472x_channel[id->driver_data];
+ indio_dev->channels = info->chan_spec;
indio_dev->num_channels = 1;
indio_dev->modes = INDIO_DIRECT_MODE;
/* read current DAC value and settings */
- err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
+ err = i2c_master_recv(client, inbuf, info->dac_reg_offset);
if (err < 0) {
dev_err(&client->dev, "failed to read DAC value");
@@ -458,10 +471,10 @@ static int mcp4725_probe(struct i2c_client *client)
data->powerdown = pd > 0;
data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
- if (data->id == MCP4726)
+ if (!info->use_ext_ref_voltage)
ref = (inbuf[3] >> 3) & 0x3;
- if (data->id == MCP4726 && ref != data->ref_mode) {
+ if (!info->use_ext_ref_voltage && ref != data->ref_mode) {
dev_info(&client->dev,
"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
data->ref_mode, ref, data->ref_mode);
@@ -498,9 +511,20 @@ static void mcp4725_remove(struct i2c_client *client)
regulator_disable(data->vdd_reg);
}
+static const struct mcp4725_chip_info mcp4725 = {
+ .chan_spec = &mcp472x_channel[MCP4725],
+ .dac_reg_offset = 3,
+ .use_ext_ref_voltage = true,
+};
+
+static const struct mcp4725_chip_info mcp4726 = {
+ .chan_spec = &mcp472x_channel[MCP4726],
+ .dac_reg_offset = 4,
+};
+
static const struct i2c_device_id mcp4725_id[] = {
- { "mcp4725", MCP4725 },
- { "mcp4726", MCP4726 },
+ { "mcp4725", (kernel_ulong_t)&mcp4725 },
+ { "mcp4726", (kernel_ulong_t)&mcp4726 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp4725_id);
@@ -508,11 +532,11 @@ MODULE_DEVICE_TABLE(i2c, mcp4725_id);
static const struct of_device_id mcp4725_of_match[] = {
{
.compatible = "microchip,mcp4725",
- .data = (void *)MCP4725
+ .data = &mcp4725
},
{
.compatible = "microchip,mcp4726",
- .data = (void *)MCP4726
+ .data = &mcp4726
},
{ }
};
@@ -520,11 +544,11 @@ MODULE_DEVICE_TABLE(of, mcp4725_of_match);
static struct i2c_driver mcp4725_driver = {
.driver = {
- .name = MCP4725_DRV_NAME,
+ .name = "mcp4725",
.of_match_table = mcp4725_of_match,
.pm = pm_sleep_ptr(&mcp4725_pm_ops),
},
- .probe_new = mcp4725_probe,
+ .probe = mcp4725_probe,
.remove = mcp4725_remove,
.id_table = mcp4725_id,
};