Staging: iio/adc: strict_strtoul was used with a long type variable
[deliverable/linux.git] / drivers / staging / vme / devices / vme_pio2_gpio.c
CommitLineData
9dc367bc
MW
1/*
2 * GE PIO2 GPIO Driver
3 *
4 * Author: Martyn Welch <martyn.welch@ge.com>
5 * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
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
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/version.h>
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/ctype.h>
22#include <linux/gpio.h>
23#include <linux/slab.h>
24
25#include "../vme.h"
26#include "vme_pio2.h"
27
28static const char driver_name[] = "pio2_gpio";
29
30static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip)
31{
32 return container_of(chip, struct pio2_card, gc);
33}
34
35static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
36{
37 u8 reg;
38 int retval;
39 struct pio2_card *card = gpio_to_pio2_card(chip);
40
41 if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
42 (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
43
44 dev_err(&card->vdev->dev, "Channel not available as input\n");
45 return 0;
46 }
47
48 retval = vme_master_read(card->window, &reg, 1,
49 PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
50 if (retval < 0) {
51 dev_err(&card->vdev->dev, "Unable to read from GPIO\n");
52 return 0;
53 }
54
55 /*
56 * Remember, input on channels configured as both input and output
57 * are inverted!
58 */
59 if (reg & PIO2_CHANNEL_BIT[offset]) {
60 if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
61 return 0;
62 else
63 return 1;
64 } else {
65 if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
66 return 1;
67 else
68 return 0;
69 }
70}
71
72static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset,
73 int value)
74{
75 u8 reg;
76 int retval;
77 struct pio2_card *card = gpio_to_pio2_card(chip);
78
79 if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
80 (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
81
82 dev_err(&card->vdev->dev, "Channel not availabe as output\n");
83 return;
84 }
85
86 if (value)
87 reg = card->bank[PIO2_CHANNEL_BANK[offset]].value |
88 PIO2_CHANNEL_BIT[offset];
89 else
90 reg = card->bank[PIO2_CHANNEL_BANK[offset]].value &
91 ~PIO2_CHANNEL_BIT[offset];
92
93 retval = vme_master_write(card->window, &reg, 1,
94 PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
95 if (retval < 0) {
96 dev_err(&card->vdev->dev, "Unable to write to GPIO\n");
97 return;
98 }
99
100 card->bank[PIO2_CHANNEL_BANK[offset]].value = reg;
101}
102
103/* Directionality configured at board build - send appropriate response */
104static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
105{
106 int data;
107 struct pio2_card *card = gpio_to_pio2_card(chip);
108
109 if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
110 (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
111 dev_err(&card->vdev->dev,
112 "Channel directionality not configurable at runtine\n");
113
114 data = -EINVAL;
115 } else {
116 data = 0;
117 }
118
119 return data;
120}
121
122/* Directionality configured at board build - send appropriate response */
123static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
124{
125 int data;
126 struct pio2_card *card = gpio_to_pio2_card(chip);
127
128 if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
129 (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
130 dev_err(&card->vdev->dev,
131 "Channel directionality not configurable at runtine\n");
132
133 data = -EINVAL;
134 } else {
135 data = 0;
136 }
137
138 return data;
139}
140
141/*
142 * We return whether this has been successful - this is used in the probe to
143 * ensure we have a valid card.
144 */
145int pio2_gpio_reset(struct pio2_card *card)
146{
147 int retval = 0;
148 int i, j;
149
150 u8 data = 0;
151
152 /* Zero output registers */
153 for (i = 0; i < 4; i++) {
154 retval = vme_master_write(card->window, &data, 1,
155 PIO2_REGS_DATA[i]);
156 if (retval < 0)
157 return retval;
158 card->bank[i].value = 0;
159 }
160
161 /* Set input interrupt masks */
162 for (i = 0; i < 8; i++) {
163 retval = vme_master_write(card->window, &data, 1,
164 PIO2_REGS_INT_MASK[i]);
165 if (retval < 0)
166 return retval;
167
168 for (j = 0; j < 8; j++)
169 card->bank[i].irq[j] = NONE;
170 }
171
172 /* Ensure all I/O interrupts are cleared */
173 for (i = 0; i < 4; i++) {
174 do {
175 retval = vme_master_read(card->window, &data, 1,
176 PIO2_REGS_INT_STAT[i]);
177 if (retval < 0)
178 return retval;
179 } while (data != 0);
180 }
181
182 return 0;
183}
184
185int __init pio2_gpio_init(struct pio2_card *card)
186{
187 int retval = 0;
188 char *label;
189
190 label = kmalloc(PIO2_NUM_CHANNELS, GFP_KERNEL);
191 if (label == NULL) {
192 dev_err(&card->vdev->dev, "Unable to allocate GPIO label\n");
193 return -ENOMEM;
194 }
195
196 sprintf(label, "%s@%s", driver_name, dev_name(&card->vdev->dev));
197 card->gc.label = label;
198
199 card->gc.ngpio = PIO2_NUM_CHANNELS;
200 /* Dynamic allocation of base */
201 card->gc.base = -1;
202 /* Setup pointers to chip functions */
203 card->gc.direction_input = pio2_gpio_dir_in;
204 card->gc.direction_output = pio2_gpio_dir_out;
205 card->gc.get = pio2_gpio_get;
206 card->gc.set = pio2_gpio_set;
207
208 /* This function adds a memory mapped GPIO chip */
209 retval = gpiochip_add(&(card->gc));
210 if (retval) {
211 dev_err(&card->vdev->dev, "Unable to register GPIO\n");
212 kfree(card->gc.label);
213 }
214
215 return retval;
216};
217
218void __exit pio2_gpio_exit(struct pio2_card *card)
219{
220 const char *label = card->gc.label;
221
222 if (gpiochip_remove(&(card->gc)))
223 dev_err(&card->vdev->dev, "Failed to remove GPIO");
224
225 kfree(label);
226}
227
This page took 0.051065 seconds and 5 git commands to generate.