Merge 4.4-rc2 into staging-next
[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
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
26static const char driver_name[] = "pio2_gpio";
27
28static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip)
29{
30 return container_of(chip, struct pio2_card, gc);
31}
32
33static 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, &reg, 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
70static 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, &reg, 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 */
102static 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 */
121static 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 */
143int 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 188int 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 219void 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
This page took 0.413864 seconds and 5 git commands to generate.