1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Driver for Microchip MCP3911, Two-channel Analog Front End 4 * 5 * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com> 6 * Copyright (C) 2018 Kent Gustavsson <kent@minoris.se> 7 */ 8#include <linux/clk.h> 9#include <linux/delay.h> 10#include <linux/err.h> 11#include <linux/iio/iio.h> 12#include <linux/module.h> 13#include <linux/regulator/consumer.h> 14#include <linux/spi/spi.h> 15 16#define MCP3911_REG_CHANNEL0 0x00 17#define MCP3911_REG_CHANNEL1 0x03 18#define MCP3911_REG_MOD 0x06 19#define MCP3911_REG_PHASE 0x07 20#define MCP3911_REG_GAIN 0x09 21 22#define MCP3911_REG_STATUSCOM 0x0a 23#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4) 24#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3) 25#define MCP3911_STATUSCOM_EN_OFFCAL BIT(2) 26#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) 27 28#define MCP3911_REG_CONFIG 0x0c 29#define MCP3911_CONFIG_CLKEXT BIT(1) 30#define MCP3911_CONFIG_VREFEXT BIT(2) 31 32#define MCP3911_REG_OFFCAL_CH0 0x0e 33#define MCP3911_REG_GAINCAL_CH0 0x11 34#define MCP3911_REG_OFFCAL_CH1 0x14 35#define MCP3911_REG_GAINCAL_CH1 0x17 36#define MCP3911_REG_VREFCAL 0x1a 37 38#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) 39#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6) 40 41/* Internal voltage reference in mV */ 42#define MCP3911_INT_VREF_MV 1200 43 44#define MCP3911_REG_READ(reg, id) ((((reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff) 45#define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff) 46 47#define MCP3911_NUM_CHANNELS 2 48 49struct mcp3911 { 50 struct spi_device *spi; 51 struct mutex lock; 52 struct regulator *vref; 53 struct clk *clki; 54 u32 dev_addr; 55}; 56 57static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) 58{ 59 int ret; 60 61 reg = MCP3911_REG_READ(reg, adc->dev_addr); 62 ret = spi_write_then_read(adc->spi, ®, 1, val, len); 63 if (ret < 0) 64 return ret; 65 66 be32_to_cpus(val); 67 *val >>= ((4 - len) * 8); 68 dev_dbg(&adc->spi->dev, "reading 0x%x from register 0x%x\n", *val, 69 reg >> 1); 70 return ret; 71} 72 73static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len) 74{ 75 dev_dbg(&adc->spi->dev, "writing 0x%x to register 0x%x\n", val, reg); 76 77 val <<= (3 - len) * 8; 78 cpu_to_be32s(&val); 79 val |= MCP3911_REG_WRITE(reg, adc->dev_addr); 80 81 return spi_write(adc->spi, &val, len + 1); 82} 83 84static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, 85 u32 val, u8 len) 86{ 87 u32 tmp; 88 int ret; 89 90 ret = mcp3911_read(adc, reg, &tmp, len); 91 if (ret) 92 return ret; 93 94 val &= mask; 95 val |= tmp & ~mask; 96 return mcp3911_write(adc, reg, val, len); 97} 98 99static int mcp3911_read_raw(struct iio_dev *indio_dev, 100 struct iio_chan_spec const *channel, int *val, 101 int *val2, long mask) 102{ 103 struct mcp3911 *adc = iio_priv(indio_dev); 104 int ret = -EINVAL; 105 106 mutex_lock(&adc->lock); 107 switch (mask) { 108 case IIO_CHAN_INFO_RAW: 109 ret = mcp3911_read(adc, 110 MCP3911_CHANNEL(channel->channel), val, 3); 111 if (ret) 112 goto out; 113 114 *val = sign_extend32(*val, 23); 115 116 ret = IIO_VAL_INT; 117 break; 118 119 case IIO_CHAN_INFO_OFFSET: 120 ret = mcp3911_read(adc, 121 MCP3911_OFFCAL(channel->channel), val, 3); 122 if (ret) 123 goto out; 124 125 ret = IIO_VAL_INT; 126 break; 127 128 case IIO_CHAN_INFO_SCALE: 129 if (adc->vref) { 130 ret = regulator_get_voltage(adc->vref); 131 if (ret < 0) { 132 dev_err(indio_dev->dev.parent, 133 "failed to get vref voltage: %d\n", 134 ret); 135 goto out; 136 } 137 138 *val = ret / 1000; 139 } else { 140 *val = MCP3911_INT_VREF_MV; 141 } 142 143 /* 144 * For 24bit Conversion 145 * Raw = ((Voltage)/(Vref) * 2^23 * Gain * 1.5 146 * Voltage = Raw * (Vref)/(2^23 * Gain * 1.5) 147 */ 148 149 /* val2 = (2^23 * 1.5) */ 150 *val2 = 12582912; 151 ret = IIO_VAL_FRACTIONAL; 152 break; 153 } 154 155out: 156 mutex_unlock(&adc->lock); 157 return ret; 158} 159 160static int mcp3911_write_raw(struct iio_dev *indio_dev, 161 struct iio_chan_spec const *channel, int val, 162 int val2, long mask) 163{ 164 struct mcp3911 *adc = iio_priv(indio_dev); 165 int ret = -EINVAL; 166 167 mutex_lock(&adc->lock); 168 switch (mask) { 169 case IIO_CHAN_INFO_OFFSET: 170 if (val2 != 0) { 171 ret = -EINVAL; 172 goto out; 173 } 174 175 /* Write offset */ 176 ret = mcp3911_write(adc, MCP3911_OFFCAL(channel->channel), val, 177 3); 178 if (ret) 179 goto out; 180 181 /* Enable offset*/ 182 ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, 183 MCP3911_STATUSCOM_EN_OFFCAL, 184 MCP3911_STATUSCOM_EN_OFFCAL, 2); 185 break; 186 } 187 188out: 189 mutex_unlock(&adc->lock); 190 return ret; 191} 192 193#define MCP3911_CHAN(idx) { \ 194 .type = IIO_VOLTAGE, \ 195 .indexed = 1, \ 196 .channel = idx, \ 197 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 198 BIT(IIO_CHAN_INFO_OFFSET) | \ 199 BIT(IIO_CHAN_INFO_SCALE), \ 200} 201 202static const struct iio_chan_spec mcp3911_channels[] = { 203 MCP3911_CHAN(0), 204 MCP3911_CHAN(1), 205}; 206 207static const struct iio_info mcp3911_info = { 208 .read_raw = mcp3911_read_raw, 209 .write_raw = mcp3911_write_raw, 210}; 211 212static int mcp3911_config(struct mcp3911 *adc, struct device_node *of_node) 213{ 214 u32 configreg; 215 int ret; 216 217 of_property_read_u32(of_node, "device-addr", &adc->dev_addr); 218 if (adc->dev_addr > 3) { 219 dev_err(&adc->spi->dev, 220 "invalid device address (%i). Must be in range 0-3.\n", 221 adc->dev_addr); 222 return -EINVAL; 223 } 224 dev_dbg(&adc->spi->dev, "use device address %i\n", adc->dev_addr); 225 226 ret = mcp3911_read(adc, MCP3911_REG_CONFIG, &configreg, 2); 227 if (ret) 228 return ret; 229 230 if (adc->vref) { 231 dev_dbg(&adc->spi->dev, "use external voltage reference\n"); 232 configreg |= MCP3911_CONFIG_VREFEXT; 233 } else { 234 dev_dbg(&adc->spi->dev, 235 "use internal voltage reference (1.2V)\n"); 236 configreg &= ~MCP3911_CONFIG_VREFEXT; 237 } 238 239 if (adc->clki) { 240 dev_dbg(&adc->spi->dev, "use external clock as clocksource\n"); 241 configreg |= MCP3911_CONFIG_CLKEXT; 242 } else { 243 dev_dbg(&adc->spi->dev, 244 "use crystal oscillator as clocksource\n"); 245 configreg &= ~MCP3911_CONFIG_CLKEXT; 246 } 247 248 return mcp3911_write(adc, MCP3911_REG_CONFIG, configreg, 2); 249} 250 251static int mcp3911_probe(struct spi_device *spi) 252{ 253 struct iio_dev *indio_dev; 254 struct mcp3911 *adc; 255 int ret; 256 257 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); 258 if (!indio_dev) 259 return -ENOMEM; 260 261 adc = iio_priv(indio_dev); 262 adc->spi = spi; 263 264 adc->vref = devm_regulator_get_optional(&adc->spi->dev, "vref"); 265 if (IS_ERR(adc->vref)) { 266 if (PTR_ERR(adc->vref) == -ENODEV) { 267 adc->vref = NULL; 268 } else { 269 dev_err(&adc->spi->dev, 270 "failed to get regulator (%ld)\n", 271 PTR_ERR(adc->vref)); 272 return PTR_ERR(adc->vref); 273 } 274 275 } else { 276 ret = regulator_enable(adc->vref); 277 if (ret) 278 return ret; 279 } 280 281 adc->clki = devm_clk_get(&adc->spi->dev, NULL); 282 if (IS_ERR(adc->clki)) { 283 if (PTR_ERR(adc->clki) == -ENOENT) { 284 adc->clki = NULL; 285 } else { 286 dev_err(&adc->spi->dev, 287 "failed to get adc clk (%ld)\n", 288 PTR_ERR(adc->clki)); 289 ret = PTR_ERR(adc->clki); 290 goto reg_disable; 291 } 292 } else { 293 ret = clk_prepare_enable(adc->clki); 294 if (ret < 0) { 295 dev_err(&adc->spi->dev, 296 "Failed to enable clki: %d\n", ret); 297 goto reg_disable; 298 } 299 } 300 301 ret = mcp3911_config(adc, spi->dev.of_node); 302 if (ret) 303 goto clk_disable; 304 305 indio_dev->name = spi_get_device_id(spi)->name; 306 indio_dev->modes = INDIO_DIRECT_MODE; 307 indio_dev->info = &mcp3911_info; 308 spi_set_drvdata(spi, indio_dev); 309 310 indio_dev->channels = mcp3911_channels; 311 indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels); 312 313 mutex_init(&adc->lock); 314 315 ret = iio_device_register(indio_dev); 316 if (ret) 317 goto clk_disable; 318 319 return ret; 320 321clk_disable: 322 clk_disable_unprepare(adc->clki); 323reg_disable: 324 if (adc->vref) 325 regulator_disable(adc->vref); 326 327 return ret; 328} 329 330static int mcp3911_remove(struct spi_device *spi) 331{ 332 struct iio_dev *indio_dev = spi_get_drvdata(spi); 333 struct mcp3911 *adc = iio_priv(indio_dev); 334 335 iio_device_unregister(indio_dev); 336 337 clk_disable_unprepare(adc->clki); 338 if (adc->vref) 339 regulator_disable(adc->vref); 340 341 return 0; 342} 343 344static const struct of_device_id mcp3911_dt_ids[] = { 345 { .compatible = "microchip,mcp3911" }, 346 { } 347}; 348MODULE_DEVICE_TABLE(of, mcp3911_dt_ids); 349 350static const struct spi_device_id mcp3911_id[] = { 351 { "mcp3911", 0 }, 352 { } 353}; 354MODULE_DEVICE_TABLE(spi, mcp3911_id); 355 356static struct spi_driver mcp3911_driver = { 357 .driver = { 358 .name = "mcp3911", 359 .of_match_table = mcp3911_dt_ids, 360 }, 361 .probe = mcp3911_probe, 362 .remove = mcp3911_remove, 363 .id_table = mcp3911_id, 364}; 365module_spi_driver(mcp3911_driver); 366 367MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>"); 368MODULE_AUTHOR("Kent Gustavsson <kent@minoris.se>"); 369MODULE_DESCRIPTION("Microchip Technology MCP3911"); 370MODULE_LICENSE("GPL v2"); 371