Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * MEN 16z188 Analog to Digial Converter
0004  *
0005  * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)
0006  * Author: Johannes Thumshirn <johannes.thumshirn@men.de>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/mcb.h>
0012 #include <linux/io.h>
0013 #include <linux/iio/iio.h>
0014 
0015 #define Z188_ADC_MAX_CHAN   8
0016 #define Z188_ADC_GAIN       0x0700000
0017 #define Z188_MODE_VOLTAGE   BIT(27)
0018 #define Z188_CFG_AUTO       0x1
0019 #define Z188_CTRL_REG       0x40
0020 
0021 #define ADC_DATA(x) (((x) >> 2) & 0x7ffffc)
0022 #define ADC_OVR(x) ((x) & 0x1)
0023 
0024 struct z188_adc {
0025     struct resource *mem;
0026     void __iomem *base;
0027 };
0028 
0029 #define Z188_ADC_CHANNEL(idx) {                 \
0030         .type = IIO_VOLTAGE,                \
0031         .indexed = 1,                   \
0032         .channel = (idx),               \
0033         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
0034 }
0035 
0036 static const struct iio_chan_spec z188_adc_iio_channels[] = {
0037     Z188_ADC_CHANNEL(0),
0038     Z188_ADC_CHANNEL(1),
0039     Z188_ADC_CHANNEL(2),
0040     Z188_ADC_CHANNEL(3),
0041     Z188_ADC_CHANNEL(4),
0042     Z188_ADC_CHANNEL(5),
0043     Z188_ADC_CHANNEL(6),
0044     Z188_ADC_CHANNEL(7),
0045 };
0046 
0047 static int z188_iio_read_raw(struct iio_dev *iio_dev,
0048             struct iio_chan_spec const *chan,
0049             int *val,
0050             int *val2,
0051             long info)
0052 {
0053     struct z188_adc *adc = iio_priv(iio_dev);
0054     int ret;
0055     u16 tmp;
0056 
0057     switch (info) {
0058     case IIO_CHAN_INFO_RAW:
0059         tmp = readw(adc->base + chan->channel * 4);
0060 
0061         if (ADC_OVR(tmp)) {
0062             dev_info(&iio_dev->dev,
0063                 "Oversampling error on ADC channel %d\n",
0064                 chan->channel);
0065             return -EIO;
0066         }
0067         *val = ADC_DATA(tmp);
0068         ret = IIO_VAL_INT;
0069         break;
0070     default:
0071         ret = -EINVAL;
0072         break;
0073     }
0074 
0075     return ret;
0076 }
0077 
0078 static const struct iio_info z188_adc_info = {
0079     .read_raw = &z188_iio_read_raw,
0080 };
0081 
0082 static void men_z188_config_channels(void __iomem *addr)
0083 {
0084     int i;
0085     u32 cfg;
0086     u32 ctl;
0087 
0088     ctl = readl(addr + Z188_CTRL_REG);
0089     ctl |= Z188_CFG_AUTO;
0090     writel(ctl, addr + Z188_CTRL_REG);
0091 
0092     for (i = 0; i < Z188_ADC_MAX_CHAN; i++) {
0093         cfg = readl(addr + i);
0094         cfg &= ~Z188_ADC_GAIN;
0095         cfg |= Z188_MODE_VOLTAGE;
0096         writel(cfg, addr + i);
0097     }
0098 }
0099 
0100 static int men_z188_probe(struct mcb_device *dev,
0101             const struct mcb_device_id *id)
0102 {
0103     struct z188_adc *adc;
0104     struct iio_dev *indio_dev;
0105     struct resource *mem;
0106     int ret;
0107 
0108     indio_dev = devm_iio_device_alloc(&dev->dev, sizeof(struct z188_adc));
0109     if (!indio_dev)
0110         return -ENOMEM;
0111 
0112     adc = iio_priv(indio_dev);
0113     indio_dev->name = "z188-adc";
0114     indio_dev->info = &z188_adc_info;
0115     indio_dev->modes = INDIO_DIRECT_MODE;
0116     indio_dev->channels = z188_adc_iio_channels;
0117     indio_dev->num_channels = ARRAY_SIZE(z188_adc_iio_channels);
0118 
0119     mem = mcb_request_mem(dev, "z188-adc");
0120     if (IS_ERR(mem))
0121         return PTR_ERR(mem);
0122 
0123     adc->base = ioremap(mem->start, resource_size(mem));
0124     if (adc->base == NULL)
0125         goto err;
0126 
0127     men_z188_config_channels(adc->base);
0128 
0129     adc->mem = mem;
0130     mcb_set_drvdata(dev, indio_dev);
0131 
0132     ret = iio_device_register(indio_dev);
0133     if (ret)
0134         goto err_unmap;
0135 
0136     return 0;
0137 
0138 err_unmap:
0139     iounmap(adc->base);
0140 err:
0141     mcb_release_mem(mem);
0142     return -ENXIO;
0143 }
0144 
0145 static void men_z188_remove(struct mcb_device *dev)
0146 {
0147     struct iio_dev *indio_dev  = mcb_get_drvdata(dev);
0148     struct z188_adc *adc = iio_priv(indio_dev);
0149 
0150     iio_device_unregister(indio_dev);
0151     iounmap(adc->base);
0152     mcb_release_mem(adc->mem);
0153 }
0154 
0155 static const struct mcb_device_id men_z188_ids[] = {
0156     { .device = 0xbc },
0157     { }
0158 };
0159 MODULE_DEVICE_TABLE(mcb, men_z188_ids);
0160 
0161 static struct mcb_driver men_z188_driver = {
0162     .driver = {
0163         .name = "z188-adc",
0164         .owner = THIS_MODULE,
0165     },
0166     .probe = men_z188_probe,
0167     .remove = men_z188_remove,
0168     .id_table = men_z188_ids,
0169 };
0170 module_mcb_driver(men_z188_driver);
0171 
0172 MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
0173 MODULE_LICENSE("GPL");
0174 MODULE_DESCRIPTION("IIO ADC driver for MEN 16z188 ADC Core");
0175 MODULE_ALIAS("mcb:16z188");
0176 MODULE_IMPORT_NS(MCB);