mcp4922.c (4792B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * mcp4922.c 4 * 5 * Driver for Microchip Digital to Analog Converters. 6 * Supports MCP4902, MCP4912, and MCP4922. 7 * 8 * Copyright (c) 2014 EMAC Inc. 9 */ 10 11#include <linux/module.h> 12#include <linux/init.h> 13#include <linux/spi/spi.h> 14#include <linux/iio/iio.h> 15#include <linux/iio/sysfs.h> 16#include <linux/regulator/consumer.h> 17#include <linux/bitops.h> 18 19#define MCP4922_NUM_CHANNELS 2 20 21enum mcp4922_supported_device_ids { 22 ID_MCP4902, 23 ID_MCP4912, 24 ID_MCP4922, 25}; 26 27struct mcp4922_state { 28 struct spi_device *spi; 29 unsigned int value[MCP4922_NUM_CHANNELS]; 30 unsigned int vref_mv; 31 struct regulator *vref_reg; 32 u8 mosi[2] ____cacheline_aligned; 33}; 34 35#define MCP4922_CHAN(chan, bits) { \ 36 .type = IIO_VOLTAGE, \ 37 .output = 1, \ 38 .indexed = 1, \ 39 .channel = chan, \ 40 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 41 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 42 .scan_type = { \ 43 .sign = 'u', \ 44 .realbits = (bits), \ 45 .storagebits = 16, \ 46 .shift = 12 - (bits), \ 47 }, \ 48} 49 50static int mcp4922_spi_write(struct mcp4922_state *state, u8 addr, u32 val) 51{ 52 state->mosi[1] = val & 0xff; 53 state->mosi[0] = (addr == 0) ? 0x00 : 0x80; 54 state->mosi[0] |= 0x30 | ((val >> 8) & 0x0f); 55 56 return spi_write(state->spi, state->mosi, 2); 57} 58 59static int mcp4922_read_raw(struct iio_dev *indio_dev, 60 struct iio_chan_spec const *chan, 61 int *val, 62 int *val2, 63 long mask) 64{ 65 struct mcp4922_state *state = iio_priv(indio_dev); 66 67 switch (mask) { 68 case IIO_CHAN_INFO_RAW: 69 *val = state->value[chan->channel]; 70 return IIO_VAL_INT; 71 case IIO_CHAN_INFO_SCALE: 72 *val = state->vref_mv; 73 *val2 = chan->scan_type.realbits; 74 return IIO_VAL_FRACTIONAL_LOG2; 75 default: 76 return -EINVAL; 77 } 78} 79 80static int mcp4922_write_raw(struct iio_dev *indio_dev, 81 struct iio_chan_spec const *chan, 82 int val, 83 int val2, 84 long mask) 85{ 86 struct mcp4922_state *state = iio_priv(indio_dev); 87 int ret; 88 89 if (val2 != 0) 90 return -EINVAL; 91 92 switch (mask) { 93 case IIO_CHAN_INFO_RAW: 94 if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0)) 95 return -EINVAL; 96 val <<= chan->scan_type.shift; 97 98 ret = mcp4922_spi_write(state, chan->channel, val); 99 if (!ret) 100 state->value[chan->channel] = val; 101 return ret; 102 103 default: 104 return -EINVAL; 105 } 106} 107 108static const struct iio_chan_spec mcp4922_channels[3][MCP4922_NUM_CHANNELS] = { 109 [ID_MCP4902] = { MCP4922_CHAN(0, 8), MCP4922_CHAN(1, 8) }, 110 [ID_MCP4912] = { MCP4922_CHAN(0, 10), MCP4922_CHAN(1, 10) }, 111 [ID_MCP4922] = { MCP4922_CHAN(0, 12), MCP4922_CHAN(1, 12) }, 112}; 113 114static const struct iio_info mcp4922_info = { 115 .read_raw = &mcp4922_read_raw, 116 .write_raw = &mcp4922_write_raw, 117}; 118 119static int mcp4922_probe(struct spi_device *spi) 120{ 121 struct iio_dev *indio_dev; 122 struct mcp4922_state *state; 123 const struct spi_device_id *id; 124 int ret; 125 126 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state)); 127 if (indio_dev == NULL) 128 return -ENOMEM; 129 130 state = iio_priv(indio_dev); 131 state->spi = spi; 132 state->vref_reg = devm_regulator_get(&spi->dev, "vref"); 133 if (IS_ERR(state->vref_reg)) 134 return dev_err_probe(&spi->dev, PTR_ERR(state->vref_reg), 135 "Vref regulator not specified\n"); 136 137 ret = regulator_enable(state->vref_reg); 138 if (ret) { 139 dev_err(&spi->dev, "Failed to enable vref regulator: %d\n", 140 ret); 141 return ret; 142 } 143 144 ret = regulator_get_voltage(state->vref_reg); 145 if (ret < 0) { 146 dev_err(&spi->dev, "Failed to read vref regulator: %d\n", 147 ret); 148 goto error_disable_reg; 149 } 150 state->vref_mv = ret / 1000; 151 152 spi_set_drvdata(spi, indio_dev); 153 id = spi_get_device_id(spi); 154 indio_dev->info = &mcp4922_info; 155 indio_dev->modes = INDIO_DIRECT_MODE; 156 indio_dev->channels = mcp4922_channels[id->driver_data]; 157 indio_dev->num_channels = MCP4922_NUM_CHANNELS; 158 indio_dev->name = id->name; 159 160 ret = iio_device_register(indio_dev); 161 if (ret) { 162 dev_err(&spi->dev, "Failed to register iio device: %d\n", 163 ret); 164 goto error_disable_reg; 165 } 166 167 return 0; 168 169error_disable_reg: 170 regulator_disable(state->vref_reg); 171 172 return ret; 173} 174 175static void mcp4922_remove(struct spi_device *spi) 176{ 177 struct iio_dev *indio_dev = spi_get_drvdata(spi); 178 struct mcp4922_state *state; 179 180 iio_device_unregister(indio_dev); 181 state = iio_priv(indio_dev); 182 regulator_disable(state->vref_reg); 183} 184 185static const struct spi_device_id mcp4922_id[] = { 186 {"mcp4902", ID_MCP4902}, 187 {"mcp4912", ID_MCP4912}, 188 {"mcp4922", ID_MCP4922}, 189 {} 190}; 191MODULE_DEVICE_TABLE(spi, mcp4922_id); 192 193static struct spi_driver mcp4922_driver = { 194 .driver = { 195 .name = "mcp4922", 196 }, 197 .probe = mcp4922_probe, 198 .remove = mcp4922_remove, 199 .id_table = mcp4922_id, 200}; 201module_spi_driver(mcp4922_driver); 202 203MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>"); 204MODULE_DESCRIPTION("Microchip MCP4902, MCP4912, MCP4922 DAC"); 205MODULE_LICENSE("GPL v2");