Blame view
drivers/gpio/gpio-zynq.c
31.4 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
3242ba117 gpio: Add driver ... |
2 3 4 5 |
/* * Xilinx Zynq GPIO device driver * * Copyright (C) 2009 - 2014 Xilinx, Inc. |
3242ba117 gpio: Add driver ... |
6 7 8 9 10 11 12 |
*/ #include <linux/bitops.h> #include <linux/clk.h> #include <linux/gpio/driver.h> #include <linux/init.h> #include <linux/interrupt.h> |
fdcfec11b gpio: zynq: prote... |
13 |
#include <linux/spinlock.h> |
3242ba117 gpio: Add driver ... |
14 15 16 17 |
#include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> |
bdf7a4ae3 gpio: Added suppo... |
18 |
#include <linux/of.h> |
3242ba117 gpio: Add driver ... |
19 20 21 22 23 |
#define DRIVER_NAME "zynq-gpio" /* Maximum banks */ #define ZYNQ_GPIO_MAX_BANK 4 |
bdf7a4ae3 gpio: Added suppo... |
24 |
#define ZYNQMP_GPIO_MAX_BANK 6 |
675002448 gpio: zynq: Add V... |
25 |
#define VERSAL_GPIO_MAX_BANK 4 |
73c612fe2 gpio: zynq: Add p... |
26 |
#define PMC_GPIO_MAX_BANK 5 |
675002448 gpio: zynq: Add V... |
27 |
#define VERSAL_UNUSED_BANKS 2 |
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 |
|
3242ba117 gpio: Add driver ... |
62 63 64 65 66 67 |
/* 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 */ |
06aa09081 gpio: zynq: Provi... |
68 |
#define ZYNQ_GPIO_DATA_OFFSET(BANK) (0x040 + (4 * BANK)) |
3242ba117 gpio: Add driver ... |
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 |
#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 |
3638bd4a0 gpio: zynq: Clari... |
97 98 |
/* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */ #define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0) |
06aa09081 gpio: zynq: Provi... |
99 |
#define GPIO_QUIRK_DATA_RO_BUG BIT(1) |
675002448 gpio: zynq: Add V... |
100 |
#define GPIO_QUIRK_VERSAL BIT(2) |
e3296f19c gpio: Added zynq ... |
101 |
|
e11de4de2 gpio: zynq: Add s... |
102 103 104 105 106 107 108 109 110 111 112 |
struct gpio_regs { u32 datamsw[ZYNQMP_GPIO_MAX_BANK]; u32 datalsw[ZYNQMP_GPIO_MAX_BANK]; u32 dirm[ZYNQMP_GPIO_MAX_BANK]; u32 outen[ZYNQMP_GPIO_MAX_BANK]; u32 int_en[ZYNQMP_GPIO_MAX_BANK]; u32 int_dis[ZYNQMP_GPIO_MAX_BANK]; u32 int_type[ZYNQMP_GPIO_MAX_BANK]; u32 int_polarity[ZYNQMP_GPIO_MAX_BANK]; u32 int_any[ZYNQMP_GPIO_MAX_BANK]; }; |
eb73d6eaa gpio: zynq: Fix e... |
113 |
|
3242ba117 gpio: Add driver ... |
114 115 116 117 118 |
/** * 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... |
119 |
* @irq: interrupt for the GPIO device |
bdf7a4ae3 gpio: Added suppo... |
120 |
* @p_data: pointer to platform data |
e11de4de2 gpio: zynq: Add s... |
121 |
* @context: context registers |
fdcfec11b gpio: zynq: prote... |
122 |
* @dirlock: lock used for direction in/out synchronization |
3242ba117 gpio: Add driver ... |
123 124 125 126 127 |
*/ struct zynq_gpio { struct gpio_chip chip; void __iomem *base_addr; struct clk *clk; |
59e22114b gpio: zynq: Fixed... |
128 |
int irq; |
bdf7a4ae3 gpio: Added suppo... |
129 |
const struct zynq_platform_data *p_data; |
e11de4de2 gpio: zynq: Add s... |
130 |
struct gpio_regs context; |
fdcfec11b gpio: zynq: prote... |
131 |
spinlock_t dirlock; /* lock */ |
bdf7a4ae3 gpio: Added suppo... |
132 133 134 135 136 |
}; /** * struct zynq_platform_data - zynq gpio platform data structure * @label: string to store in gpio->label |
6ae5104cb gpio: zynq: Fix k... |
137 |
* @quirks: Flags is used to identify the platform |
bdf7a4ae3 gpio: Added suppo... |
138 139 140 141 |
* @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 |
6ae5104cb gpio: zynq: Fix k... |
142 |
*/ |
bdf7a4ae3 gpio: Added suppo... |
143 144 |
struct zynq_platform_data { const char *label; |
e3296f19c gpio: Added zynq ... |
145 |
u32 quirks; |
bdf7a4ae3 gpio: Added suppo... |
146 147 148 149 |
u16 ngpio; int max_bank; int bank_min[ZYNQMP_GPIO_MAX_BANK]; int bank_max[ZYNQMP_GPIO_MAX_BANK]; |
3242ba117 gpio: Add driver ... |
150 |
}; |
6dd859508 gpio: zynq: Fix I... |
151 152 |
static struct irq_chip zynq_gpio_level_irqchip; static struct irq_chip zynq_gpio_edge_irqchip; |
fa9795d11 gpio: zynq: use c... |
153 |
|
3242ba117 gpio: Add driver ... |
154 |
/** |
3638bd4a0 gpio: zynq: Clari... |
155 156 157 158 159 160 161 162 163 164 165 |
* zynq_gpio_is_zynq - test if HW is zynq or zynqmp * @gpio: Pointer to driver data struct * * Return: 0 if zynqmp, 1 if zynq. */ static int zynq_gpio_is_zynq(struct zynq_gpio *gpio) { return !!(gpio->p_data->quirks & ZYNQ_GPIO_QUIRK_IS_ZYNQ); } /** |
06aa09081 gpio: zynq: Provi... |
166 167 168 169 170 171 172 173 174 175 176 |
* gpio_data_ro_bug - test if HW bug exists or not * @gpio: Pointer to driver data struct * * Return: 0 if bug doesnot exist, 1 if bug exists. */ static int gpio_data_ro_bug(struct zynq_gpio *gpio) { return !!(gpio->p_data->quirks & GPIO_QUIRK_DATA_RO_BUG); } /** |
3242ba117 gpio: Add driver ... |
177 178 179 180 181 182 183 |
* 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 |
6ae5104cb gpio: zynq: Fix k... |
184 |
* @gpio: gpio device data structure |
3242ba117 gpio: Add driver ... |
185 186 187 188 189 |
* * 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... |
190 191 |
unsigned int *bank_pin_num, struct zynq_gpio *gpio) |
3242ba117 gpio: Add driver ... |
192 |
{ |
bdf7a4ae3 gpio: Added suppo... |
193 194 195 196 |
int bank; for (bank = 0; bank < gpio->p_data->max_bank; bank++) { if ((pin_num >= gpio->p_data->bank_min[bank]) && |
16ee62e56 gpio: zynq: Fix d... |
197 |
(pin_num <= gpio->p_data->bank_max[bank])) { |
2717cfcaf gpio: zynq: Fix w... |
198 199 200 201 |
*bank_num = bank; *bank_pin_num = pin_num - gpio->p_data->bank_min[bank]; return; |
bdf7a4ae3 gpio: Added suppo... |
202 |
} |
675002448 gpio: zynq: Add V... |
203 204 |
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) bank = bank + VERSAL_UNUSED_BANKS; |
3242ba117 gpio: Add driver ... |
205 |
} |
3242ba117 gpio: Add driver ... |
206 |
|
bdf7a4ae3 gpio: Added suppo... |
207 208 209 210 211 |
/* default */ WARN(true, "invalid GPIO pin number: %u", pin_num); *bank_num = 0; *bank_pin_num = 0; } |
016da1443 gpio: zynq: Take ... |
212 |
|
3242ba117 gpio: Add driver ... |
213 214 215 216 217 218 219 220 221 222 223 224 225 |
/** * 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... |
226 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
227 |
|
bdf7a4ae3 gpio: Added suppo... |
228 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
229 |
|
06aa09081 gpio: zynq: Provi... |
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
if (gpio_data_ro_bug(gpio)) { if (zynq_gpio_is_zynq(gpio)) { if (bank_num <= 1) { data = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); } else { data = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_OFFSET(bank_num)); } } else { if (bank_num <= 2) { data = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); } else { data = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_OFFSET(bank_num)); } } } else { data = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); } |
3242ba117 gpio: Add driver ... |
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
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... |
269 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
270 |
|
bdf7a4ae3 gpio: Added suppo... |
271 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
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; unsigned int bank_num, bank_pin_num; |
fdcfec11b gpio: zynq: prote... |
306 |
unsigned long flags; |
31a894475 gpio: zynq: use g... |
307 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
308 |
|
bdf7a4ae3 gpio: Added suppo... |
309 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
310 |
|
e3296f19c gpio: Added zynq ... |
311 312 313 314 |
/* * On zynq bank 0 pins 7 and 8 are special and cannot be used * as inputs. */ |
3638bd4a0 gpio: zynq: Clari... |
315 |
if (zynq_gpio_is_zynq(gpio) && bank_num == 0 && |
16ee62e56 gpio: zynq: Fix d... |
316 |
(bank_pin_num == 7 || bank_pin_num == 8)) |
3242ba117 gpio: Add driver ... |
317 318 319 |
return -EINVAL; /* clear the bit in direction mode reg to set the pin as input */ |
fdcfec11b gpio: zynq: prote... |
320 |
spin_lock_irqsave(&gpio->dirlock, flags); |
3242ba117 gpio: Add driver ... |
321 322 323 |
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)); |
fdcfec11b gpio: zynq: prote... |
324 |
spin_unlock_irqrestore(&gpio->dirlock, flags); |
3242ba117 gpio: Add driver ... |
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
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; |
fdcfec11b gpio: zynq: prote... |
346 |
unsigned long flags; |
31a894475 gpio: zynq: use g... |
347 |
struct zynq_gpio *gpio = gpiochip_get_data(chip); |
3242ba117 gpio: Add driver ... |
348 |
|
bdf7a4ae3 gpio: Added suppo... |
349 |
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
350 351 |
/* set the GPIO pin as output */ |
fdcfec11b gpio: zynq: prote... |
352 |
spin_lock_irqsave(&gpio->dirlock, flags); |
3242ba117 gpio: Add driver ... |
353 354 355 356 357 358 359 360 |
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)); |
fdcfec11b gpio: zynq: prote... |
361 |
spin_unlock_irqrestore(&gpio->dirlock, flags); |
3242ba117 gpio: Add driver ... |
362 363 364 365 366 367 368 |
/* set the state of the pin */ zynq_gpio_set_value(chip, pin, state); return 0; } /** |
6169005ce gpio: zynq: Repor... |
369 370 371 372 373 374 |
* zynq_gpio_get_direction - Read the direction of the specified GPIO pin * @chip: gpio_chip instance to be worked on * @pin: gpio pin number within the device * * This function returns the direction of the specified GPIO. * |
e42615ec2 gpio: Use new GPI... |
375 |
* Return: GPIO_LINE_DIRECTION_OUT or GPIO_LINE_DIRECTION_IN |
6169005ce gpio: zynq: Repor... |
376 377 378 379 380 381 382 383 384 385 |
*/ static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) { u32 reg; unsigned int bank_num, bank_pin_num; struct zynq_gpio *gpio = gpiochip_get_data(chip); zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
e42615ec2 gpio: Use new GPI... |
386 387 388 389 |
if (reg & BIT(bank_pin_num)) return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_IN; |
6169005ce gpio: zynq: Repor... |
390 391 392 |
} /** |
3242ba117 gpio: Add driver ... |
393 394 395 396 397 398 399 400 401 402 |
* 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... |
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 |
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... |
424 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
425 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
3242ba117 gpio: Add driver ... |
426 427 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
428 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
429 430 431 432 433 |
writel_relaxed(BIT(bank_pin_num), gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num)); } /** |
190dc2e68 gpio: zynq: Clear... |
434 435 436 437 438 439 440 441 442 443 |
* 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... |
444 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
445 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
190dc2e68 gpio: zynq: Clear... |
446 447 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
448 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
190dc2e68 gpio: zynq: Clear... |
449 450 451 452 453 454 455 456 457 |
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... |
458 |
* Clears the INTSTS bit and unmasks the given interrupt. |
190dc2e68 gpio: zynq: Clear... |
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
*/ 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 ... |
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
* 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... |
495 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
496 |
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); |
3242ba117 gpio: Add driver ... |
497 498 |
device_pin_num = irq_data->hwirq; |
bdf7a4ae3 gpio: Added suppo... |
499 |
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); |
3242ba117 gpio: Add driver ... |
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
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... |
545 |
|
16ee62e56 gpio: zynq: Fix d... |
546 |
if (type & IRQ_TYPE_LEVEL_MASK) |
47c084629 gpio/zynq: Use ir... |
547 |
irq_set_chip_handler_name_locked(irq_data, |
16ee62e56 gpio: zynq: Fix d... |
548 549 550 |
&zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL); else |
47c084629 gpio/zynq: Use ir... |
551 |
irq_set_chip_handler_name_locked(irq_data, |
16ee62e56 gpio: zynq: Fix d... |
552 553 |
&zynq_gpio_edge_irqchip, handle_level_irq, NULL); |
6dd859508 gpio: zynq: Fix I... |
554 |
|
3242ba117 gpio: Add driver ... |
555 556 557 558 559 |
return 0; } static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) { |
fa9795d11 gpio: zynq: use c... |
560 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
561 |
gpiochip_get_data(irq_data_get_irq_chip_data(data)); |
59e22114b gpio: zynq: Fixed... |
562 563 |
irq_set_irq_wake(gpio->irq, on); |
3242ba117 gpio: Add driver ... |
564 565 566 |
return 0; } |
c2df3de0d gpio: zynq: prope... |
567 568 569 570 |
static int zynq_gpio_irq_reqres(struct irq_data *d) { struct gpio_chip *chip = irq_data_get_irq_chip_data(d); int ret; |
7f57b295f gpio: zynq: fix r... |
571 |
ret = pm_runtime_resume_and_get(chip->parent); |
c2df3de0d gpio: zynq: prope... |
572 573 574 575 576 577 578 579 580 581 582 583 584 |
if (ret < 0) return ret; return gpiochip_reqres_irq(chip, d->hwirq); } static void zynq_gpio_irq_relres(struct irq_data *d) { struct gpio_chip *chip = irq_data_get_irq_chip_data(d); gpiochip_relres_irq(chip, d->hwirq); pm_runtime_put(chip->parent); } |
3242ba117 gpio: Add driver ... |
585 |
/* irq chip descriptor */ |
6dd859508 gpio: zynq: Fix I... |
586 |
static struct irq_chip zynq_gpio_level_irqchip = { |
3242ba117 gpio: Add driver ... |
587 |
.name = DRIVER_NAME, |
190dc2e68 gpio: zynq: Clear... |
588 |
.irq_enable = zynq_gpio_irq_enable, |
6dd859508 gpio: zynq: Fix I... |
589 590 591 592 593 |
.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, |
c2df3de0d gpio: zynq: prope... |
594 595 |
.irq_request_resources = zynq_gpio_irq_reqres, .irq_release_resources = zynq_gpio_irq_relres, |
a19467788 gpio: zynq: Mask ... |
596 597 |
.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | IRQCHIP_MASK_ON_SUSPEND, |
6dd859508 gpio: zynq: Fix I... |
598 599 600 601 602 603 |
}; 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 ... |
604 605 606 607 |
.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, |
c2df3de0d gpio: zynq: prope... |
608 609 |
.irq_request_resources = zynq_gpio_irq_reqres, .irq_release_resources = zynq_gpio_irq_relres, |
a19467788 gpio: zynq: Mask ... |
610 |
.flags = IRQCHIP_MASK_ON_SUSPEND, |
3242ba117 gpio: Add driver ... |
611 |
}; |
5a2533a74 gpio: zynq: Reduc... |
612 613 614 615 |
static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, unsigned int bank_num, unsigned long pending) { |
bdf7a4ae3 gpio: Added suppo... |
616 |
unsigned int bank_offset = gpio->p_data->bank_min[bank_num]; |
f0fbe7bce gpio: Move irqdom... |
617 |
struct irq_domain *irqdomain = gpio->chip.irq.domain; |
5a2533a74 gpio: zynq: Reduc... |
618 619 620 621 622 623 624 |
int offset; if (!pending) return; for_each_set_bit(offset, &pending, 32) { unsigned int gpio_irq; |
016da1443 gpio: zynq: Take ... |
625 |
gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset); |
5a2533a74 gpio: zynq: Reduc... |
626 627 628 |
generic_handle_irq(gpio_irq); } } |
3242ba117 gpio: Add driver ... |
629 630 |
/** * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device |
3242ba117 gpio: Add driver ... |
631 632 633 634 635 636 637 638 |
* @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... |
639 |
static void zynq_gpio_irqhandler(struct irq_desc *desc) |
3242ba117 gpio: Add driver ... |
640 641 642 |
{ u32 int_sts, int_enb; unsigned int bank_num; |
fa9795d11 gpio: zynq: use c... |
643 |
struct zynq_gpio *gpio = |
31a894475 gpio: zynq: use g... |
644 |
gpiochip_get_data(irq_desc_get_handler_data(desc)); |
3242ba117 gpio: Add driver ... |
645 646 647 |
struct irq_chip *irqchip = irq_desc_get_chip(desc); chained_irq_enter(irqchip, desc); |
bdf7a4ae3 gpio: Added suppo... |
648 |
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { |
3242ba117 gpio: Add driver ... |
649 650 651 652 |
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... |
653 |
zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb); |
675002448 gpio: zynq: Add V... |
654 655 |
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) bank_num = bank_num + VERSAL_UNUSED_BANKS; |
3242ba117 gpio: Add driver ... |
656 657 658 659 |
} chained_irq_exit(irqchip, desc); } |
e11de4de2 gpio: zynq: Add s... |
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
static void zynq_gpio_save_context(struct zynq_gpio *gpio) { unsigned int bank_num; for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { gpio->context.datalsw[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num)); gpio->context.datamsw[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num)); gpio->context.dirm[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); gpio->context.int_en[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); gpio->context.int_type[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); gpio->context.int_polarity[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num)); gpio->context.int_any[bank_num] = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); |
675002448 gpio: zynq: Add V... |
684 685 |
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) bank_num = bank_num + VERSAL_UNUSED_BANKS; |
e11de4de2 gpio: zynq: Add s... |
686 687 688 689 690 691 692 693 |
} } static void zynq_gpio_restore_context(struct zynq_gpio *gpio) { unsigned int bank_num; for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { |
36f2e7207 gpio: zynq: Fix f... |
694 695 |
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); |
e11de4de2 gpio: zynq: Add s... |
696 697 698 699 700 701 702 703 704 |
writel_relaxed(gpio->context.datalsw[bank_num], gpio->base_addr + ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num)); writel_relaxed(gpio->context.datamsw[bank_num], gpio->base_addr + ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num)); writel_relaxed(gpio->context.dirm[bank_num], gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
e11de4de2 gpio: zynq: Add s... |
705 706 707 708 709 710 711 712 713 |
writel_relaxed(gpio->context.int_type[bank_num], gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); writel_relaxed(gpio->context.int_polarity[bank_num], gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num)); writel_relaxed(gpio->context.int_any[bank_num], gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); |
36f2e7207 gpio: zynq: Fix f... |
714 715 716 |
writel_relaxed(~(gpio->context.int_en[bank_num]), gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num)); |
675002448 gpio: zynq: Add V... |
717 718 |
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) bank_num = bank_num + VERSAL_UNUSED_BANKS; |
e11de4de2 gpio: zynq: Add s... |
719 720 |
} } |
eb73d6eaa gpio: zynq: Fix e... |
721 |
|
3242ba117 gpio: Add driver ... |
722 723 |
static int __maybe_unused zynq_gpio_suspend(struct device *dev) { |
a76e865ee gpio: zynq: simpl... |
724 |
struct zynq_gpio *gpio = dev_get_drvdata(dev); |
5e3a8ecd7 gpio: zynq: Remov... |
725 |
struct irq_data *data = irq_get_irq_data(gpio->irq); |
59e22114b gpio: zynq: Fixed... |
726 |
|
26ebdbf8c gpio: zynq: Disab... |
727 728 |
if (!device_may_wakeup(dev)) disable_irq(gpio->irq); |
e11de4de2 gpio: zynq: Add s... |
729 730 |
if (!irqd_is_wakeup_set(data)) { zynq_gpio_save_context(gpio); |
3242ba117 gpio: Add driver ... |
731 |
return pm_runtime_force_suspend(dev); |
e11de4de2 gpio: zynq: Add s... |
732 |
} |
3242ba117 gpio: Add driver ... |
733 734 735 736 737 738 |
return 0; } static int __maybe_unused zynq_gpio_resume(struct device *dev) { |
a76e865ee gpio: zynq: simpl... |
739 |
struct zynq_gpio *gpio = dev_get_drvdata(dev); |
5e3a8ecd7 gpio: zynq: Remov... |
740 |
struct irq_data *data = irq_get_irq_data(gpio->irq); |
e11de4de2 gpio: zynq: Add s... |
741 |
int ret; |
59e22114b gpio: zynq: Fixed... |
742 |
|
26ebdbf8c gpio: zynq: Disab... |
743 744 |
if (!device_may_wakeup(dev)) enable_irq(gpio->irq); |
e11de4de2 gpio: zynq: Add s... |
745 746 747 748 749 |
if (!irqd_is_wakeup_set(data)) { ret = pm_runtime_force_resume(dev); zynq_gpio_restore_context(gpio); return ret; } |
3242ba117 gpio: Add driver ... |
750 751 752 753 754 755 |
return 0; } static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev) { |
38ccad024 gpio: gpio-zynq: ... |
756 |
struct zynq_gpio *gpio = dev_get_drvdata(dev); |
3242ba117 gpio: Add driver ... |
757 758 759 760 761 762 763 764 |
clk_disable_unprepare(gpio->clk); return 0; } static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev) { |
38ccad024 gpio: gpio-zynq: ... |
765 |
struct zynq_gpio *gpio = dev_get_drvdata(dev); |
3242ba117 gpio: Add driver ... |
766 767 768 |
return clk_prepare_enable(gpio->clk); } |
2717cfcaf gpio: zynq: Fix w... |
769 |
static int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset) |
3242ba117 gpio: Add driver ... |
770 771 |
{ int ret; |
58383c784 gpio: change memb... |
772 |
ret = pm_runtime_get_sync(chip->parent); |
3242ba117 gpio: Add driver ... |
773 774 775 776 777 778 779 |
/* * 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; } |
2717cfcaf gpio: zynq: Fix w... |
780 |
static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset) |
3242ba117 gpio: Add driver ... |
781 |
{ |
58383c784 gpio: change memb... |
782 |
pm_runtime_put(chip->parent); |
3242ba117 gpio: Add driver ... |
783 784 785 786 |
} 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... |
787 |
SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, |
16ee62e56 gpio: zynq: Fix d... |
788 |
zynq_gpio_runtime_resume, NULL) |
3242ba117 gpio: Add driver ... |
789 |
}; |
675002448 gpio: zynq: Add V... |
790 791 792 793 794 795 796 797 798 799 |
static const struct zynq_platform_data versal_gpio_def = { .label = "versal_gpio", .quirks = GPIO_QUIRK_VERSAL, .ngpio = 58, .max_bank = VERSAL_GPIO_MAX_BANK, .bank_min[0] = 0, .bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */ .bank_min[3] = 26, .bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */ }; |
73c612fe2 gpio: zynq: Add p... |
800 801 802 803 804 805 806 807 808 809 810 811 812 |
static const struct zynq_platform_data pmc_gpio_def = { .label = "pmc_gpio", .ngpio = 116, .max_bank = PMC_GPIO_MAX_BANK, .bank_min[0] = 0, .bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */ .bank_min[1] = 26, .bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */ .bank_min[3] = 52, .bank_max[3] = 83, /* Bank 3 is connected to EMIOs (32 pins) */ .bank_min[4] = 84, .bank_max[4] = 115, /* Bank 4 is connected to EMIOs (32 pins) */ }; |
bdf7a4ae3 gpio: Added suppo... |
813 814 |
static const struct zynq_platform_data zynqmp_gpio_def = { .label = "zynqmp_gpio", |
06aa09081 gpio: zynq: Provi... |
815 |
.quirks = GPIO_QUIRK_DATA_RO_BUG, |
bdf7a4ae3 gpio: Added suppo... |
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 |
.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", |
06aa09081 gpio: zynq: Provi... |
834 |
.quirks = ZYNQ_GPIO_QUIRK_IS_ZYNQ | GPIO_QUIRK_DATA_RO_BUG, |
bdf7a4ae3 gpio: Added suppo... |
835 836 837 838 839 840 841 842 843 844 845 846 847 |
.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[] = { |
7808c42b4 gpio: zynq: remov... |
848 849 |
{ .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def }, { .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def }, |
675002448 gpio: zynq: Add V... |
850 |
{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def }, |
73c612fe2 gpio: zynq: Add p... |
851 |
{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def }, |
bdf7a4ae3 gpio: Added suppo... |
852 853 854 |
{ /* end of table */ } }; MODULE_DEVICE_TABLE(of, zynq_gpio_of_match); |
3242ba117 gpio: Add driver ... |
855 856 857 858 859 860 861 862 863 864 865 866 867 |
/** * 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... |
868 |
int ret, bank_num; |
3242ba117 gpio: Add driver ... |
869 870 |
struct zynq_gpio *gpio; struct gpio_chip *chip; |
f6a7053dd gpio: zynq: Pass ... |
871 |
struct gpio_irq_chip *girq; |
bdf7a4ae3 gpio: Added suppo... |
872 |
const struct of_device_id *match; |
3242ba117 gpio: Add driver ... |
873 874 875 876 |
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; |
bdf7a4ae3 gpio: Added suppo... |
877 878 879 880 881 882 883 |
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 ... |
884 |
platform_set_drvdata(pdev, gpio); |
77bc0e69c gpio: zynq: use d... |
885 |
gpio->base_addr = devm_platform_ioremap_resource(pdev, 0); |
3242ba117 gpio: Add driver ... |
886 887 |
if (IS_ERR(gpio->base_addr)) return PTR_ERR(gpio->base_addr); |
59e22114b gpio: zynq: Fixed... |
888 |
gpio->irq = platform_get_irq(pdev, 0); |
15bddb7d7 gpio: Remove dev_... |
889 |
if (gpio->irq < 0) |
59e22114b gpio: zynq: Fixed... |
890 |
return gpio->irq; |
3242ba117 gpio: Add driver ... |
891 892 893 |
/* configure the gpio chip */ chip = &gpio->chip; |
bdf7a4ae3 gpio: Added suppo... |
894 |
chip->label = gpio->p_data->label; |
3242ba117 gpio: Add driver ... |
895 |
chip->owner = THIS_MODULE; |
58383c784 gpio: change memb... |
896 |
chip->parent = &pdev->dev; |
3242ba117 gpio: Add driver ... |
897 898 899 900 901 902 |
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; |
6169005ce gpio: zynq: Repor... |
903 |
chip->get_direction = zynq_gpio_get_direction; |
060f3ebf6 gpio: zynq: Setup... |
904 |
chip->base = of_alias_get_id(pdev->dev.of_node, "gpio"); |
bdf7a4ae3 gpio: Added suppo... |
905 |
chip->ngpio = gpio->p_data->ngpio; |
3242ba117 gpio: Add driver ... |
906 |
|
3773c195d gpio: zynq: Do PM... |
907 |
/* Retrieve GPIO clock */ |
3242ba117 gpio: Add driver ... |
908 |
gpio->clk = devm_clk_get(&pdev->dev, NULL); |
805a6ef8a gpio: zynq: Simpl... |
909 910 911 |
if (IS_ERR(gpio->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(gpio->clk), "input clock not found. "); |
0f84f29ff gpio: zynq: initi... |
912 913 914 915 916 917 |
ret = clk_prepare_enable(gpio->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock. "); return ret; } |
3773c195d gpio: zynq: Do PM... |
918 |
|
fdcfec11b gpio: zynq: prote... |
919 |
spin_lock_init(&gpio->dirlock); |
0f84f29ff gpio: zynq: initi... |
920 |
pm_runtime_set_active(&pdev->dev); |
3773c195d gpio: zynq: Do PM... |
921 |
pm_runtime_enable(&pdev->dev); |
7f57b295f gpio: zynq: fix r... |
922 |
ret = pm_runtime_resume_and_get(&pdev->dev); |
3773c195d gpio: zynq: Do PM... |
923 |
if (ret < 0) |
615d23f80 gpio: zynq: Fix t... |
924 |
goto err_pm_dis; |
3242ba117 gpio: Add driver ... |
925 |
|
3242ba117 gpio: Add driver ... |
926 |
/* disable interrupts for all banks */ |
675002448 gpio: zynq: Add V... |
927 |
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { |
3242ba117 gpio: Add driver ... |
928 929 |
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); |
675002448 gpio: zynq: Add V... |
930 931 932 |
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) bank_num = bank_num + VERSAL_UNUSED_BANKS; } |
3242ba117 gpio: Add driver ... |
933 |
|
f6a7053dd gpio: zynq: Pass ... |
934 935 936 937 938 939 940 941 942 943 944 |
/* Set up the GPIO irqchip */ girq = &chip->irq; girq->chip = &zynq_gpio_edge_irqchip; girq->parent_handler = zynq_gpio_irqhandler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL); if (!girq->parents) { ret = -ENOMEM; goto err_pm_put; |
3242ba117 gpio: Add driver ... |
945 |
} |
f6a7053dd gpio: zynq: Pass ... |
946 947 948 |
girq->parents[0] = gpio->irq; girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; |
3242ba117 gpio: Add driver ... |
949 |
|
f6a7053dd gpio: zynq: Pass ... |
950 951 952 953 954 955 956 |
/* report a bug if gpio chip registration fails */ ret = gpiochip_add_data(chip, gpio); if (ret) { dev_err(&pdev->dev, "Failed to add gpio chip "); goto err_pm_put; } |
3242ba117 gpio: Add driver ... |
957 |
|
26ebdbf8c gpio: zynq: Disab... |
958 959 |
irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY); device_init_wakeup(&pdev->dev, 1); |
3773c195d gpio: zynq: Do PM... |
960 |
pm_runtime_put(&pdev->dev); |
3242ba117 gpio: Add driver ... |
961 |
|
3242ba117 gpio: Add driver ... |
962 |
return 0; |
3773c195d gpio: zynq: Do PM... |
963 964 |
err_pm_put: pm_runtime_put(&pdev->dev); |
615d23f80 gpio: zynq: Fix t... |
965 966 |
err_pm_dis: pm_runtime_disable(&pdev->dev); |
0f84f29ff gpio: zynq: initi... |
967 |
clk_disable_unprepare(gpio->clk); |
3242ba117 gpio: Add driver ... |
968 969 970 971 972 973 974 975 976 977 978 979 |
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 ... |
980 981 982 |
struct zynq_gpio *gpio = platform_get_drvdata(pdev); pm_runtime_get_sync(&pdev->dev); |
da26d5d80 gpio: remove rema... |
983 |
gpiochip_remove(&gpio->chip); |
3242ba117 gpio: Add driver ... |
984 985 |
clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); |
6b956af08 gpio: zynq: Fix p... |
986 |
pm_runtime_disable(&pdev->dev); |
3242ba117 gpio: Add driver ... |
987 988 |
return 0; } |
3242ba117 gpio: Add driver ... |
989 990 991 |
static struct platform_driver zynq_gpio_driver = { .driver = { .name = DRIVER_NAME, |
3242ba117 gpio: Add driver ... |
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
.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... |
1009 1010 1011 1012 1013 |
static void __exit zynq_gpio_exit(void) { platform_driver_unregister(&zynq_gpio_driver); } module_exit(zynq_gpio_exit); |
3242ba117 gpio: Add driver ... |
1014 1015 1016 |
MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); MODULE_LICENSE("GPL"); |