Blame view
drivers/gpio/gpio-zynq.c
24.6 KB
3242ba117 gpio: Add driver ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * Xilinx Zynq GPIO device driver * * Copyright (C) 2009 - 2014 Xilinx, Inc. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. */ #include <linux/bitops.h> #include <linux/clk.h> #include <linux/gpio/driver.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> |
bdf7a4ae3 gpio: Added suppo... |
21 |
#include <linux/of.h> |
3242ba117 gpio: Add driver ... |
22 23 24 25 26 |
#define DRIVER_NAME "zynq-gpio" /* Maximum banks */ #define ZYNQ_GPIO_MAX_BANK 4 |
bdf7a4ae3 gpio: Added suppo... |
27 |
#define ZYNQMP_GPIO_MAX_BANK 6 |
3242ba117 gpio: Add driver ... |
28 29 30 31 32 |
#define ZYNQ_GPIO_BANK0_NGPIO 32 #define ZYNQ_GPIO_BANK1_NGPIO 22 #define ZYNQ_GPIO_BANK2_NGPIO 32 #define ZYNQ_GPIO_BANK3_NGPIO 32 |
bdf7a4ae3 gpio: Added suppo... |
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#define ZYNQMP_GPIO_BANK0_NGPIO 26 #define ZYNQMP_GPIO_BANK1_NGPIO 26 #define ZYNQMP_GPIO_BANK2_NGPIO 26 #define ZYNQMP_GPIO_BANK3_NGPIO 32 #define ZYNQMP_GPIO_BANK4_NGPIO 32 #define ZYNQMP_GPIO_BANK5_NGPIO 32 #define ZYNQ_GPIO_NR_GPIOS 118 #define ZYNQMP_GPIO_NR_GPIOS 174 #define ZYNQ_GPIO_BANK0_PIN_MIN(str) 0 #define ZYNQ_GPIO_BANK0_PIN_MAX(str) (ZYNQ_GPIO_BANK0_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK0_NGPIO - 1) #define ZYNQ_GPIO_BANK1_PIN_MIN(str) (ZYNQ_GPIO_BANK0_PIN_MAX(str) + 1) #define ZYNQ_GPIO_BANK1_PIN_MAX(str) (ZYNQ_GPIO_BANK1_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK1_NGPIO - 1) #define ZYNQ_GPIO_BANK2_PIN_MIN(str) (ZYNQ_GPIO_BANK1_PIN_MAX(str) + 1) #define ZYNQ_GPIO_BANK2_PIN_MAX(str) (ZYNQ_GPIO_BANK2_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK2_NGPIO - 1) #define ZYNQ_GPIO_BANK3_PIN_MIN(str) (ZYNQ_GPIO_BANK2_PIN_MAX(str) + 1) #define ZYNQ_GPIO_BANK3_PIN_MAX(str) (ZYNQ_GPIO_BANK3_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK3_NGPIO - 1) #define ZYNQ_GPIO_BANK4_PIN_MIN(str) (ZYNQ_GPIO_BANK3_PIN_MAX(str) + 1) #define ZYNQ_GPIO_BANK4_PIN_MAX(str) (ZYNQ_GPIO_BANK4_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK4_NGPIO - 1) #define ZYNQ_GPIO_BANK5_PIN_MIN(str) (ZYNQ_GPIO_BANK4_PIN_MAX(str) + 1) #define ZYNQ_GPIO_BANK5_PIN_MAX(str) (ZYNQ_GPIO_BANK5_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK5_NGPIO - 1) |
3242ba117 gpio: Add driver ... |
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
/* Register offsets for the GPIO device */ /* LSW Mask & Data -WO */ #define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK)) /* MSW Mask & Data -WO */ #define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK)) /* Data Register-RW */ #define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK)) /* Direction mode reg-RW */ #define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK)) /* Output enable reg-RW */ #define ZYNQ_GPIO_OUTEN_OFFSET(BANK) (0x208 + (0x40 * BANK)) /* Interrupt mask reg-RO */ #define ZYNQ_GPIO_INTMASK_OFFSET(BANK) (0x20C + (0x40 * BANK)) /* Interrupt enable reg-WO */ #define ZYNQ_GPIO_INTEN_OFFSET(BANK) (0x210 + (0x40 * BANK)) /* Interrupt disable reg-WO */ #define ZYNQ_GPIO_INTDIS_OFFSET(BANK) (0x214 + (0x40 * BANK)) /* Interrupt status reg-RO */ #define ZYNQ_GPIO_INTSTS_OFFSET(BANK) (0x218 + (0x40 * BANK)) /* Interrupt type reg-RW */ #define ZYNQ_GPIO_INTTYPE_OFFSET(BANK) (0x21C + (0x40 * BANK)) /* Interrupt polarity reg-RW */ #define ZYNQ_GPIO_INTPOL_OFFSET(BANK) (0x220 + (0x40 * BANK)) /* Interrupt on any, reg-RW */ #define ZYNQ_GPIO_INTANY_OFFSET(BANK) (0x224 + (0x40 * BANK)) /* Disable all interrupts mask */ #define ZYNQ_GPIO_IXR_DISABLE_ALL 0xFFFFFFFF /* Mid pin number of a bank */ #define ZYNQ_GPIO_MID_PIN_NUM 16 /* GPIO upper 16 bit mask */ #define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000 |
e3296f19c gpio: Added zynq ... |
97 98 |
/* For GPIO quirks */ #define ZYNQ_GPIO_QUIRK_FOO BIT(0) |
3242ba117 gpio: Add driver ... |
99 100 101 102 103 |
/** * struct zynq_gpio - gpio device private data structure * @chip: instance of the gpio_chip * @base_addr: base address of the GPIO device * @clk: clock resource for this controller |
59e22114b gpio: zynq: Fixed... |
104 |
* @irq: interrupt for the GPIO device |
bdf7a4ae3 gpio: Added suppo... |
105 |
* @p_data: pointer to platform data |
3242ba117 gpio: Add driver ... |
106 107 108 109 110 |
*/ struct zynq_gpio { struct gpio_chip chip; void __iomem *base_addr; struct clk *clk; |
59e22114b gpio: zynq: Fixed... |
111 |
int irq; |
bdf7a4ae3 gpio: Added suppo... |
112 113 114 115 116 117 118 119 120 121 122 123 124 |
const struct zynq_platform_data *p_data; }; /** * struct zynq_platform_data - zynq gpio platform data structure * @label: string to store in gpio->label * @ngpio: max number of gpio pins * @max_bank: maximum number of gpio banks * @bank_min: this array represents bank's min pin * @bank_max: this array represents bank's max pin */ struct zynq_platform_data { const char *label; |
e3296f19c gpio: Added zynq ... |
125 |
u32 quirks; |
bdf7a4ae3 gpio: Added suppo... |
126 127 128 129 |
u16 ngpio; int max_bank; int bank_min[ZYNQMP_GPIO_MAX_BANK]; int bank_max[ZYNQMP_GPIO_MAX_BANK]; |
3242ba117 gpio: Add driver ... |
130 |
}; |
6dd859508 gpio: zynq: Fix I... |
131 132 |
static struct irq_chip zynq_gpio_level_irqchip; static struct irq_chip zynq_gpio_edge_irqchip; |
fa9795d11 gpio: zynq: use c... |
133 |
|
3242ba117 gpio: Add driver ... |
134 135 136 137 138 139 140 141 142 143 144 145 146 |
/** * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank * for a given pin in the GPIO device * @pin_num: gpio pin number within the device * @bank_num: an output parameter used to return the bank number of the gpio * pin * @bank_pin_num: an output parameter used to return pin number within a bank * for the given gpio pin * * Returns the bank number and pin offset within the bank. */ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, unsigned int *bank_num, |
bdf7a4ae3 gpio: Added suppo... |
147 148 |
unsigned int *bank_pin_num, struct zynq_gpio *gpio) |
3242ba117 gpio: Add driver ... |
149 |
{ |
bdf7a4ae3 gpio: Added suppo... |
150 151 152 153 154 155 156 157 158 159 |
int bank; for (bank = 0; bank < gpio->p_data->max_bank; bank++) { if ((pin_num >= gpio->p_data->bank_min[bank]) && (pin_num <= gpio->p_data->bank_max[bank])) { *bank_num = bank; *bank_pin_num = pin_num - gpio->p_data->bank_min[bank]; return; } |
3242ba117 gpio: Add driver ... |
160 |
} |
3242ba117 gpio: Add driver ... |
161 |
|
bdf7a4ae3 gpio: Added suppo... |
162 163 164 165 166 |
/* default */ WARN(true, "invalid GPIO pin number: %u", pin_num); *bank_num = 0; *bank_pin_num = 0; } |
016da1443 gpio: zynq: Take ... |
167 |
|
3242ba117 gpio: Add driver ... |
168 169 170 171 172 173 174 175 176 177 178 179 180 |
/** * zynq_gpio_get_value - Get the state of the specified pin of GPIO device * @chip: gpio_chip instance to be worked on * @pin: gpio pin number within the device * * This function reads the state of the specified pin of the GPIO device. * * Return: 0 if the pin is low, 1 if pin is high. */ static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin) { u32 data; unsigned int bank_num, bank_pin_num; |
31a894475 gpio: zynq: use g... |
181 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
182 |
|
bdf7a4ae3 gpio: Added suppo... |
183 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
data = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); return (data >> bank_pin_num) & 1; } /** * zynq_gpio_set_value - Modify the state of the pin with specified value * @chip: gpio_chip instance to be worked on * @pin: gpio pin number within the device * @state: value used to modify the state of the specified pin * * This function calculates the register offset (i.e to lower 16 bits or * upper 16 bits) based on the given pin number and sets the state of a * gpio pin to the specified value. The state is either 0 or non-zero. */ static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin, int state) { unsigned int reg_offset, bank_num, bank_pin_num; |
31a894475 gpio: zynq: use g... |
205 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
206 |
|
bdf7a4ae3 gpio: Added suppo... |
207 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) { /* only 16 data bits in bit maskable reg */ bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM; reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num); } else { reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num); } /* * get the 32 bit value to be written to the mask/data register where * the upper 16 bits is the mask and lower 16 bits is the data */ state = !!state; state = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) & ((state << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK); writel_relaxed(state, gpio->base_addr + reg_offset); } /** * zynq_gpio_dir_in - Set the direction of the specified GPIO pin as input * @chip: gpio_chip instance to be worked on * @pin: gpio pin number within the device * * This function uses the read-modify-write sequence to set the direction of * the gpio pin as input. * * Return: 0 always */ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin) { u32 reg; |
e3296f19c gpio: Added zynq ... |
241 |
bool is_zynq_gpio; |
3242ba117 gpio: Add driver ... |
242 |
unsigned int bank_num, bank_pin_num; |
31a894475 gpio: zynq: use g... |
243 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
244 |
|
e3296f19c gpio: Added zynq ... |
245 |
is_zynq_gpio = gpio->p_data->quirks & ZYNQ_GPIO_QUIRK_FOO; |
bdf7a4ae3 gpio: Added suppo... |
246 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
247 |
|
e3296f19c gpio: Added zynq ... |
248 249 250 251 252 253 |
/* * On zynq bank 0 pins 7 and 8 are special and cannot be used * as inputs. */ if (is_zynq_gpio && bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8)) |
3242ba117 gpio: Add driver ... |
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
return -EINVAL; /* clear the bit in direction mode reg to set the pin as input */ reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); reg &= ~BIT(bank_pin_num); writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); return 0; } /** * zynq_gpio_dir_out - Set the direction of the specified GPIO pin as output * @chip: gpio_chip instance to be worked on * @pin: gpio pin number within the device * @state: value to be written to specified pin * * This function sets the direction of specified GPIO pin as output, configures * the Output Enable register for the pin and uses zynq_gpio_set to set * the state of the pin to the value specified. * * Return: 0 always */ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int state) { u32 reg; unsigned int bank_num, bank_pin_num; |
31a894475 gpio: zynq: use g... |
281 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
282 |
|
bdf7a4ae3 gpio: Added suppo... |
283 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
/* set the GPIO pin as output */ reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); reg |= BIT(bank_pin_num); writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); /* configure the output enable reg for the pin */ reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); reg |= BIT(bank_pin_num); writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); /* set the state of the pin */ zynq_gpio_set_value(chip, pin, state); return 0; } /** * zynq_gpio_irq_mask - Disable the interrupts for a gpio pin * @irq_data: per irq and chip data passed down to chip functions * * This function calculates gpio pin number from irq number and sets the * bit in the Interrupt Disable register of the corresponding bank to disable * interrupts for that pin. */ static void zynq_gpio_irq_mask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; |
fa9795d11 gpio: zynq: use c... |
311 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
312 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
3242ba117 gpio: Add driver ... |
313 314 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
315 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
writel_relaxed(BIT(bank_pin_num), gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); } /** * zynq_gpio_irq_unmask - Enable the interrupts for a gpio pin * @irq_data: irq data containing irq number of gpio pin for the interrupt * to enable * * This function calculates the gpio pin number from irq number and sets the * bit in the Interrupt Enable register of the corresponding bank to enable * interrupts for that pin. */ static void zynq_gpio_irq_unmask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; |
fa9795d11 gpio: zynq: use c... |
332 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
333 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
3242ba117 gpio: Add driver ... |
334 335 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
336 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
337 338 339 340 341 |
writel_relaxed(BIT(bank_pin_num), gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num)); } /** |
190dc2e68 gpio: zynq: Clear... |
342 343 344 345 346 347 348 349 350 351 |
* zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin * @irq_data: irq data containing irq number of gpio pin for the interrupt * to ack * * This function calculates gpio pin number from irq number and sets the bit * in the Interrupt Status Register of the corresponding bank, to ACK the irq. */ static void zynq_gpio_irq_ack(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; |
fa9795d11 gpio: zynq: use c... |
352 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
353 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
190dc2e68 gpio: zynq: Clear... |
354 355 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
356 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
190dc2e68 gpio: zynq: Clear... |
357 358 359 360 361 362 363 364 365 |
writel_relaxed(BIT(bank_pin_num), gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num)); } /** * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin * @irq_data: irq data containing irq number of gpio pin for the interrupt * to enable * |
20a8a9687 Drivers: gpio: Fi... |
366 |
* Clears the INTSTS bit and unmasks the given interrupt. |
190dc2e68 gpio: zynq: Clear... |
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
*/ static void zynq_gpio_irq_enable(struct irq_data *irq_data) { /* * The Zynq GPIO controller does not disable interrupt detection when * the interrupt is masked and only disables the propagation of the * interrupt. This means when the controller detects an interrupt * condition while the interrupt is logically disabled it will propagate * that interrupt event once the interrupt is enabled. This will cause * the interrupt consumer to see spurious interrupts to prevent this * first make sure that the interrupt is not asserted and then enable * it. */ zynq_gpio_irq_ack(irq_data); zynq_gpio_irq_unmask(irq_data); } /** |
3242ba117 gpio: Add driver ... |
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
* zynq_gpio_set_irq_type - Set the irq type for a gpio pin * @irq_data: irq data containing irq number of gpio pin * @type: interrupt type that is to be set for the gpio pin * * This function gets the gpio pin number and its bank from the gpio pin number * and configures the INT_TYPE, INT_POLARITY and INT_ANY registers. * * Return: 0, negative error otherwise. * TYPE-EDGE_RISING, INT_TYPE - 1, INT_POLARITY - 1, INT_ANY - 0; * TYPE-EDGE_FALLING, INT_TYPE - 1, INT_POLARITY - 0, INT_ANY - 0; * TYPE-EDGE_BOTH, INT_TYPE - 1, INT_POLARITY - NA, INT_ANY - 1; * TYPE-LEVEL_HIGH, INT_TYPE - 0, INT_POLARITY - 1, INT_ANY - NA; * TYPE-LEVEL_LOW, INT_TYPE - 0, INT_POLARITY - 0, INT_ANY - NA */ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) { u32 int_type, int_pol, int_any; unsigned int device_pin_num, bank_num, bank_pin_num; |
fa9795d11 gpio: zynq: use c... |
403 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
404 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
3242ba117 gpio: Add driver ... |
405 406 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
407 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
int_type = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); int_pol = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num)); int_any = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); /* * based on the type requested, configure the INT_TYPE, INT_POLARITY * and INT_ANY registers */ switch (type) { case IRQ_TYPE_EDGE_RISING: int_type |= BIT(bank_pin_num); int_pol |= BIT(bank_pin_num); int_any &= ~BIT(bank_pin_num); break; case IRQ_TYPE_EDGE_FALLING: int_type |= BIT(bank_pin_num); int_pol &= ~BIT(bank_pin_num); int_any &= ~BIT(bank_pin_num); break; case IRQ_TYPE_EDGE_BOTH: int_type |= BIT(bank_pin_num); int_any |= BIT(bank_pin_num); break; case IRQ_TYPE_LEVEL_HIGH: int_type &= ~BIT(bank_pin_num); int_pol |= BIT(bank_pin_num); break; case IRQ_TYPE_LEVEL_LOW: int_type &= ~BIT(bank_pin_num); int_pol &= ~BIT(bank_pin_num); break; default: return -EINVAL; } writel_relaxed(int_type, gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); writel_relaxed(int_pol, gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num)); writel_relaxed(int_any, gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); |
6dd859508 gpio: zynq: Fix I... |
453 454 |
if (type & IRQ_TYPE_LEVEL_MASK) { |
47c084629 gpio/zynq: Use ir... |
455 |
irq_set_chip_handler_name_locked(irq_data, |
6dd859508 gpio: zynq: Fix I... |
456 457 |
&zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL); } else { |
47c084629 gpio/zynq: Use ir... |
458 |
irq_set_chip_handler_name_locked(irq_data, |
6dd859508 gpio: zynq: Fix I... |
459 460 |
&zynq_gpio_edge_irqchip, handle_level_irq, NULL); } |
3242ba117 gpio: Add driver ... |
461 462 463 464 465 |
return 0; } static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) { |
fa9795d11 gpio: zynq: use c... |
466 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
467 |
gpiochip_get_data(irq_data_get_irq_chip_data(data)); |
59e22114b gpio: zynq: Fixed... |
468 469 |
irq_set_irq_wake(gpio->irq, on); |
3242ba117 gpio: Add driver ... |
470 471 472 473 474 |
return 0; } /* irq chip descriptor */ |
6dd859508 gpio: zynq: Fix I... |
475 |
static struct irq_chip zynq_gpio_level_irqchip = { |
3242ba117 gpio: Add driver ... |
476 |
.name = DRIVER_NAME, |
190dc2e68 gpio: zynq: Clear... |
477 |
.irq_enable = zynq_gpio_irq_enable, |
6dd859508 gpio: zynq: Fix I... |
478 479 480 481 482 |
.irq_eoi = zynq_gpio_irq_ack, .irq_mask = zynq_gpio_irq_mask, .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, |
a19467788 gpio: zynq: Mask ... |
483 484 |
.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | IRQCHIP_MASK_ON_SUSPEND, |
6dd859508 gpio: zynq: Fix I... |
485 486 487 488 489 490 |
}; static struct irq_chip zynq_gpio_edge_irqchip = { .name = DRIVER_NAME, .irq_enable = zynq_gpio_irq_enable, .irq_ack = zynq_gpio_irq_ack, |
3242ba117 gpio: Add driver ... |
491 492 493 494 |
.irq_mask = zynq_gpio_irq_mask, .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, |
a19467788 gpio: zynq: Mask ... |
495 |
.flags = IRQCHIP_MASK_ON_SUSPEND, |
3242ba117 gpio: Add driver ... |
496 |
}; |
5a2533a74 gpio: zynq: Reduc... |
497 498 499 500 |
static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, unsigned int bank_num, unsigned long pending) { |
bdf7a4ae3 gpio: Added suppo... |
501 |
unsigned int bank_offset = gpio->p_data->bank_min[bank_num]; |
5a2533a74 gpio: zynq: Reduc... |
502 503 504 505 506 507 508 509 |
struct irq_domain *irqdomain = gpio->chip.irqdomain; int offset; if (!pending) return; for_each_set_bit(offset, &pending, 32) { unsigned int gpio_irq; |
016da1443 gpio: zynq: Take ... |
510 |
gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset); |
5a2533a74 gpio: zynq: Reduc... |
511 512 513 |
generic_handle_irq(gpio_irq); } } |
3242ba117 gpio: Add driver ... |
514 515 516 517 518 519 520 521 522 523 524 |
/** * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device * @irq: irq number of the gpio bank where interrupt has occurred * @desc: irq descriptor instance of the 'irq' * * This function reads the Interrupt Status Register of each bank to get the * gpio pin number which has triggered an interrupt. It then acks the triggered * interrupt and calls the pin specific handler set by the higher layer * application for that pin. * Note: A bug is reported if no handler is set for the gpio pin. */ |
bd0b9ac40 genirq: Remove ir... |
525 |
static void zynq_gpio_irqhandler(struct irq_desc *desc) |
3242ba117 gpio: Add driver ... |
526 527 528 |
{ u32 int_sts, int_enb; unsigned int bank_num; |
fa9795d11 gpio: zynq: use c... |
529 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
530 |
gpiochip_get_data(irq_desc_get_handler_data(desc)); |
3242ba117 gpio: Add driver ... |
531 532 533 |
struct irq_chip *irqchip = irq_desc_get_chip(desc); chained_irq_enter(irqchip, desc); |
bdf7a4ae3 gpio: Added suppo... |
534 |
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { |
3242ba117 gpio: Add driver ... |
535 536 537 538 |
int_sts = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num)); int_enb = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); |
5a2533a74 gpio: zynq: Reduc... |
539 |
zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb); |
3242ba117 gpio: Add driver ... |
540 541 542 543 544 545 546 |
} chained_irq_exit(irqchip, desc); } static int __maybe_unused zynq_gpio_suspend(struct device *dev) { |
59e22114b gpio: zynq: Fixed... |
547 548 549 550 551 |
struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq(pdev, 0); struct irq_data *data = irq_get_irq_data(irq); if (!irqd_is_wakeup_set(data)) |
3242ba117 gpio: Add driver ... |
552 553 554 555 556 557 558 |
return pm_runtime_force_suspend(dev); return 0; } static int __maybe_unused zynq_gpio_resume(struct device *dev) { |
59e22114b gpio: zynq: Fixed... |
559 560 561 562 563 |
struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq(pdev, 0); struct irq_data *data = irq_get_irq_data(irq); if (!irqd_is_wakeup_set(data)) |
3242ba117 gpio: Add driver ... |
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
return pm_runtime_force_resume(dev); return 0; } static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct zynq_gpio *gpio = platform_get_drvdata(pdev); clk_disable_unprepare(gpio->clk); return 0; } static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct zynq_gpio *gpio = platform_get_drvdata(pdev); return clk_prepare_enable(gpio->clk); } static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset) { int ret; |
58383c784 gpio: change memb... |
590 |
ret = pm_runtime_get_sync(chip->parent); |
3242ba117 gpio: Add driver ... |
591 592 593 594 595 596 597 598 599 600 |
/* * If the device is already active pm_runtime_get() will return 1 on * success, but gpio_request still needs to return 0. */ return ret < 0 ? ret : 0; } static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset) { |
58383c784 gpio: change memb... |
601 |
pm_runtime_put(chip->parent); |
3242ba117 gpio: Add driver ... |
602 603 604 605 |
} static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume) |
6ed23b806 PM: Merge the SET... |
606 |
SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, |
3242ba117 gpio: Add driver ... |
607 608 |
zynq_gpio_runtime_resume, NULL) }; |
bdf7a4ae3 gpio: Added suppo... |
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
static const struct zynq_platform_data zynqmp_gpio_def = { .label = "zynqmp_gpio", .ngpio = ZYNQMP_GPIO_NR_GPIOS, .max_bank = ZYNQMP_GPIO_MAX_BANK, .bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(MP), .bank_max[0] = ZYNQ_GPIO_BANK0_PIN_MAX(MP), .bank_min[1] = ZYNQ_GPIO_BANK1_PIN_MIN(MP), .bank_max[1] = ZYNQ_GPIO_BANK1_PIN_MAX(MP), .bank_min[2] = ZYNQ_GPIO_BANK2_PIN_MIN(MP), .bank_max[2] = ZYNQ_GPIO_BANK2_PIN_MAX(MP), .bank_min[3] = ZYNQ_GPIO_BANK3_PIN_MIN(MP), .bank_max[3] = ZYNQ_GPIO_BANK3_PIN_MAX(MP), .bank_min[4] = ZYNQ_GPIO_BANK4_PIN_MIN(MP), .bank_max[4] = ZYNQ_GPIO_BANK4_PIN_MAX(MP), .bank_min[5] = ZYNQ_GPIO_BANK5_PIN_MIN(MP), .bank_max[5] = ZYNQ_GPIO_BANK5_PIN_MAX(MP), }; static const struct zynq_platform_data zynq_gpio_def = { .label = "zynq_gpio", |
e3296f19c gpio: Added zynq ... |
629 |
.quirks = ZYNQ_GPIO_QUIRK_FOO, |
bdf7a4ae3 gpio: Added suppo... |
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
.ngpio = ZYNQ_GPIO_NR_GPIOS, .max_bank = ZYNQ_GPIO_MAX_BANK, .bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(), .bank_max[0] = ZYNQ_GPIO_BANK0_PIN_MAX(), .bank_min[1] = ZYNQ_GPIO_BANK1_PIN_MIN(), .bank_max[1] = ZYNQ_GPIO_BANK1_PIN_MAX(), .bank_min[2] = ZYNQ_GPIO_BANK2_PIN_MIN(), .bank_max[2] = ZYNQ_GPIO_BANK2_PIN_MAX(), .bank_min[3] = ZYNQ_GPIO_BANK3_PIN_MIN(), .bank_max[3] = ZYNQ_GPIO_BANK3_PIN_MAX(), }; static const struct of_device_id zynq_gpio_of_match[] = { { .compatible = "xlnx,zynq-gpio-1.0", .data = (void *)&zynq_gpio_def }, { .compatible = "xlnx,zynqmp-gpio-1.0", .data = (void *)&zynqmp_gpio_def }, { /* end of table */ } }; MODULE_DEVICE_TABLE(of, zynq_gpio_of_match); |
3242ba117 gpio: Add driver ... |
649 650 651 652 653 654 655 656 657 658 659 660 661 |
/** * zynq_gpio_probe - Initialization method for a zynq_gpio device * @pdev: platform device instance * * This function allocates memory resources for the gpio device and registers * all the banks of the device. It will also set up interrupts for the gpio * pins. * Note: Interrupts are disabled for all the banks during initialization. * * Return: 0 on success, negative error otherwise. */ static int zynq_gpio_probe(struct platform_device *pdev) { |
59e22114b gpio: zynq: Fixed... |
662 |
int ret, bank_num; |
3242ba117 gpio: Add driver ... |
663 664 665 |
struct zynq_gpio *gpio; struct gpio_chip *chip; struct resource *res; |
bdf7a4ae3 gpio: Added suppo... |
666 |
const struct of_device_id *match; |
3242ba117 gpio: Add driver ... |
667 668 669 670 |
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; |
bdf7a4ae3 gpio: Added suppo... |
671 672 673 674 675 676 677 |
match = of_match_node(zynq_gpio_of_match, pdev->dev.of_node); if (!match) { dev_err(&pdev->dev, "of_match_node() failed "); return -EINVAL; } gpio->p_data = match->data; |
3242ba117 gpio: Add driver ... |
678 679 680 681 682 683 |
platform_set_drvdata(pdev, gpio); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); gpio->base_addr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(gpio->base_addr)) return PTR_ERR(gpio->base_addr); |
59e22114b gpio: zynq: Fixed... |
684 685 |
gpio->irq = platform_get_irq(pdev, 0); if (gpio->irq < 0) { |
3242ba117 gpio: Add driver ... |
686 687 |
dev_err(&pdev->dev, "invalid IRQ "); |
59e22114b gpio: zynq: Fixed... |
688 |
return gpio->irq; |
3242ba117 gpio: Add driver ... |
689 690 691 692 |
} /* configure the gpio chip */ chip = &gpio->chip; |
bdf7a4ae3 gpio: Added suppo... |
693 |
chip->label = gpio->p_data->label; |
3242ba117 gpio: Add driver ... |
694 |
chip->owner = THIS_MODULE; |
58383c784 gpio: change memb... |
695 |
chip->parent = &pdev->dev; |
3242ba117 gpio: Add driver ... |
696 697 698 699 700 701 702 |
chip->get = zynq_gpio_get_value; chip->set = zynq_gpio_set_value; chip->request = zynq_gpio_request; chip->free = zynq_gpio_free; chip->direction_input = zynq_gpio_dir_in; chip->direction_output = zynq_gpio_dir_out; chip->base = -1; |
bdf7a4ae3 gpio: Added suppo... |
703 |
chip->ngpio = gpio->p_data->ngpio; |
3242ba117 gpio: Add driver ... |
704 |
|
3773c195d gpio: zynq: Do PM... |
705 |
/* Retrieve GPIO clock */ |
3242ba117 gpio: Add driver ... |
706 707 708 709 710 711 |
gpio->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(gpio->clk)) { dev_err(&pdev->dev, "input clock not found. "); return PTR_ERR(gpio->clk); } |
0f84f29ff gpio: zynq: initi... |
712 713 714 715 716 717 |
ret = clk_prepare_enable(gpio->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock. "); return ret; } |
3773c195d gpio: zynq: Do PM... |
718 |
|
0f84f29ff gpio: zynq: initi... |
719 |
pm_runtime_set_active(&pdev->dev); |
3773c195d gpio: zynq: Do PM... |
720 721 722 |
pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) |
615d23f80 gpio: zynq: Fix t... |
723 |
goto err_pm_dis; |
3242ba117 gpio: Add driver ... |
724 725 |
/* report a bug if gpio chip registration fails */ |
31a894475 gpio: zynq: use g... |
726 |
ret = gpiochip_add_data(chip, gpio); |
3242ba117 gpio: Add driver ... |
727 728 729 |
if (ret) { dev_err(&pdev->dev, "Failed to add gpio chip "); |
3773c195d gpio: zynq: Do PM... |
730 |
goto err_pm_put; |
3242ba117 gpio: Add driver ... |
731 732 733 |
} /* disable interrupts for all banks */ |
bdf7a4ae3 gpio: Added suppo... |
734 |
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) |
3242ba117 gpio: Add driver ... |
735 736 |
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); |
6dd859508 gpio: zynq: Fix I... |
737 738 |
ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0, handle_level_irq, IRQ_TYPE_NONE); |
3242ba117 gpio: Add driver ... |
739 740 741 742 743 |
if (ret) { dev_err(&pdev->dev, "Failed to add irq chip "); goto err_rm_gpiochip; } |
59e22114b gpio: zynq: Fixed... |
744 |
gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq, |
3242ba117 gpio: Add driver ... |
745 |
zynq_gpio_irqhandler); |
3773c195d gpio: zynq: Do PM... |
746 |
pm_runtime_put(&pdev->dev); |
3242ba117 gpio: Add driver ... |
747 |
|
3242ba117 gpio: Add driver ... |
748 749 750 |
return 0; err_rm_gpiochip: |
88d5e520a driver:gpio remov... |
751 |
gpiochip_remove(chip); |
3773c195d gpio: zynq: Do PM... |
752 753 |
err_pm_put: pm_runtime_put(&pdev->dev); |
615d23f80 gpio: zynq: Fix t... |
754 755 |
err_pm_dis: pm_runtime_disable(&pdev->dev); |
0f84f29ff gpio: zynq: initi... |
756 |
clk_disable_unprepare(gpio->clk); |
3242ba117 gpio: Add driver ... |
757 758 759 760 761 762 763 764 765 766 767 768 |
return ret; } /** * zynq_gpio_remove - Driver removal function * @pdev: platform device instance * * Return: 0 always */ static int zynq_gpio_remove(struct platform_device *pdev) { |
3242ba117 gpio: Add driver ... |
769 770 771 |
struct zynq_gpio *gpio = platform_get_drvdata(pdev); pm_runtime_get_sync(&pdev->dev); |
da26d5d80 gpio: remove rema... |
772 |
gpiochip_remove(&gpio->chip); |
3242ba117 gpio: Add driver ... |
773 774 |
clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); |
6b956af08 gpio: zynq: Fix p... |
775 |
pm_runtime_disable(&pdev->dev); |
3242ba117 gpio: Add driver ... |
776 777 |
return 0; } |
3242ba117 gpio: Add driver ... |
778 779 780 |
static struct platform_driver zynq_gpio_driver = { .driver = { .name = DRIVER_NAME, |
3242ba117 gpio: Add driver ... |
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 |
.pm = &zynq_gpio_dev_pm_ops, .of_match_table = zynq_gpio_of_match, }, .probe = zynq_gpio_probe, .remove = zynq_gpio_remove, }; /** * zynq_gpio_init - Initial driver registration call * * Return: value from platform_driver_register */ static int __init zynq_gpio_init(void) { return platform_driver_register(&zynq_gpio_driver); } postcore_initcall(zynq_gpio_init); |
80d2bf55a gpio: zynq: add m... |
798 799 800 801 802 |
static void __exit zynq_gpio_exit(void) { platform_driver_unregister(&zynq_gpio_driver); } module_exit(zynq_gpio_exit); |
3242ba117 gpio: Add driver ... |
803 804 805 |
MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); MODULE_LICENSE("GPL"); |