brintos

brintos / linux-shallow public Read only

0
0
Text · 9.0 KiB · 18ba3ea Raw
388 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 /*3  * iio/dac/max5821.c4  * Copyright (C) 2014 Philippe Reynes5  */6 7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/i2c.h>10#include <linux/iio/iio.h>11#include <linux/regulator/consumer.h>12 13#define MAX5821_MAX_DAC_CHANNELS		214 15/* command bytes */16#define MAX5821_LOAD_DAC_A_IN_REG_B		0x0017#define MAX5821_LOAD_DAC_B_IN_REG_A		0x1018#define MAX5821_EXTENDED_COMMAND_MODE		0xf019#define MAX5821_READ_DAC_A_COMMAND		0xf120#define MAX5821_READ_DAC_B_COMMAND		0xf221 22#define MAX5821_EXTENDED_POWER_UP		0x0023#define MAX5821_EXTENDED_POWER_DOWN_MODE0	0x0124#define MAX5821_EXTENDED_POWER_DOWN_MODE1	0x0225#define MAX5821_EXTENDED_POWER_DOWN_MODE2	0x0326#define MAX5821_EXTENDED_DAC_A			0x0427#define MAX5821_EXTENDED_DAC_B			0x0828 29enum max5821_device_ids {30	ID_MAX5821,31};32 33struct max5821_data {34	struct i2c_client	*client;35	struct regulator	*vref_reg;36	unsigned short		vref_mv;37	bool			powerdown[MAX5821_MAX_DAC_CHANNELS];38	u8			powerdown_mode[MAX5821_MAX_DAC_CHANNELS];39	struct mutex		lock;40};41 42static const char * const max5821_powerdown_modes[] = {43	"three_state",44	"1kohm_to_gnd",45	"100kohm_to_gnd",46};47 48enum {49	MAX5821_THREE_STATE,50	MAX5821_1KOHM_TO_GND,51	MAX5821_100KOHM_TO_GND52};53 54static int max5821_get_powerdown_mode(struct iio_dev *indio_dev,55				      const struct iio_chan_spec *chan)56{57	struct max5821_data *st = iio_priv(indio_dev);58 59	return st->powerdown_mode[chan->channel];60}61 62static int max5821_set_powerdown_mode(struct iio_dev *indio_dev,63				      const struct iio_chan_spec *chan,64				      unsigned int mode)65{66	struct max5821_data *st = iio_priv(indio_dev);67 68	st->powerdown_mode[chan->channel] = mode;69 70	return 0;71}72 73static const struct iio_enum max5821_powerdown_mode_enum = {74	.items = max5821_powerdown_modes,75	.num_items = ARRAY_SIZE(max5821_powerdown_modes),76	.get = max5821_get_powerdown_mode,77	.set = max5821_set_powerdown_mode,78};79 80static ssize_t max5821_read_dac_powerdown(struct iio_dev *indio_dev,81					  uintptr_t private,82					  const struct iio_chan_spec *chan,83					  char *buf)84{85	struct max5821_data *st = iio_priv(indio_dev);86 87	return sysfs_emit(buf, "%d\n", st->powerdown[chan->channel]);88}89 90static int max5821_sync_powerdown_mode(struct max5821_data *data,91				       const struct iio_chan_spec *chan)92{93	u8 outbuf[2];94 95	outbuf[0] = MAX5821_EXTENDED_COMMAND_MODE;96 97	if (chan->channel == 0)98		outbuf[1] = MAX5821_EXTENDED_DAC_A;99	else100		outbuf[1] = MAX5821_EXTENDED_DAC_B;101 102	if (data->powerdown[chan->channel])103		outbuf[1] |= data->powerdown_mode[chan->channel] + 1;104	else105		outbuf[1] |= MAX5821_EXTENDED_POWER_UP;106 107	return i2c_master_send(data->client, outbuf, 2);108}109 110static ssize_t max5821_write_dac_powerdown(struct iio_dev *indio_dev,111					   uintptr_t private,112					   const struct iio_chan_spec *chan,113					   const char *buf, size_t len)114{115	struct max5821_data *data = iio_priv(indio_dev);116	bool powerdown;117	int ret;118 119	ret = kstrtobool(buf, &powerdown);120	if (ret)121		return ret;122 123	data->powerdown[chan->channel] = powerdown;124 125	ret = max5821_sync_powerdown_mode(data, chan);126	if (ret < 0)127		return ret;128 129	return len;130}131 132static const struct iio_chan_spec_ext_info max5821_ext_info[] = {133	{134		.name = "powerdown",135		.read = max5821_read_dac_powerdown,136		.write = max5821_write_dac_powerdown,137		.shared = IIO_SEPARATE,138	},139	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &max5821_powerdown_mode_enum),140	IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &max5821_powerdown_mode_enum),141	{ },142};143 144#define MAX5821_CHANNEL(chan) {					\145	.type = IIO_VOLTAGE,					\146	.indexed = 1,						\147	.output = 1,						\148	.channel = (chan),					\149	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\150	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),	\151	.ext_info = max5821_ext_info,				\152}153 154static const struct iio_chan_spec max5821_channels[] = {155	MAX5821_CHANNEL(0),156	MAX5821_CHANNEL(1)157};158 159static const u8 max5821_read_dac_command[] = {160	MAX5821_READ_DAC_A_COMMAND,161	MAX5821_READ_DAC_B_COMMAND162};163 164static const u8 max5821_load_dac_command[] = {165	MAX5821_LOAD_DAC_A_IN_REG_B,166	MAX5821_LOAD_DAC_B_IN_REG_A167};168 169static int max5821_get_value(struct iio_dev *indio_dev,170			     int *val, int channel)171{172	struct max5821_data *data = iio_priv(indio_dev);173	struct i2c_client *client = data->client;174	u8 outbuf[1];175	u8 inbuf[2];176	int ret;177 178	if ((channel != 0) && (channel != 1))179		return -EINVAL;180 181	outbuf[0] = max5821_read_dac_command[channel];182 183	mutex_lock(&data->lock);184 185	ret = i2c_master_send(client, outbuf, 1);186	if (ret < 0) {187		mutex_unlock(&data->lock);188		return ret;189	} else if (ret != 1) {190		mutex_unlock(&data->lock);191		return -EIO;192	}193 194	ret = i2c_master_recv(client, inbuf, 2);195	if (ret < 0) {196		mutex_unlock(&data->lock);197		return ret;198	} else if (ret != 2) {199		mutex_unlock(&data->lock);200		return -EIO;201	}202 203	mutex_unlock(&data->lock);204 205	*val = ((inbuf[0] & 0x0f) << 6) | (inbuf[1] >> 2);206 207	return IIO_VAL_INT;208}209 210static int max5821_set_value(struct iio_dev *indio_dev,211			     int val, int channel)212{213	struct max5821_data *data = iio_priv(indio_dev);214	struct i2c_client *client = data->client;215	u8 outbuf[2];216	int ret;217 218	if ((val < 0) || (val > 1023))219		return -EINVAL;220 221	if ((channel != 0) && (channel != 1))222		return -EINVAL;223 224	outbuf[0] = max5821_load_dac_command[channel];225	outbuf[0] |= val >> 6;226	outbuf[1] = (val & 0x3f) << 2;227 228	ret = i2c_master_send(client, outbuf, 2);229	if (ret < 0)230		return ret;231	else if (ret != 2)232		return -EIO;233	else234		return 0;235}236 237static int max5821_read_raw(struct iio_dev *indio_dev,238			   struct iio_chan_spec const *chan,239			   int *val, int *val2, long mask)240{241	struct max5821_data *data = iio_priv(indio_dev);242 243	switch (mask) {244	case IIO_CHAN_INFO_RAW:245		return max5821_get_value(indio_dev, val, chan->channel);246	case IIO_CHAN_INFO_SCALE:247		*val = data->vref_mv;248		*val2 = 10;249		return IIO_VAL_FRACTIONAL_LOG2;250	default:251		return -EINVAL;252	}253}254 255static int max5821_write_raw(struct iio_dev *indio_dev,256			     struct iio_chan_spec const *chan,257			     int val, int val2, long mask)258{259	if (val2 != 0)260		return -EINVAL;261 262	switch (mask) {263	case IIO_CHAN_INFO_RAW:264		return max5821_set_value(indio_dev, val, chan->channel);265	default:266		return -EINVAL;267	}268}269 270static int max5821_suspend(struct device *dev)271{272	u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,273			 MAX5821_EXTENDED_DAC_A |274			 MAX5821_EXTENDED_DAC_B |275			 MAX5821_EXTENDED_POWER_DOWN_MODE2 };276 277	return i2c_master_send(to_i2c_client(dev), outbuf, 2);278}279 280static int max5821_resume(struct device *dev)281{282	u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,283			 MAX5821_EXTENDED_DAC_A |284			 MAX5821_EXTENDED_DAC_B |285			 MAX5821_EXTENDED_POWER_UP };286 287	return i2c_master_send(to_i2c_client(dev), outbuf, 2);288}289 290static DEFINE_SIMPLE_DEV_PM_OPS(max5821_pm_ops, max5821_suspend,291				max5821_resume);292 293static const struct iio_info max5821_info = {294	.read_raw = max5821_read_raw,295	.write_raw = max5821_write_raw,296};297 298static void max5821_regulator_disable(void *reg)299{300	regulator_disable(reg);301}302 303static int max5821_probe(struct i2c_client *client)304{305	const struct i2c_device_id *id = i2c_client_get_device_id(client);306	struct max5821_data *data;307	struct iio_dev *indio_dev;308	u32 tmp;309	int ret;310 311	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));312	if (!indio_dev)313		return -ENOMEM;314	data = iio_priv(indio_dev);315	data->client = client;316	mutex_init(&data->lock);317 318	/* max5821 start in powerdown mode 100Kohm to ground */319	for (tmp = 0; tmp < MAX5821_MAX_DAC_CHANNELS; tmp++) {320		data->powerdown[tmp] = true;321		data->powerdown_mode[tmp] = MAX5821_100KOHM_TO_GND;322	}323 324	data->vref_reg = devm_regulator_get(&client->dev, "vref");325	if (IS_ERR(data->vref_reg))326		return dev_err_probe(&client->dev, PTR_ERR(data->vref_reg),327				     "Failed to get vref regulator\n");328 329	ret = regulator_enable(data->vref_reg);330	if (ret) {331		dev_err(&client->dev,332			"Failed to enable vref regulator: %d\n", ret);333		return ret;334	}335 336	ret = devm_add_action_or_reset(&client->dev, max5821_regulator_disable,337				       data->vref_reg);338	if (ret) {339		dev_err(&client->dev,340			"Failed to add action to managed regulator: %d\n", ret);341		return ret;342	}343 344	ret = regulator_get_voltage(data->vref_reg);345	if (ret < 0) {346		dev_err(&client->dev,347			"Failed to get voltage on regulator: %d\n", ret);348		return ret;349	}350 351	data->vref_mv = ret / 1000;352 353	indio_dev->name = id->name;354	indio_dev->num_channels = ARRAY_SIZE(max5821_channels);355	indio_dev->channels = max5821_channels;356	indio_dev->modes = INDIO_DIRECT_MODE;357	indio_dev->info = &max5821_info;358 359	return devm_iio_device_register(&client->dev, indio_dev);360}361 362static const struct i2c_device_id max5821_id[] = {363	{ "max5821", ID_MAX5821 },364	{ }365};366MODULE_DEVICE_TABLE(i2c, max5821_id);367 368static const struct of_device_id max5821_of_match[] = {369	{ .compatible = "maxim,max5821" },370	{ }371};372MODULE_DEVICE_TABLE(of, max5821_of_match);373 374static struct i2c_driver max5821_driver = {375	.driver = {376		.name	= "max5821",377		.of_match_table = max5821_of_match,378		.pm     = pm_sleep_ptr(&max5821_pm_ops),379	},380	.probe		= max5821_probe,381	.id_table	= max5821_id,382};383module_i2c_driver(max5821_driver);384 385MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");386MODULE_DESCRIPTION("MAX5821 DAC");387MODULE_LICENSE("GPL v2");388