Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Driver for Microchip MCP3911, Two-channel Analog Front End
0004  *
0005  * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
0006  * Copyright (C) 2018 Kent Gustavsson <kent@minoris.se>
0007  */
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 #include <linux/iio/iio.h>
0012 #include <linux/module.h>
0013 #include <linux/mod_devicetable.h>
0014 #include <linux/property.h>
0015 #include <linux/regulator/consumer.h>
0016 #include <linux/spi/spi.h>
0017 
0018 #define MCP3911_REG_CHANNEL0        0x00
0019 #define MCP3911_REG_CHANNEL1        0x03
0020 #define MCP3911_REG_MOD         0x06
0021 #define MCP3911_REG_PHASE       0x07
0022 #define MCP3911_REG_GAIN        0x09
0023 
0024 #define MCP3911_REG_STATUSCOM       0x0a
0025 #define MCP3911_STATUSCOM_CH1_24WIDTH   BIT(4)
0026 #define MCP3911_STATUSCOM_CH0_24WIDTH   BIT(3)
0027 #define MCP3911_STATUSCOM_EN_OFFCAL BIT(2)
0028 #define MCP3911_STATUSCOM_EN_GAINCAL    BIT(1)
0029 
0030 #define MCP3911_REG_CONFIG      0x0c
0031 #define MCP3911_CONFIG_CLKEXT       BIT(1)
0032 #define MCP3911_CONFIG_VREFEXT      BIT(2)
0033 
0034 #define MCP3911_REG_OFFCAL_CH0      0x0e
0035 #define MCP3911_REG_GAINCAL_CH0     0x11
0036 #define MCP3911_REG_OFFCAL_CH1      0x14
0037 #define MCP3911_REG_GAINCAL_CH1     0x17
0038 #define MCP3911_REG_VREFCAL     0x1a
0039 
0040 #define MCP3911_CHANNEL(x)      (MCP3911_REG_CHANNEL0 + x * 3)
0041 #define MCP3911_OFFCAL(x)       (MCP3911_REG_OFFCAL_CH0 + x * 6)
0042 
0043 /* Internal voltage reference in mV */
0044 #define MCP3911_INT_VREF_MV     1200
0045 
0046 #define MCP3911_REG_READ(reg, id)   ((((reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff)
0047 #define MCP3911_REG_WRITE(reg, id)  ((((reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff)
0048 
0049 #define MCP3911_NUM_CHANNELS        2
0050 
0051 struct mcp3911 {
0052     struct spi_device *spi;
0053     struct mutex lock;
0054     struct regulator *vref;
0055     struct clk *clki;
0056     u32 dev_addr;
0057 };
0058 
0059 static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len)
0060 {
0061     int ret;
0062 
0063     reg = MCP3911_REG_READ(reg, adc->dev_addr);
0064     ret = spi_write_then_read(adc->spi, &reg, 1, val, len);
0065     if (ret < 0)
0066         return ret;
0067 
0068     be32_to_cpus(val);
0069     *val >>= ((4 - len) * 8);
0070     dev_dbg(&adc->spi->dev, "reading 0x%x from register 0x%x\n", *val,
0071         reg >> 1);
0072     return ret;
0073 }
0074 
0075 static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len)
0076 {
0077     dev_dbg(&adc->spi->dev, "writing 0x%x to register 0x%x\n", val, reg);
0078 
0079     val <<= (3 - len) * 8;
0080     cpu_to_be32s(&val);
0081     val |= MCP3911_REG_WRITE(reg, adc->dev_addr);
0082 
0083     return spi_write(adc->spi, &val, len + 1);
0084 }
0085 
0086 static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
0087         u32 val, u8 len)
0088 {
0089     u32 tmp;
0090     int ret;
0091 
0092     ret = mcp3911_read(adc, reg, &tmp, len);
0093     if (ret)
0094         return ret;
0095 
0096     val &= mask;
0097     val |= tmp & ~mask;
0098     return mcp3911_write(adc, reg, val, len);
0099 }
0100 
0101 static int mcp3911_read_raw(struct iio_dev *indio_dev,
0102                 struct iio_chan_spec const *channel, int *val,
0103                 int *val2, long mask)
0104 {
0105     struct mcp3911 *adc = iio_priv(indio_dev);
0106     int ret = -EINVAL;
0107 
0108     mutex_lock(&adc->lock);
0109     switch (mask) {
0110     case IIO_CHAN_INFO_RAW:
0111         ret = mcp3911_read(adc,
0112                    MCP3911_CHANNEL(channel->channel), val, 3);
0113         if (ret)
0114             goto out;
0115 
0116         *val = sign_extend32(*val, 23);
0117 
0118         ret = IIO_VAL_INT;
0119         break;
0120 
0121     case IIO_CHAN_INFO_OFFSET:
0122         ret = mcp3911_read(adc,
0123                    MCP3911_OFFCAL(channel->channel), val, 3);
0124         if (ret)
0125             goto out;
0126 
0127         ret = IIO_VAL_INT;
0128         break;
0129 
0130     case IIO_CHAN_INFO_SCALE:
0131         if (adc->vref) {
0132             ret = regulator_get_voltage(adc->vref);
0133             if (ret < 0) {
0134                 dev_err(indio_dev->dev.parent,
0135                     "failed to get vref voltage: %d\n",
0136                        ret);
0137                 goto out;
0138             }
0139 
0140             *val = ret / 1000;
0141         } else {
0142             *val = MCP3911_INT_VREF_MV;
0143         }
0144 
0145         /*
0146          * For 24bit Conversion
0147          * Raw = ((Voltage)/(Vref) * 2^23 * Gain * 1.5
0148          * Voltage = Raw * (Vref)/(2^23 * Gain * 1.5)
0149          */
0150 
0151         /* val2 = (2^23 * 1.5) */
0152         *val2 = 12582912;
0153         ret = IIO_VAL_FRACTIONAL;
0154         break;
0155     }
0156 
0157 out:
0158     mutex_unlock(&adc->lock);
0159     return ret;
0160 }
0161 
0162 static int mcp3911_write_raw(struct iio_dev *indio_dev,
0163                 struct iio_chan_spec const *channel, int val,
0164                 int val2, long mask)
0165 {
0166     struct mcp3911 *adc = iio_priv(indio_dev);
0167     int ret = -EINVAL;
0168 
0169     mutex_lock(&adc->lock);
0170     switch (mask) {
0171     case IIO_CHAN_INFO_OFFSET:
0172         if (val2 != 0) {
0173             ret = -EINVAL;
0174             goto out;
0175         }
0176 
0177         /* Write offset */
0178         ret = mcp3911_write(adc, MCP3911_OFFCAL(channel->channel), val,
0179                     3);
0180         if (ret)
0181             goto out;
0182 
0183         /* Enable offset*/
0184         ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM,
0185                 MCP3911_STATUSCOM_EN_OFFCAL,
0186                 MCP3911_STATUSCOM_EN_OFFCAL, 2);
0187         break;
0188     }
0189 
0190 out:
0191     mutex_unlock(&adc->lock);
0192     return ret;
0193 }
0194 
0195 #define MCP3911_CHAN(idx) {                 \
0196         .type = IIO_VOLTAGE,                \
0197         .indexed = 1,                   \
0198         .channel = idx,                 \
0199         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |  \
0200             BIT(IIO_CHAN_INFO_OFFSET) |     \
0201             BIT(IIO_CHAN_INFO_SCALE),       \
0202 }
0203 
0204 static const struct iio_chan_spec mcp3911_channels[] = {
0205     MCP3911_CHAN(0),
0206     MCP3911_CHAN(1),
0207 };
0208 
0209 static const struct iio_info mcp3911_info = {
0210     .read_raw = mcp3911_read_raw,
0211     .write_raw = mcp3911_write_raw,
0212 };
0213 
0214 static int mcp3911_config(struct mcp3911 *adc)
0215 {
0216     struct device *dev = &adc->spi->dev;
0217     u32 configreg;
0218     int ret;
0219 
0220     ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr);
0221 
0222     /*
0223      * Fallback to "device-addr" due to historical mismatch between
0224      * dt-bindings and implementation
0225      */
0226     if (ret)
0227         device_property_read_u32(dev, "device-addr", &adc->dev_addr);
0228     if (adc->dev_addr > 3) {
0229         dev_err(&adc->spi->dev,
0230             "invalid device address (%i). Must be in range 0-3.\n",
0231             adc->dev_addr);
0232         return -EINVAL;
0233     }
0234     dev_dbg(&adc->spi->dev, "use device address %i\n", adc->dev_addr);
0235 
0236     ret = mcp3911_read(adc, MCP3911_REG_CONFIG, &configreg, 2);
0237     if (ret)
0238         return ret;
0239 
0240     if (adc->vref) {
0241         dev_dbg(&adc->spi->dev, "use external voltage reference\n");
0242         configreg |= MCP3911_CONFIG_VREFEXT;
0243     } else {
0244         dev_dbg(&adc->spi->dev,
0245             "use internal voltage reference (1.2V)\n");
0246         configreg &= ~MCP3911_CONFIG_VREFEXT;
0247     }
0248 
0249     if (adc->clki) {
0250         dev_dbg(&adc->spi->dev, "use external clock as clocksource\n");
0251         configreg |= MCP3911_CONFIG_CLKEXT;
0252     } else {
0253         dev_dbg(&adc->spi->dev,
0254             "use crystal oscillator as clocksource\n");
0255         configreg &= ~MCP3911_CONFIG_CLKEXT;
0256     }
0257 
0258     return  mcp3911_write(adc, MCP3911_REG_CONFIG, configreg, 2);
0259 }
0260 
0261 static int mcp3911_probe(struct spi_device *spi)
0262 {
0263     struct iio_dev *indio_dev;
0264     struct mcp3911 *adc;
0265     int ret;
0266 
0267     indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
0268     if (!indio_dev)
0269         return -ENOMEM;
0270 
0271     adc = iio_priv(indio_dev);
0272     adc->spi = spi;
0273 
0274     adc->vref = devm_regulator_get_optional(&adc->spi->dev, "vref");
0275     if (IS_ERR(adc->vref)) {
0276         if (PTR_ERR(adc->vref) == -ENODEV) {
0277             adc->vref = NULL;
0278         } else {
0279             dev_err(&adc->spi->dev,
0280                 "failed to get regulator (%ld)\n",
0281                 PTR_ERR(adc->vref));
0282             return PTR_ERR(adc->vref);
0283         }
0284 
0285     } else {
0286         ret = regulator_enable(adc->vref);
0287         if (ret)
0288             return ret;
0289     }
0290 
0291     adc->clki = devm_clk_get(&adc->spi->dev, NULL);
0292     if (IS_ERR(adc->clki)) {
0293         if (PTR_ERR(adc->clki) == -ENOENT) {
0294             adc->clki = NULL;
0295         } else {
0296             dev_err(&adc->spi->dev,
0297                 "failed to get adc clk (%ld)\n",
0298                 PTR_ERR(adc->clki));
0299             ret = PTR_ERR(adc->clki);
0300             goto reg_disable;
0301         }
0302     } else {
0303         ret = clk_prepare_enable(adc->clki);
0304         if (ret < 0) {
0305             dev_err(&adc->spi->dev,
0306                 "Failed to enable clki: %d\n", ret);
0307             goto reg_disable;
0308         }
0309     }
0310 
0311     ret = mcp3911_config(adc);
0312     if (ret)
0313         goto clk_disable;
0314 
0315     indio_dev->name = spi_get_device_id(spi)->name;
0316     indio_dev->modes = INDIO_DIRECT_MODE;
0317     indio_dev->info = &mcp3911_info;
0318     spi_set_drvdata(spi, indio_dev);
0319 
0320     indio_dev->channels = mcp3911_channels;
0321     indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
0322 
0323     mutex_init(&adc->lock);
0324 
0325     ret = iio_device_register(indio_dev);
0326     if (ret)
0327         goto clk_disable;
0328 
0329     return ret;
0330 
0331 clk_disable:
0332     clk_disable_unprepare(adc->clki);
0333 reg_disable:
0334     if (adc->vref)
0335         regulator_disable(adc->vref);
0336 
0337     return ret;
0338 }
0339 
0340 static void mcp3911_remove(struct spi_device *spi)
0341 {
0342     struct iio_dev *indio_dev = spi_get_drvdata(spi);
0343     struct mcp3911 *adc = iio_priv(indio_dev);
0344 
0345     iio_device_unregister(indio_dev);
0346 
0347     clk_disable_unprepare(adc->clki);
0348     if (adc->vref)
0349         regulator_disable(adc->vref);
0350 }
0351 
0352 static const struct of_device_id mcp3911_dt_ids[] = {
0353     { .compatible = "microchip,mcp3911" },
0354     { }
0355 };
0356 MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
0357 
0358 static const struct spi_device_id mcp3911_id[] = {
0359     { "mcp3911", 0 },
0360     { }
0361 };
0362 MODULE_DEVICE_TABLE(spi, mcp3911_id);
0363 
0364 static struct spi_driver mcp3911_driver = {
0365     .driver = {
0366         .name = "mcp3911",
0367         .of_match_table = mcp3911_dt_ids,
0368     },
0369     .probe = mcp3911_probe,
0370     .remove = mcp3911_remove,
0371     .id_table = mcp3911_id,
0372 };
0373 module_spi_driver(mcp3911_driver);
0374 
0375 MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
0376 MODULE_AUTHOR("Kent Gustavsson <kent@minoris.se>");
0377 MODULE_DESCRIPTION("Microchip Technology MCP3911");
0378 MODULE_LICENSE("GPL v2");