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