diff options
Diffstat (limited to 'drivers/gpio/gpio-xilinx.c')
-rw-r--r-- | drivers/gpio/gpio-xilinx.c | 144 |
1 files changed, 112 insertions, 32 deletions
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 9ae7aa8ca48a..792a05ad4649 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Xilinx gpio driver | 2 | * Xilinx gpio driver for xps/axi_gpio IP. |
3 | * | 3 | * |
4 | * Copyright 2008 Xilinx, Inc. | 4 | * Copyright 2008 - 2013 Xilinx, Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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 | 7 | * it under the terms of the GNU General Public License version 2 |
@@ -12,6 +12,7 @@ | |||
12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/bitops.h> | ||
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
@@ -26,11 +27,31 @@ | |||
26 | #define XGPIO_DATA_OFFSET (0x0) /* Data register */ | 27 | #define XGPIO_DATA_OFFSET (0x0) /* Data register */ |
27 | #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ | 28 | #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ |
28 | 29 | ||
30 | #define XGPIO_CHANNEL_OFFSET 0x8 | ||
31 | |||
32 | /* Read/Write access to the GPIO registers */ | ||
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 | ||
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 | ||
46 | * offset: GPIO channel offset | ||
47 | * gpio_lock: Lock used for synchronization | ||
48 | */ | ||
29 | struct xgpio_instance { | 49 | struct xgpio_instance { |
30 | struct of_mm_gpio_chip mmchip; | 50 | struct of_mm_gpio_chip mmchip; |
31 | u32 gpio_state; /* GPIO state shadow register */ | 51 | u32 gpio_state; |
32 | u32 gpio_dir; /* GPIO direction shadow register */ | 52 | u32 gpio_dir; |
33 | spinlock_t gpio_lock; /* Lock used for synchronization */ | 53 | u32 offset; |
54 | spinlock_t gpio_lock; | ||
34 | }; | 55 | }; |
35 | 56 | ||
36 | /** | 57 | /** |
@@ -44,8 +65,12 @@ struct xgpio_instance { | |||
44 | static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) | 65 | static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) |
45 | { | 66 | { |
46 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 67 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
68 | struct xgpio_instance *chip = | ||
69 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
47 | 70 | ||
48 | return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1; | 71 | void __iomem *regs = mm_gc->regs + chip->offset; |
72 | |||
73 | return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio)); | ||
49 | } | 74 | } |
50 | 75 | ||
51 | /** | 76 | /** |
@@ -63,15 +88,18 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | |||
63 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 88 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
64 | struct xgpio_instance *chip = | 89 | struct xgpio_instance *chip = |
65 | container_of(mm_gc, struct xgpio_instance, mmchip); | 90 | container_of(mm_gc, struct xgpio_instance, mmchip); |
91 | void __iomem *regs = mm_gc->regs; | ||
66 | 92 | ||
67 | spin_lock_irqsave(&chip->gpio_lock, flags); | 93 | spin_lock_irqsave(&chip->gpio_lock, flags); |
68 | 94 | ||
69 | /* Write to GPIO signal and set its direction to output */ | 95 | /* Write to GPIO signal and set its direction to output */ |
70 | if (val) | 96 | if (val) |
71 | chip->gpio_state |= 1 << gpio; | 97 | chip->gpio_state |= BIT(gpio); |
72 | else | 98 | else |
73 | chip->gpio_state &= ~(1 << gpio); | 99 | chip->gpio_state &= ~BIT(gpio); |
74 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | 100 | |
101 | xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, | ||
102 | chip->gpio_state); | ||
75 | 103 | ||
76 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | 104 | spin_unlock_irqrestore(&chip->gpio_lock, flags); |
77 | } | 105 | } |
@@ -91,12 +119,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | |||
91 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 119 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
92 | struct xgpio_instance *chip = | 120 | struct xgpio_instance *chip = |
93 | container_of(mm_gc, struct xgpio_instance, mmchip); | 121 | container_of(mm_gc, struct xgpio_instance, mmchip); |
122 | void __iomem *regs = mm_gc->regs; | ||
94 | 123 | ||
95 | spin_lock_irqsave(&chip->gpio_lock, flags); | 124 | spin_lock_irqsave(&chip->gpio_lock, flags); |
96 | 125 | ||
97 | /* Set the GPIO bit in shadow register and set direction as input */ | 126 | /* Set the GPIO bit in shadow register and set direction as input */ |
98 | chip->gpio_dir |= (1 << gpio); | 127 | chip->gpio_dir |= BIT(gpio); |
99 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | 128 | xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); |
100 | 129 | ||
101 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | 130 | spin_unlock_irqrestore(&chip->gpio_lock, flags); |
102 | 131 | ||
@@ -119,19 +148,21 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
119 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 148 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
120 | struct xgpio_instance *chip = | 149 | struct xgpio_instance *chip = |
121 | container_of(mm_gc, struct xgpio_instance, mmchip); | 150 | container_of(mm_gc, struct xgpio_instance, mmchip); |
151 | void __iomem *regs = mm_gc->regs; | ||
122 | 152 | ||
123 | spin_lock_irqsave(&chip->gpio_lock, flags); | 153 | spin_lock_irqsave(&chip->gpio_lock, flags); |
124 | 154 | ||
125 | /* Write state of GPIO signal */ | 155 | /* Write state of GPIO signal */ |
126 | if (val) | 156 | if (val) |
127 | chip->gpio_state |= 1 << gpio; | 157 | chip->gpio_state |= BIT(gpio); |
128 | else | 158 | else |
129 | chip->gpio_state &= ~(1 << gpio); | 159 | chip->gpio_state &= ~BIT(gpio); |
130 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | 160 | xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, |
161 | chip->gpio_state); | ||
131 | 162 | ||
132 | /* Clear the GPIO bit in shadow register and set direction as output */ | 163 | /* Clear the GPIO bit in shadow register and set direction as output */ |
133 | chip->gpio_dir &= (~(1 << gpio)); | 164 | chip->gpio_dir &= ~BIT(gpio); |
134 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | 165 | xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); |
135 | 166 | ||
136 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | 167 | spin_unlock_irqrestore(&chip->gpio_lock, flags); |
137 | 168 | ||
@@ -147,8 +178,10 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) | |||
147 | struct xgpio_instance *chip = | 178 | struct xgpio_instance *chip = |
148 | container_of(mm_gc, struct xgpio_instance, mmchip); | 179 | container_of(mm_gc, struct xgpio_instance, mmchip); |
149 | 180 | ||
150 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | 181 | xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET, |
151 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | 182 | chip->gpio_state); |
183 | xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET, | ||
184 | chip->gpio_dir); | ||
152 | } | 185 | } |
153 | 186 | ||
154 | /** | 187 | /** |
@@ -170,24 +203,20 @@ static int xgpio_of_probe(struct device_node *np) | |||
170 | return -ENOMEM; | 203 | return -ENOMEM; |
171 | 204 | ||
172 | /* Update GPIO state shadow register with default value */ | 205 | /* Update GPIO state shadow register with default value */ |
173 | tree_info = of_get_property(np, "xlnx,dout-default", NULL); | 206 | of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state); |
174 | if (tree_info) | 207 | |
175 | chip->gpio_state = be32_to_cpup(tree_info); | 208 | /* By default, all pins are inputs */ |
209 | chip->gpio_dir = 0xFFFFFFFF; | ||
176 | 210 | ||
177 | /* Update GPIO direction shadow register with default value */ | 211 | /* Update GPIO direction shadow register with default value */ |
178 | chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */ | 212 | of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); |
179 | tree_info = of_get_property(np, "xlnx,tri-default", NULL); | 213 | |
180 | if (tree_info) | 214 | /* By default assume full GPIO controller */ |
181 | chip->gpio_dir = be32_to_cpup(tree_info); | 215 | chip->mmchip.gc.ngpio = 32; |
182 | 216 | ||
183 | /* Check device node and parent device node for device width */ | 217 | /* Check device node and parent device node for device width */ |
184 | chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */ | 218 | of_property_read_u32(np, "xlnx,gpio-width", |
185 | tree_info = of_get_property(np, "xlnx,gpio-width", NULL); | 219 | (u32 *)&chip->mmchip.gc.ngpio); |
186 | if (!tree_info) | ||
187 | tree_info = of_get_property(np->parent, | ||
188 | "xlnx,gpio-width", NULL); | ||
189 | if (tree_info) | ||
190 | chip->mmchip.gc.ngpio = be32_to_cpup(tree_info); | ||
191 | 220 | ||
192 | spin_lock_init(&chip->gpio_lock); | 221 | spin_lock_init(&chip->gpio_lock); |
193 | 222 | ||
@@ -206,6 +235,57 @@ static int xgpio_of_probe(struct device_node *np) | |||
206 | np->full_name, status); | 235 | np->full_name, status); |
207 | return status; | 236 | return status; |
208 | } | 237 | } |
238 | |||
239 | pr_info("XGpio: %s: registered, base is %d\n", np->full_name, | ||
240 | chip->mmchip.gc.base); | ||
241 | |||
242 | tree_info = of_get_property(np, "xlnx,is-dual", NULL); | ||
243 | if (tree_info && be32_to_cpup(tree_info)) { | ||
244 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
245 | if (!chip) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | /* Add dual channel offset */ | ||
249 | chip->offset = XGPIO_CHANNEL_OFFSET; | ||
250 | |||
251 | /* Update GPIO state shadow register with default value */ | ||
252 | of_property_read_u32(np, "xlnx,dout-default-2", | ||
253 | &chip->gpio_state); | ||
254 | |||
255 | /* By default, all pins are inputs */ | ||
256 | chip->gpio_dir = 0xFFFFFFFF; | ||
257 | |||
258 | /* Update GPIO direction shadow register with default value */ | ||
259 | of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir); | ||
260 | |||
261 | /* By default assume full GPIO controller */ | ||
262 | chip->mmchip.gc.ngpio = 32; | ||
263 | |||
264 | /* Check device node and parent device node for device width */ | ||
265 | of_property_read_u32(np, "xlnx,gpio2-width", | ||
266 | (u32 *)&chip->mmchip.gc.ngpio); | ||
267 | |||
268 | spin_lock_init(&chip->gpio_lock); | ||
269 | |||
270 | chip->mmchip.gc.direction_input = xgpio_dir_in; | ||
271 | chip->mmchip.gc.direction_output = xgpio_dir_out; | ||
272 | chip->mmchip.gc.get = xgpio_get; | ||
273 | chip->mmchip.gc.set = xgpio_set; | ||
274 | |||
275 | chip->mmchip.save_regs = xgpio_save_regs; | ||
276 | |||
277 | /* Call the OF gpio helper to setup and register the GPIO dev */ | ||
278 | status = of_mm_gpiochip_add(np, &chip->mmchip); | ||
279 | if (status) { | ||
280 | kfree(chip); | ||
281 | pr_err("%s: error in probe function with status %d\n", | ||
282 | np->full_name, status); | ||
283 | return status; | ||
284 | } | ||
285 | pr_info("XGpio: %s: dual channel registered, base is %d\n", | ||
286 | np->full_name, chip->mmchip.gc.base); | ||
287 | } | ||
288 | |||
209 | return 0; | 289 | return 0; |
210 | } | 290 | } |
211 | 291 | ||