diff options
Diffstat (limited to 'drivers/gpio/gpio-xilinx.c')
-rw-r--r-- | drivers/gpio/gpio-xilinx.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c new file mode 100644 index 000000000000..846fbd5e31bf --- /dev/null +++ b/drivers/gpio/gpio-xilinx.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Xilinx gpio driver | ||
3 | * | ||
4 | * Copyright 2008 Xilinx, Inc. | ||
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 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/of_device.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/of_gpio.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | /* Register Offset Definitions */ | ||
25 | #define XGPIO_DATA_OFFSET (0x0) /* Data register */ | ||
26 | #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ | ||
27 | |||
28 | struct xgpio_instance { | ||
29 | struct of_mm_gpio_chip mmchip; | ||
30 | u32 gpio_state; /* GPIO state shadow register */ | ||
31 | u32 gpio_dir; /* GPIO direction shadow register */ | ||
32 | spinlock_t gpio_lock; /* Lock used for synchronization */ | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * xgpio_get - Read the specified signal of the GPIO device. | ||
37 | * @gc: Pointer to gpio_chip device structure. | ||
38 | * @gpio: GPIO signal number. | ||
39 | * | ||
40 | * This function reads the specified signal of the GPIO device. It returns 0 if | ||
41 | * the signal clear, 1 if signal is set or negative value on error. | ||
42 | */ | ||
43 | static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
44 | { | ||
45 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
46 | |||
47 | return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1; | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * xgpio_set - Write the specified signal of the GPIO device. | ||
52 | * @gc: Pointer to gpio_chip device structure. | ||
53 | * @gpio: GPIO signal number. | ||
54 | * @val: Value to be written to specified signal. | ||
55 | * | ||
56 | * This function writes the specified value in to the specified signal of the | ||
57 | * GPIO device. | ||
58 | */ | ||
59 | static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
60 | { | ||
61 | unsigned long flags; | ||
62 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
63 | struct xgpio_instance *chip = | ||
64 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
65 | |||
66 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
67 | |||
68 | /* Write to GPIO signal and set its direction to output */ | ||
69 | if (val) | ||
70 | chip->gpio_state |= 1 << gpio; | ||
71 | else | ||
72 | chip->gpio_state &= ~(1 << gpio); | ||
73 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
74 | |||
75 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * xgpio_dir_in - Set the direction of the specified GPIO signal as input. | ||
80 | * @gc: Pointer to gpio_chip device structure. | ||
81 | * @gpio: GPIO signal number. | ||
82 | * | ||
83 | * This function sets the direction of specified GPIO signal as input. | ||
84 | * It returns 0 if direction of GPIO signals is set as input otherwise it | ||
85 | * returns negative error value. | ||
86 | */ | ||
87 | static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
88 | { | ||
89 | unsigned long flags; | ||
90 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
91 | struct xgpio_instance *chip = | ||
92 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
93 | |||
94 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
95 | |||
96 | /* Set the GPIO bit in shadow register and set direction as input */ | ||
97 | chip->gpio_dir |= (1 << gpio); | ||
98 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
99 | |||
100 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * xgpio_dir_out - Set the direction of the specified GPIO signal as output. | ||
107 | * @gc: Pointer to gpio_chip device structure. | ||
108 | * @gpio: GPIO signal number. | ||
109 | * @val: Value to be written to specified signal. | ||
110 | * | ||
111 | * This function sets the direction of specified GPIO signal as output. If all | ||
112 | * GPIO signals of GPIO chip is configured as input then it returns | ||
113 | * error otherwise it returns 0. | ||
114 | */ | ||
115 | static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
116 | { | ||
117 | unsigned long flags; | ||
118 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
119 | struct xgpio_instance *chip = | ||
120 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
121 | |||
122 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
123 | |||
124 | /* Write state of GPIO signal */ | ||
125 | if (val) | ||
126 | chip->gpio_state |= 1 << gpio; | ||
127 | else | ||
128 | chip->gpio_state &= ~(1 << gpio); | ||
129 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
130 | |||
131 | /* Clear the GPIO bit in shadow register and set direction as output */ | ||
132 | chip->gpio_dir &= (~(1 << gpio)); | ||
133 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
134 | |||
135 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * xgpio_save_regs - Set initial values of GPIO pins | ||
142 | * @mm_gc: pointer to memory mapped GPIO chip structure | ||
143 | */ | ||
144 | static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
145 | { | ||
146 | struct xgpio_instance *chip = | ||
147 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
148 | |||
149 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
150 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * xgpio_of_probe - Probe method for the GPIO device. | ||
155 | * @np: pointer to device tree node | ||
156 | * | ||
157 | * This function probes the GPIO device in the device tree. It initializes the | ||
158 | * driver data structure. It returns 0, if the driver is bound to the GPIO | ||
159 | * device, or a negative value if there is an error. | ||
160 | */ | ||
161 | static int __devinit xgpio_of_probe(struct device_node *np) | ||
162 | { | ||
163 | struct xgpio_instance *chip; | ||
164 | int status = 0; | ||
165 | const u32 *tree_info; | ||
166 | |||
167 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
168 | if (!chip) | ||
169 | return -ENOMEM; | ||
170 | |||
171 | /* Update GPIO state shadow register with default value */ | ||
172 | tree_info = of_get_property(np, "xlnx,dout-default", NULL); | ||
173 | if (tree_info) | ||
174 | chip->gpio_state = be32_to_cpup(tree_info); | ||
175 | |||
176 | /* Update GPIO direction shadow register with default value */ | ||
177 | chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */ | ||
178 | tree_info = of_get_property(np, "xlnx,tri-default", NULL); | ||
179 | if (tree_info) | ||
180 | chip->gpio_dir = be32_to_cpup(tree_info); | ||
181 | |||
182 | /* Check device node and parent device node for device width */ | ||
183 | chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */ | ||
184 | tree_info = of_get_property(np, "xlnx,gpio-width", NULL); | ||
185 | if (!tree_info) | ||
186 | tree_info = of_get_property(np->parent, | ||
187 | "xlnx,gpio-width", NULL); | ||
188 | if (tree_info) | ||
189 | chip->mmchip.gc.ngpio = be32_to_cpup(tree_info); | ||
190 | |||
191 | spin_lock_init(&chip->gpio_lock); | ||
192 | |||
193 | chip->mmchip.gc.direction_input = xgpio_dir_in; | ||
194 | chip->mmchip.gc.direction_output = xgpio_dir_out; | ||
195 | chip->mmchip.gc.get = xgpio_get; | ||
196 | chip->mmchip.gc.set = xgpio_set; | ||
197 | |||
198 | chip->mmchip.save_regs = xgpio_save_regs; | ||
199 | |||
200 | /* Call the OF gpio helper to setup and register the GPIO device */ | ||
201 | status = of_mm_gpiochip_add(np, &chip->mmchip); | ||
202 | if (status) { | ||
203 | kfree(chip); | ||
204 | pr_err("%s: error in probe function with status %d\n", | ||
205 | np->full_name, status); | ||
206 | return status; | ||
207 | } | ||
208 | pr_info("XGpio: %s: registered\n", np->full_name); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static struct of_device_id xgpio_of_match[] __devinitdata = { | ||
213 | { .compatible = "xlnx,xps-gpio-1.00.a", }, | ||
214 | { /* end of list */ }, | ||
215 | }; | ||
216 | |||
217 | static int __init xgpio_init(void) | ||
218 | { | ||
219 | struct device_node *np; | ||
220 | |||
221 | for_each_matching_node(np, xgpio_of_match) | ||
222 | xgpio_of_probe(np); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | /* Make sure we get initialized before anyone else tries to use us */ | ||
228 | subsys_initcall(xgpio_init); | ||
229 | /* No exit call at the moment as we cannot unregister of GPIO chips */ | ||
230 | |||
231 | MODULE_AUTHOR("Xilinx, Inc."); | ||
232 | MODULE_DESCRIPTION("Xilinx GPIO driver"); | ||
233 | MODULE_LICENSE("GPL"); | ||