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