diff options
author | Johannes Thumshirn <johannes.thumshirn@men.de> | 2014-02-26 11:29:07 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-28 18:47:57 -0500 |
commit | 74aeac4da66fbfa246edbfc849002eac9b5af9ca (patch) | |
tree | eeca7feedef21ca53614702aa4f9a3c281e0cc1a /drivers/iio | |
parent | b71bb8639891827051af88d8dfb17ca608b6ae88 (diff) |
iio: adc: Add MEN 16z188 ADC driver
Add support for MEN 16z188 ADC IP Core on MCB FPGAs.
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@men.de>
Acked-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/adc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/adc/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/adc/men_z188_adc.c | 171 |
3 files changed, 182 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 2209f28441e9..5c63f0918d12 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig | |||
@@ -155,6 +155,16 @@ config MCP3422 | |||
155 | This driver can also be built as a module. If so, the module will be | 155 | This driver can also be built as a module. If so, the module will be |
156 | called mcp3422. | 156 | called mcp3422. |
157 | 157 | ||
158 | config MEN_Z188_ADC | ||
159 | tristate "MEN 16z188 ADC IP Core support" | ||
160 | depends on MCB | ||
161 | help | ||
162 | Say yes here to enable support for the MEN 16z188 ADC IP-Core on a MCB | ||
163 | carrier. | ||
164 | |||
165 | This driver can also be built as a module. If so, the module will be | ||
166 | called men_z188_adc. | ||
167 | |||
158 | config NAU7802 | 168 | config NAU7802 |
159 | tristate "Nuvoton NAU7802 ADC driver" | 169 | tristate "Nuvoton NAU7802 ADC driver" |
160 | depends on I2C | 170 | depends on I2C |
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ba9a10a24cd0..85a4a045f1f0 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o | |||
17 | obj-$(CONFIG_MAX1363) += max1363.o | 17 | obj-$(CONFIG_MAX1363) += max1363.o |
18 | obj-$(CONFIG_MCP320X) += mcp320x.o | 18 | obj-$(CONFIG_MCP320X) += mcp320x.o |
19 | obj-$(CONFIG_MCP3422) += mcp3422.o | 19 | obj-$(CONFIG_MCP3422) += mcp3422.o |
20 | obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o | ||
20 | obj-$(CONFIG_NAU7802) += nau7802.o | 21 | obj-$(CONFIG_NAU7802) += nau7802.o |
21 | obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o | 22 | obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o |
22 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o | 23 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_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 000000000000..70365034caa9 --- /dev/null +++ b/drivers/iio/adc/men_z188_adc.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * MEN 16z188 Analog to Digial Converter | ||
3 | * | ||
4 | * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de) | ||
5 | * Author: Johannes Thumshirn <johannes.thumshirn@men.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation; version 2 of the License. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/mcb.h> | ||
15 | #include <linux/iio/iio.h> | ||
16 | |||
17 | #define Z188_ADC_MAX_CHAN 8 | ||
18 | #define Z188_ADC_GAIN 0x0700000 | ||
19 | #define Z188_MODE_VOLTAGE BIT(27) | ||
20 | #define Z188_CFG_AUTO 0x1 | ||
21 | #define Z188_CTRL_REG 0x40 | ||
22 | |||
23 | #define ADC_DATA(x) (((x) >> 2) & 0x7ffffc) | ||
24 | #define ADC_OVR(x) ((x) & 0x1) | ||
25 | |||
26 | struct z188_adc { | ||
27 | struct resource *mem; | ||
28 | void __iomem *base; | ||
29 | }; | ||
30 | |||
31 | #define Z188_ADC_CHANNEL(idx) { \ | ||
32 | .type = IIO_VOLTAGE, \ | ||
33 | .indexed = 1, \ | ||
34 | .channel = (idx), \ | ||
35 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
36 | } | ||
37 | |||
38 | static const struct iio_chan_spec z188_adc_iio_channels[] = { | ||
39 | Z188_ADC_CHANNEL(0), | ||
40 | Z188_ADC_CHANNEL(1), | ||
41 | Z188_ADC_CHANNEL(2), | ||
42 | Z188_ADC_CHANNEL(3), | ||
43 | Z188_ADC_CHANNEL(4), | ||
44 | Z188_ADC_CHANNEL(5), | ||
45 | Z188_ADC_CHANNEL(6), | ||
46 | Z188_ADC_CHANNEL(7), | ||
47 | }; | ||
48 | |||
49 | static int z188_iio_read_raw(struct iio_dev *iio_dev, | ||
50 | struct iio_chan_spec const *chan, | ||
51 | int *val, | ||
52 | int *val2, | ||
53 | long info) | ||
54 | { | ||
55 | struct z188_adc *adc = iio_priv(iio_dev); | ||
56 | int ret; | ||
57 | u16 tmp; | ||
58 | |||
59 | switch (info) { | ||
60 | case IIO_CHAN_INFO_RAW: | ||
61 | tmp = readw(adc->base + chan->channel * 4); | ||
62 | |||
63 | if (ADC_OVR(tmp)) { | ||
64 | dev_info(&iio_dev->dev, | ||
65 | "Oversampling error on ADC channel %d\n", | ||
66 | chan->channel); | ||
67 | return -EIO; | ||
68 | } | ||
69 | *val = ADC_DATA(tmp); | ||
70 | ret = IIO_VAL_INT; | ||
71 | break; | ||
72 | default: | ||
73 | ret = -EINVAL; | ||
74 | break; | ||
75 | } | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | static struct iio_info z188_adc_info = { | ||
81 | .read_raw = &z188_iio_read_raw, | ||
82 | .driver_module = THIS_MODULE, | ||
83 | }; | ||
84 | |||
85 | static void men_z188_config_channels(void __iomem *addr) | ||
86 | { | ||
87 | int i; | ||
88 | u32 cfg; | ||
89 | u32 ctl; | ||
90 | |||
91 | ctl = readl(addr + Z188_CTRL_REG); | ||
92 | ctl |= Z188_CFG_AUTO; | ||
93 | writel(ctl, addr + Z188_CTRL_REG); | ||
94 | |||
95 | for (i = 0; i < Z188_ADC_MAX_CHAN; i++) { | ||
96 | cfg = readl(addr + i); | ||
97 | cfg &= ~Z188_ADC_GAIN; | ||
98 | cfg |= Z188_MODE_VOLTAGE; | ||
99 | writel(cfg, addr + i); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static int men_z188_probe(struct mcb_device *dev, | ||
104 | const struct mcb_device_id *id) | ||
105 | { | ||
106 | struct z188_adc *adc; | ||
107 | struct iio_dev *indio_dev; | ||
108 | struct resource *mem; | ||
109 | |||
110 | indio_dev = devm_iio_device_alloc(&dev->dev, sizeof(struct z188_adc)); | ||
111 | if (!indio_dev) | ||
112 | return -ENOMEM; | ||
113 | |||
114 | adc = iio_priv(indio_dev); | ||
115 | indio_dev->name = "z188-adc"; | ||
116 | indio_dev->dev.parent = &dev->dev; | ||
117 | indio_dev->info = &z188_adc_info; | ||
118 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
119 | indio_dev->channels = z188_adc_iio_channels; | ||
120 | indio_dev->num_channels = ARRAY_SIZE(z188_adc_iio_channels); | ||
121 | |||
122 | mem = mcb_request_mem(dev, "z188-adc"); | ||
123 | if (!mem) | ||
124 | return -ENOMEM; | ||
125 | |||
126 | adc->base = ioremap(mem->start, resource_size(mem)); | ||
127 | if (adc->base == NULL) | ||
128 | goto err; | ||
129 | |||
130 | men_z188_config_channels(adc->base); | ||
131 | |||
132 | adc->mem = mem; | ||
133 | mcb_set_drvdata(dev, indio_dev); | ||
134 | |||
135 | return iio_device_register(indio_dev); | ||
136 | |||
137 | err: | ||
138 | mcb_release_mem(mem); | ||
139 | return -ENXIO; | ||
140 | } | ||
141 | |||
142 | static void men_z188_remove(struct mcb_device *dev) | ||
143 | { | ||
144 | struct iio_dev *indio_dev = mcb_get_drvdata(dev); | ||
145 | struct z188_adc *adc = iio_priv(indio_dev); | ||
146 | |||
147 | iio_device_unregister(indio_dev); | ||
148 | iounmap(adc->base); | ||
149 | mcb_release_mem(adc->mem); | ||
150 | } | ||
151 | |||
152 | static const struct mcb_device_id men_z188_ids[] = { | ||
153 | { .device = 0xbc }, | ||
154 | }; | ||
155 | MODULE_DEVICE_TABLE(mcb, men_z188_ids); | ||
156 | |||
157 | static struct mcb_driver men_z188_driver = { | ||
158 | .driver = { | ||
159 | .name = "z188-adc", | ||
160 | .owner = THIS_MODULE, | ||
161 | }, | ||
162 | .probe = men_z188_probe, | ||
163 | .remove = men_z188_remove, | ||
164 | .id_table = men_z188_ids, | ||
165 | }; | ||
166 | module_mcb_driver(men_z188_driver); | ||
167 | |||
168 | MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>"); | ||
169 | MODULE_LICENSE("GPL"); | ||
170 | MODULE_DESCRIPTION("IIO ADC driver for MEN 16z188 ADC Core"); | ||
171 | MODULE_ALIAS("mcb:16z188"); | ||