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