]>
Commit | Line | Data |
---|---|---|
0bcb6069 | 1 | /* |
74600ee0 | 2 | * Xilinx gpio driver for xps/axi_gpio IP. |
0bcb6069 | 3 | * |
74600ee0 | 4 | * Copyright 2008 - 2013 Xilinx, Inc. |
0bcb6069 JL |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * You should have received a copy of the GNU General Public License | |
11 | * along with this program; if not, write to the Free Software | |
12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
13 | */ | |
14 | ||
74600ee0 | 15 | #include <linux/bitops.h> |
0bcb6069 JL |
16 | #include <linux/init.h> |
17 | #include <linux/errno.h> | |
bb207ef1 | 18 | #include <linux/module.h> |
0bcb6069 JL |
19 | #include <linux/of_device.h> |
20 | #include <linux/of_platform.h> | |
21 | #include <linux/of_gpio.h> | |
22 | #include <linux/io.h> | |
23 | #include <linux/gpio.h> | |
5a0e3ad6 | 24 | #include <linux/slab.h> |
0bcb6069 JL |
25 | |
26 | /* Register Offset Definitions */ | |
27 | #define XGPIO_DATA_OFFSET (0x0) /* Data register */ | |
28 | #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ | |
29 | ||
74600ee0 MS |
30 | #define XGPIO_CHANNEL_OFFSET 0x8 |
31 | ||
32 | /* Read/Write access to the GPIO registers */ | |
cc090d61 MS |
33 | #ifdef CONFIG_ARCH_ZYNQ |
34 | # define xgpio_readreg(offset) readl(offset) | |
35 | # define xgpio_writereg(offset, val) writel(val, offset) | |
36 | #else | |
37 | # define xgpio_readreg(offset) __raw_readl(offset) | |
38 | # define xgpio_writereg(offset, val) __raw_writel(val, offset) | |
39 | #endif | |
74600ee0 MS |
40 | |
41 | /** | |
42 | * struct xgpio_instance - Stores information about GPIO device | |
43 | * struct of_mm_gpio_chip mmchip: OF GPIO chip for memory mapped banks | |
44 | * gpio_state: GPIO state shadow register | |
45 | * gpio_dir: GPIO direction shadow register | |
74600ee0 | 46 | * gpio_lock: Lock used for synchronization |
749564ff | 47 | * inited: True if the port has been inited |
74600ee0 | 48 | */ |
0bcb6069 JL |
49 | struct xgpio_instance { |
50 | struct of_mm_gpio_chip mmchip; | |
74600ee0 MS |
51 | u32 gpio_state; |
52 | u32 gpio_dir; | |
74600ee0 | 53 | spinlock_t gpio_lock; |
749564ff RRD |
54 | bool inited; |
55 | }; | |
56 | ||
57 | struct xgpio { | |
58 | struct xgpio_instance port[2]; | |
0bcb6069 JL |
59 | }; |
60 | ||
61 | /** | |
62 | * xgpio_get - Read the specified signal of the GPIO device. | |
63 | * @gc: Pointer to gpio_chip device structure. | |
64 | * @gpio: GPIO signal number. | |
65 | * | |
66 | * This function reads the specified signal of the GPIO device. It returns 0 if | |
67 | * the signal clear, 1 if signal is set or negative value on error. | |
68 | */ | |
69 | static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) | |
70 | { | |
71 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | |
72 | ||
bc2f3dc3 | 73 | return !!(xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET) & BIT(gpio)); |
0bcb6069 JL |
74 | } |
75 | ||
76 | /** | |
77 | * xgpio_set - Write the specified signal of the GPIO device. | |
78 | * @gc: Pointer to gpio_chip device structure. | |
79 | * @gpio: GPIO signal number. | |
80 | * @val: Value to be written to specified signal. | |
81 | * | |
82 | * This function writes the specified value in to the specified signal of the | |
83 | * GPIO device. | |
84 | */ | |
85 | static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | |
86 | { | |
87 | unsigned long flags; | |
88 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | |
89 | struct xgpio_instance *chip = | |
90 | container_of(mm_gc, struct xgpio_instance, mmchip); | |
91 | ||
92 | spin_lock_irqsave(&chip->gpio_lock, flags); | |
93 | ||
94 | /* Write to GPIO signal and set its direction to output */ | |
95 | if (val) | |
9f7f0b2b | 96 | chip->gpio_state |= BIT(gpio); |
0bcb6069 | 97 | else |
9f7f0b2b | 98 | chip->gpio_state &= ~BIT(gpio); |
74600ee0 | 99 | |
bc2f3dc3 | 100 | xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); |
0bcb6069 JL |
101 | |
102 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | |
103 | } | |
104 | ||
105 | /** | |
106 | * xgpio_dir_in - Set the direction of the specified GPIO signal as input. | |
107 | * @gc: Pointer to gpio_chip device structure. | |
108 | * @gpio: GPIO signal number. | |
109 | * | |
110 | * This function sets the direction of specified GPIO signal as input. | |
111 | * It returns 0 if direction of GPIO signals is set as input otherwise it | |
112 | * returns negative error value. | |
113 | */ | |
114 | static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | |
115 | { | |
116 | unsigned long flags; | |
117 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | |
118 | struct xgpio_instance *chip = | |
119 | container_of(mm_gc, struct xgpio_instance, mmchip); | |
120 | ||
121 | spin_lock_irqsave(&chip->gpio_lock, flags); | |
122 | ||
123 | /* Set the GPIO bit in shadow register and set direction as input */ | |
9f7f0b2b | 124 | chip->gpio_dir |= BIT(gpio); |
bc2f3dc3 | 125 | xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); |
0bcb6069 JL |
126 | |
127 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | |
128 | ||
129 | return 0; | |
130 | } | |
131 | ||
132 | /** | |
133 | * xgpio_dir_out - Set the direction of the specified GPIO signal as output. | |
134 | * @gc: Pointer to gpio_chip device structure. | |
135 | * @gpio: GPIO signal number. | |
136 | * @val: Value to be written to specified signal. | |
137 | * | |
138 | * This function sets the direction of specified GPIO signal as output. If all | |
139 | * GPIO signals of GPIO chip is configured as input then it returns | |
140 | * error otherwise it returns 0. | |
141 | */ | |
142 | static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |
143 | { | |
144 | unsigned long flags; | |
145 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | |
146 | struct xgpio_instance *chip = | |
147 | container_of(mm_gc, struct xgpio_instance, mmchip); | |
148 | ||
149 | spin_lock_irqsave(&chip->gpio_lock, flags); | |
150 | ||
151 | /* Write state of GPIO signal */ | |
152 | if (val) | |
9f7f0b2b | 153 | chip->gpio_state |= BIT(gpio); |
0bcb6069 | 154 | else |
9f7f0b2b | 155 | chip->gpio_state &= ~BIT(gpio); |
bc2f3dc3 | 156 | xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); |
0bcb6069 JL |
157 | |
158 | /* Clear the GPIO bit in shadow register and set direction as output */ | |
9f7f0b2b | 159 | chip->gpio_dir &= ~BIT(gpio); |
bc2f3dc3 | 160 | xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); |
0bcb6069 JL |
161 | |
162 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | |
163 | ||
164 | return 0; | |
165 | } | |
166 | ||
167 | /** | |
168 | * xgpio_save_regs - Set initial values of GPIO pins | |
169 | * @mm_gc: pointer to memory mapped GPIO chip structure | |
170 | */ | |
171 | static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) | |
172 | { | |
173 | struct xgpio_instance *chip = | |
174 | container_of(mm_gc, struct xgpio_instance, mmchip); | |
175 | ||
bc2f3dc3 RRD |
176 | xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); |
177 | xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | |
0bcb6069 JL |
178 | } |
179 | ||
749564ff RRD |
180 | /** |
181 | * xgpio_remove - Remove method for the GPIO device. | |
182 | * @pdev: pointer to the platform device | |
183 | * | |
184 | * This function remove gpiochips and frees all the allocated resources. | |
185 | */ | |
186 | static int xgpio_remove(struct platform_device *pdev) | |
187 | { | |
188 | struct xgpio *xgpio = platform_get_drvdata(pdev); | |
189 | int i; | |
190 | ||
191 | for (i = 0; i < 2; i++) { | |
192 | if (!xgpio->port[i].inited) | |
193 | continue; | |
194 | gpiochip_remove(&xgpio->port[i].mmchip.gc); | |
195 | ||
196 | if (i == 1) | |
197 | xgpio->port[i].mmchip.regs -= XGPIO_CHANNEL_OFFSET; | |
198 | ||
199 | iounmap(xgpio->port[i].mmchip.regs); | |
200 | kfree(xgpio->port[i].mmchip.gc.label); | |
201 | } | |
202 | ||
203 | return 0; | |
204 | } | |
205 | ||
0bcb6069 JL |
206 | /** |
207 | * xgpio_of_probe - Probe method for the GPIO device. | |
749564ff | 208 | * @pdev: pointer to the platform device |
0bcb6069 JL |
209 | * |
210 | * This function probes the GPIO device in the device tree. It initializes the | |
211 | * driver data structure. It returns 0, if the driver is bound to the GPIO | |
212 | * device, or a negative value if there is an error. | |
213 | */ | |
749564ff | 214 | static int xgpio_probe(struct platform_device *pdev) |
0bcb6069 | 215 | { |
749564ff | 216 | struct xgpio *xgpio; |
0bcb6069 | 217 | struct xgpio_instance *chip; |
0bcb6069 | 218 | int status = 0; |
749564ff | 219 | struct device_node *np = pdev->dev.of_node; |
0bcb6069 | 220 | const u32 *tree_info; |
1b4c5a6e | 221 | u32 ngpio; |
0bcb6069 | 222 | |
749564ff RRD |
223 | xgpio = devm_kzalloc(&pdev->dev, sizeof(*xgpio), GFP_KERNEL); |
224 | if (!xgpio) | |
0bcb6069 | 225 | return -ENOMEM; |
0bcb6069 | 226 | |
749564ff RRD |
227 | platform_set_drvdata(pdev, xgpio); |
228 | ||
229 | chip = &xgpio->port[0]; | |
230 | ||
0bcb6069 | 231 | /* Update GPIO state shadow register with default value */ |
6f8bf500 MS |
232 | of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state); |
233 | ||
234 | /* By default, all pins are inputs */ | |
235 | chip->gpio_dir = 0xFFFFFFFF; | |
0bcb6069 JL |
236 | |
237 | /* Update GPIO direction shadow register with default value */ | |
6f8bf500 MS |
238 | of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); |
239 | ||
1b4c5a6e GV |
240 | /* |
241 | * Check device node and parent device node for device width | |
242 | * and assume default width of 32 | |
243 | */ | |
244 | if (of_property_read_u32(np, "xlnx,gpio-width", &ngpio)) | |
245 | ngpio = 32; | |
246 | chip->mmchip.gc.ngpio = (u16)ngpio; | |
0bcb6069 JL |
247 | |
248 | spin_lock_init(&chip->gpio_lock); | |
249 | ||
749564ff | 250 | chip->mmchip.gc.dev = &pdev->dev; |
a19e3da5 AV |
251 | chip->mmchip.gc.direction_input = xgpio_dir_in; |
252 | chip->mmchip.gc.direction_output = xgpio_dir_out; | |
253 | chip->mmchip.gc.get = xgpio_get; | |
254 | chip->mmchip.gc.set = xgpio_set; | |
0bcb6069 JL |
255 | |
256 | chip->mmchip.save_regs = xgpio_save_regs; | |
257 | ||
258 | /* Call the OF gpio helper to setup and register the GPIO device */ | |
259 | status = of_mm_gpiochip_add(np, &chip->mmchip); | |
260 | if (status) { | |
0bcb6069 JL |
261 | pr_err("%s: error in probe function with status %d\n", |
262 | np->full_name, status); | |
263 | return status; | |
264 | } | |
749564ff | 265 | chip->inited = true; |
74600ee0 MS |
266 | |
267 | pr_info("XGpio: %s: registered, base is %d\n", np->full_name, | |
268 | chip->mmchip.gc.base); | |
269 | ||
270 | tree_info = of_get_property(np, "xlnx,is-dual", NULL); | |
271 | if (tree_info && be32_to_cpup(tree_info)) { | |
749564ff | 272 | chip = &xgpio->port[1]; |
74600ee0 | 273 | |
74600ee0 MS |
274 | /* Update GPIO state shadow register with default value */ |
275 | of_property_read_u32(np, "xlnx,dout-default-2", | |
276 | &chip->gpio_state); | |
277 | ||
278 | /* By default, all pins are inputs */ | |
279 | chip->gpio_dir = 0xFFFFFFFF; | |
280 | ||
281 | /* Update GPIO direction shadow register with default value */ | |
282 | of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir); | |
283 | ||
1b4c5a6e GV |
284 | /* |
285 | * Check device node and parent device node for device width | |
286 | * and assume default width of 32 | |
287 | */ | |
288 | if (of_property_read_u32(np, "xlnx,gpio2-width", &ngpio)) | |
289 | ngpio = 32; | |
290 | chip->mmchip.gc.ngpio = (u16)ngpio; | |
74600ee0 MS |
291 | |
292 | spin_lock_init(&chip->gpio_lock); | |
293 | ||
749564ff | 294 | chip->mmchip.gc.dev = &pdev->dev; |
74600ee0 MS |
295 | chip->mmchip.gc.direction_input = xgpio_dir_in; |
296 | chip->mmchip.gc.direction_output = xgpio_dir_out; | |
297 | chip->mmchip.gc.get = xgpio_get; | |
298 | chip->mmchip.gc.set = xgpio_set; | |
299 | ||
300 | chip->mmchip.save_regs = xgpio_save_regs; | |
301 | ||
302 | /* Call the OF gpio helper to setup and register the GPIO dev */ | |
303 | status = of_mm_gpiochip_add(np, &chip->mmchip); | |
304 | if (status) { | |
749564ff | 305 | xgpio_remove(pdev); |
74600ee0 MS |
306 | pr_err("%s: error in probe function with status %d\n", |
307 | np->full_name, status); | |
308 | return status; | |
309 | } | |
bc2f3dc3 RRD |
310 | |
311 | /* Add dual channel offset */ | |
312 | chip->mmchip.regs += XGPIO_CHANNEL_OFFSET; | |
749564ff | 313 | chip->inited = true; |
bc2f3dc3 | 314 | |
74600ee0 MS |
315 | pr_info("XGpio: %s: dual channel registered, base is %d\n", |
316 | np->full_name, chip->mmchip.gc.base); | |
317 | } | |
318 | ||
0bcb6069 JL |
319 | return 0; |
320 | } | |
321 | ||
9992bc95 | 322 | static const struct of_device_id xgpio_of_match[] = { |
0bcb6069 JL |
323 | { .compatible = "xlnx,xps-gpio-1.00.a", }, |
324 | { /* end of list */ }, | |
325 | }; | |
326 | ||
749564ff | 327 | MODULE_DEVICE_TABLE(of, xgpio_of_match); |
0bcb6069 | 328 | |
749564ff RRD |
329 | static struct platform_driver xgpio_plat_driver = { |
330 | .probe = xgpio_probe, | |
331 | .remove = xgpio_remove, | |
332 | .driver = { | |
333 | .name = "gpio-xilinx", | |
334 | .of_match_table = xgpio_of_match, | |
335 | }, | |
336 | }; | |
0bcb6069 | 337 | |
749564ff RRD |
338 | static int __init xgpio_init(void) |
339 | { | |
340 | return platform_driver_register(&xgpio_plat_driver); | |
0bcb6069 JL |
341 | } |
342 | ||
0bcb6069 | 343 | subsys_initcall(xgpio_init); |
749564ff RRD |
344 | |
345 | static void __exit xgpio_exit(void) | |
346 | { | |
347 | platform_driver_unregister(&xgpio_plat_driver); | |
348 | } | |
349 | module_exit(xgpio_exit); | |
0bcb6069 JL |
350 | |
351 | MODULE_AUTHOR("Xilinx, Inc."); | |
352 | MODULE_DESCRIPTION("Xilinx GPIO driver"); | |
353 | MODULE_LICENSE("GPL"); |