brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · 198c7e6 Raw
176 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MEN 16z188 Analog to Digial Converter4 *5 * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)6 * Author: Johannes Thumshirn <johannes.thumshirn@men.de>7 */8 9#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/mcb.h>12#include <linux/io.h>13#include <linux/iio/iio.h>14 15#define Z188_ADC_MAX_CHAN	816#define Z188_ADC_GAIN		0x070000017#define Z188_MODE_VOLTAGE	BIT(27)18#define Z188_CFG_AUTO		0x119#define Z188_CTRL_REG		0x4020 21#define ADC_DATA(x) (((x) >> 2) & 0x7ffffc)22#define ADC_OVR(x) ((x) & 0x1)23 24struct z188_adc {25	struct resource *mem;26	void __iomem *base;27};28 29#define Z188_ADC_CHANNEL(idx) {					\30		.type = IIO_VOLTAGE,				\31		.indexed = 1,					\32		.channel = (idx),				\33		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \34}35 36static const struct iio_chan_spec z188_adc_iio_channels[] = {37	Z188_ADC_CHANNEL(0),38	Z188_ADC_CHANNEL(1),39	Z188_ADC_CHANNEL(2),40	Z188_ADC_CHANNEL(3),41	Z188_ADC_CHANNEL(4),42	Z188_ADC_CHANNEL(5),43	Z188_ADC_CHANNEL(6),44	Z188_ADC_CHANNEL(7),45};46 47static int z188_iio_read_raw(struct iio_dev *iio_dev,48			struct iio_chan_spec const *chan,49			int *val,50			int *val2,51			long info)52{53	struct z188_adc *adc = iio_priv(iio_dev);54	int ret;55	u16 tmp;56 57	switch (info) {58	case IIO_CHAN_INFO_RAW:59		tmp = readw(adc->base + chan->channel * 4);60 61		if (ADC_OVR(tmp)) {62			dev_info(&iio_dev->dev,63				"Oversampling error on ADC channel %d\n",64				chan->channel);65			return -EIO;66		}67		*val = ADC_DATA(tmp);68		ret = IIO_VAL_INT;69		break;70	default:71		ret = -EINVAL;72		break;73	}74 75	return ret;76}77 78static const struct iio_info z188_adc_info = {79	.read_raw = &z188_iio_read_raw,80};81 82static void men_z188_config_channels(void __iomem *addr)83{84	int i;85	u32 cfg;86	u32 ctl;87 88	ctl = readl(addr + Z188_CTRL_REG);89	ctl |= Z188_CFG_AUTO;90	writel(ctl, addr + Z188_CTRL_REG);91 92	for (i = 0; i < Z188_ADC_MAX_CHAN; i++) {93		cfg = readl(addr + i);94		cfg &= ~Z188_ADC_GAIN;95		cfg |= Z188_MODE_VOLTAGE;96		writel(cfg, addr + i);97	}98}99 100static int men_z188_probe(struct mcb_device *dev,101			const struct mcb_device_id *id)102{103	struct z188_adc *adc;104	struct iio_dev *indio_dev;105	struct resource *mem;106	int ret;107 108	indio_dev = devm_iio_device_alloc(&dev->dev, sizeof(struct z188_adc));109	if (!indio_dev)110		return -ENOMEM;111 112	adc = iio_priv(indio_dev);113	indio_dev->name = "z188-adc";114	indio_dev->info = &z188_adc_info;115	indio_dev->modes = INDIO_DIRECT_MODE;116	indio_dev->channels = z188_adc_iio_channels;117	indio_dev->num_channels = ARRAY_SIZE(z188_adc_iio_channels);118 119	mem = mcb_request_mem(dev, "z188-adc");120	if (IS_ERR(mem))121		return PTR_ERR(mem);122 123	adc->base = ioremap(mem->start, resource_size(mem));124	if (adc->base == NULL)125		goto err;126 127	men_z188_config_channels(adc->base);128 129	adc->mem = mem;130	mcb_set_drvdata(dev, indio_dev);131 132	ret = iio_device_register(indio_dev);133	if (ret)134		goto err_unmap;135 136	return 0;137 138err_unmap:139	iounmap(adc->base);140err:141	mcb_release_mem(mem);142	return -ENXIO;143}144 145static void men_z188_remove(struct mcb_device *dev)146{147	struct iio_dev *indio_dev  = mcb_get_drvdata(dev);148	struct z188_adc *adc = iio_priv(indio_dev);149 150	iio_device_unregister(indio_dev);151	iounmap(adc->base);152	mcb_release_mem(adc->mem);153}154 155static const struct mcb_device_id men_z188_ids[] = {156	{ .device = 0xbc },157	{ }158};159MODULE_DEVICE_TABLE(mcb, men_z188_ids);160 161static struct mcb_driver men_z188_driver = {162	.driver = {163		.name = "z188-adc",164	},165	.probe = men_z188_probe,166	.remove = men_z188_remove,167	.id_table = men_z188_ids,168};169module_mcb_driver(men_z188_driver);170 171MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");172MODULE_LICENSE("GPL");173MODULE_DESCRIPTION("IIO ADC driver for MEN 16z188 ADC Core");174MODULE_ALIAS("mcb:16z188");175MODULE_IMPORT_NS(MCB);176