Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932107AbaBRPeq (ORCPT ); Tue, 18 Feb 2014 10:34:46 -0500 Received: from mail1.bemta14.messagelabs.com ([193.109.254.110]:50097 "EHLO mail1.bemta14.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756024AbaBRPen (ORCPT ); Tue, 18 Feb 2014 10:34:43 -0500 X-Env-Sender: Johannes.Thumshirn@men.de X-Msg-Ref: server-3.tower-194.messagelabs.com!1392737675!10939541!1 X-Originating-IP: [80.255.6.145] X-StarScan-Received: X-StarScan-Version: 6.9.16; banners=-,-,- X-VirusChecked: Checked X-PGP-Universal: processed; by keys.men.de on Tue, 18 Feb 2014 16:34:36 +0100 From: Johannes Thumshirn To: Greg Kroah-Hartman , Jonathan Cameron CC: , , Johannes Thumshirn Subject: [PATCH 3/3] iio: adc: Add MEN 16z188 ADC driver Date: Tue, 18 Feb 2014 16:34:14 +0100 Message-ID: <1392737654-22682-4-git-send-email-johannes.thumshirn@men.de> X-Mailer: git-send-email 1.8.5.4 In-Reply-To: <1392737654-22682-1-git-send-email-johannes.thumshirn@men.de> References: <1392737654-22682-1-git-send-email-johannes.thumshirn@men.de> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [192.1.1.31] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for MEN 16z188 ADC IP Core on MCB FPGAs. Signed-off-by: Johannes Thumshirn --- drivers/iio/adc/Kconfig | 10 +++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/men_z188_adc.c | 172 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 drivers/iio/adc/men_z188_adc.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 2209f28..5209437 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -204,4 +204,14 @@ config VIPERBOARD_ADC Say yes here to access the ADC part of the Nano River Technologies Viperboard. +config MEN_Z188_ADC + tristate "MEN 16z188 ADC IP Core support" + depends on MCB + help + Say yes here to access support the MEN 16z188 ADC IP-Core on a MCB + carrier. + + This driver can also be built as a module. If so, the module will be + called men_z188_adc. + endmenu diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ba9a10a..1584391 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o +obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c new file mode 100644 index 0000000..8bc66cf --- /dev/null +++ b/drivers/iio/adc/men_z188_adc.c @@ -0,0 +1,172 @@ +/* + * MEN 16z188 Analoge to Digial Converter + * + * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de) + * Author: Johannes Thumshirn + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; version 2 of the License. + */ +#include +#include +#include +#include + +#define Z188_ADC_MAX_CHAN 8 +#define Z188_ADC_GAIN 0x0700000 +#define Z188_MODE_VOLTAGE BIT(27) +#define Z188_CFG_AUTO 0x1 +#define Z188_CTRL_REG 0x40 + +#define ADC_DATA(x) (((x) >> 2) & 0x7ffffc) +#define ADC_OVR(x) ((x) & 0x1) + +struct z188_adc { + struct resource *mem; + void __iomem *base; +}; + +#define Z188_ADC_CHANNEL(idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (idx), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +} + +static struct iio_chan_spec z188_adc_iio_channels[] = { + Z188_ADC_CHANNEL(0), + Z188_ADC_CHANNEL(1), + Z188_ADC_CHANNEL(2), + Z188_ADC_CHANNEL(3), + Z188_ADC_CHANNEL(4), + Z188_ADC_CHANNEL(5), + Z188_ADC_CHANNEL(6), + Z188_ADC_CHANNEL(7), +}; + +static int z188_iio_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long info) +{ + struct z188_adc *adc = iio_priv(iio_dev); + int ret = 0; + u16 tmp = 0; + + + switch (info) { + case IIO_CHAN_INFO_RAW: + tmp = readw(adc->base + chan->channel * 4); + + if (ADC_OVR(tmp)) { + dev_info(&iio_dev->dev, + "Oversampling error on ADC channel %d\n", + chan->channel); + return -EIO; + } + *val = ADC_DATA(tmp); + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static struct iio_info z188_adc_info = { + .read_raw = &z188_iio_read_raw, + .driver_module = THIS_MODULE, +}; + +static void men_z188_config_channels(void __iomem *addr) +{ + int i; + u32 cfg; + u32 ctl; + + ctl = readl(addr + Z188_CTRL_REG); + ctl |= Z188_CFG_AUTO; + writel(ctl, addr + Z188_CTRL_REG); + + for (i = 0; i < Z188_ADC_MAX_CHAN; i++) { + cfg = readl(addr + i); + cfg &= ~Z188_ADC_GAIN; + cfg |= Z188_MODE_VOLTAGE; + writel(cfg, addr + i); + } +} + +static int men_z188_probe(struct mcb_device *dev, + const struct mcb_device_id *id) +{ + struct z188_adc *adc; + struct iio_dev *indio_dev; + struct resource *mem; + + indio_dev = devm_iio_device_alloc(&dev->dev, sizeof(struct z188_adc)); + if (!indio_dev) + return -ENOMEM; + + adc = iio_priv(indio_dev); + indio_dev->name = "z188-adc"; + indio_dev->dev.parent = &dev->dev; + indio_dev->info = &z188_adc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = z188_adc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(z188_adc_iio_channels); + + mem = mcb_request_mem(dev, "z188-adc"); + if (!mem) + return -ENOMEM; + + adc->base = ioremap(mem->start, resource_size(mem)); + if (adc->base == NULL) + goto err; + + men_z188_config_channels(adc->base); + + adc->mem = mem; + mcb_set_drvdata(dev, indio_dev); + + return devm_iio_device_register(&dev->dev, indio_dev); + +err: + mcb_release_mem(mem); + return -ENXIO; +} + +static void men_z188_remove(struct mcb_device *dev) +{ + struct iio_dev *indio_dev = mcb_get_drvdata(dev); + struct z188_adc *adc = iio_priv(indio_dev); + + iounmap(adc->base); + mcb_release_mem(adc->mem); + + mcb_set_drvdata(dev, NULL); +} + +static struct mcb_device_id men_z188_ids[] = { + { .device = 0xbc }, +}; +MODULE_DEVICE_TABLE(mcb, men_z188_ids); + +static struct mcb_driver men_z188_driver = { + .driver = { + .name = "z188-adc", + .owner = THIS_MODULE, + }, + .probe = men_z188_probe, + .remove = men_z188_remove, + .id_table = men_z188_ids, +}; +module_mcb_driver(men_z188_driver); + +MODULE_AUTHOR("Johannes Thumshirn "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IIO ADC driver for MEN 16z188 ADC Core"); +MODULE_ALIAS("mcb:16z188"); -- 1.8.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/