Blame view

drivers/gpio/gpio-zynq.c 31.4 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
3242ba117   Harini Katakam   gpio: Add driver ...
2
3
4
5
  /*
   * Xilinx Zynq GPIO device driver
   *
   * Copyright (C) 2009 - 2014 Xilinx, Inc.
3242ba117   Harini Katakam   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   Glenn Langedock   gpio: zynq: prote...
13
  #include <linux/spinlock.h>
3242ba117   Harini Katakam   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   Anurag Kumar Vulisha   gpio: Added suppo...
18
  #include <linux/of.h>
3242ba117   Harini Katakam   gpio: Add driver ...
19
20
21
22
23
  
  #define DRIVER_NAME "zynq-gpio"
  
  /* Maximum banks */
  #define ZYNQ_GPIO_MAX_BANK	4
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
24
  #define ZYNQMP_GPIO_MAX_BANK	6
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
25
  #define VERSAL_GPIO_MAX_BANK	4
73c612fe2   Shubhrajyoti Datta   gpio: zynq: Add p...
26
  #define PMC_GPIO_MAX_BANK	5
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
27
  #define VERSAL_UNUSED_BANKS	2
3242ba117   Harini Katakam   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   Anurag Kumar Vulisha   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   Harini Katakam   gpio: Add driver ...
61

3242ba117   Harini Katakam   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   Swapna Manupati   gpio: zynq: Provi...
68
  #define ZYNQ_GPIO_DATA_OFFSET(BANK)	(0x040 + (4 * BANK))
3242ba117   Harini Katakam   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   Soren Brinkmann   gpio: zynq: Clari...
97
98
  /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
  #define ZYNQ_GPIO_QUIRK_IS_ZYNQ	BIT(0)
06aa09081   Swapna Manupati   gpio: zynq: Provi...
99
  #define GPIO_QUIRK_DATA_RO_BUG	BIT(1)
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
100
  #define GPIO_QUIRK_VERSAL	BIT(2)
e3296f19c   Nava kishore Manne   gpio: Added zynq ...
101

e11de4de2   Shubhrajyoti Datta   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   Michal Simek   gpio: zynq: Fix e...
113

3242ba117   Harini Katakam   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   Ezra Savard   gpio: zynq: Fixed...
119
   * @irq:	interrupt for the GPIO device
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
120
   * @p_data:	pointer to platform data
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
121
   * @context:	context registers
fdcfec11b   Glenn Langedock   gpio: zynq: prote...
122
   * @dirlock:	lock used for direction in/out synchronization
3242ba117   Harini Katakam   gpio: Add driver ...
123
124
125
126
127
   */
  struct zynq_gpio {
  	struct gpio_chip chip;
  	void __iomem *base_addr;
  	struct clk *clk;
59e22114b   Ezra Savard   gpio: zynq: Fixed...
128
  	int irq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
129
  	const struct zynq_platform_data *p_data;
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
130
  	struct gpio_regs context;
fdcfec11b   Glenn Langedock   gpio: zynq: prote...
131
  	spinlock_t dirlock; /* lock */
bdf7a4ae3   Anurag Kumar Vulisha   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   Nava kishore Manne   gpio: zynq: Fix k...
137
   * @quirks:	Flags is used to identify the platform
bdf7a4ae3   Anurag Kumar Vulisha   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   Nava kishore Manne   gpio: zynq: Fix k...
142
   */
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
143
144
  struct zynq_platform_data {
  	const char *label;
e3296f19c   Nava kishore Manne   gpio: Added zynq ...
145
  	u32 quirks;
bdf7a4ae3   Anurag Kumar Vulisha   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   Harini Katakam   gpio: Add driver ...
150
  };
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
151
152
  static struct irq_chip zynq_gpio_level_irqchip;
  static struct irq_chip zynq_gpio_edge_irqchip;
fa9795d11   Linus Walleij   gpio: zynq: use c...
153

3242ba117   Harini Katakam   gpio: Add driver ...
154
  /**
3638bd4a0   Soren Brinkmann   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   Swapna Manupati   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   Harini Katakam   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   Nava kishore Manne   gpio: zynq: Fix k...
184
   * @gpio:	gpio device data structure
3242ba117   Harini Katakam   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   Anurag Kumar Vulisha   gpio: Added suppo...
190
191
  					  unsigned int *bank_pin_num,
  					  struct zynq_gpio *gpio)
3242ba117   Harini Katakam   gpio: Add driver ...
192
  {
bdf7a4ae3   Anurag Kumar Vulisha   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   Michal Simek   gpio: zynq: Fix d...
197
  		    (pin_num <= gpio->p_data->bank_max[bank])) {
2717cfcaf   Nava kishore Manne   gpio: zynq: Fix w...
198
199
200
201
  			*bank_num = bank;
  			*bank_pin_num = pin_num -
  					gpio->p_data->bank_min[bank];
  			return;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
202
  		}
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
203
204
  		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
  			bank = bank + VERSAL_UNUSED_BANKS;
3242ba117   Harini Katakam   gpio: Add driver ...
205
  	}
3242ba117   Harini Katakam   gpio: Add driver ...
206

bdf7a4ae3   Anurag Kumar Vulisha   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   Lars-Peter Clausen   gpio: zynq: Take ...
212

3242ba117   Harini Katakam   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   Linus Walleij   gpio: zynq: use g...
226
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
227

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
228
  	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
229

06aa09081   Swapna Manupati   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   Harini Katakam   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   Linus Walleij   gpio: zynq: use g...
269
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
270

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
271
  	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   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   Glenn Langedock   gpio: zynq: prote...
306
  	unsigned long flags;
31a894475   Linus Walleij   gpio: zynq: use g...
307
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
308

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
309
  	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
310

e3296f19c   Nava kishore Manne   gpio: Added zynq ...
311
312
313
314
  	/*
  	 * On zynq bank 0 pins 7 and 8 are special and cannot be used
  	 * as inputs.
  	 */
3638bd4a0   Soren Brinkmann   gpio: zynq: Clari...
315
  	if (zynq_gpio_is_zynq(gpio) && bank_num == 0 &&
16ee62e56   Michal Simek   gpio: zynq: Fix d...
316
  	    (bank_pin_num == 7 || bank_pin_num == 8))
3242ba117   Harini Katakam   gpio: Add driver ...
317
318
319
  		return -EINVAL;
  
  	/* clear the bit in direction mode reg to set the pin as input */
fdcfec11b   Glenn Langedock   gpio: zynq: prote...
320
  	spin_lock_irqsave(&gpio->dirlock, flags);
3242ba117   Harini Katakam   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   Glenn Langedock   gpio: zynq: prote...
324
  	spin_unlock_irqrestore(&gpio->dirlock, flags);
3242ba117   Harini Katakam   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   Glenn Langedock   gpio: zynq: prote...
346
  	unsigned long flags;
31a894475   Linus Walleij   gpio: zynq: use g...
347
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
348

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
349
  	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
350
351
  
  	/* set the GPIO pin as output */
fdcfec11b   Glenn Langedock   gpio: zynq: prote...
352
  	spin_lock_irqsave(&gpio->dirlock, flags);
3242ba117   Harini Katakam   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   Glenn Langedock   gpio: zynq: prote...
361
  	spin_unlock_irqrestore(&gpio->dirlock, flags);
3242ba117   Harini Katakam   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   Brandon Maier   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   Matti Vaittinen   gpio: Use new GPI...
375
   * Return: GPIO_LINE_DIRECTION_OUT or GPIO_LINE_DIRECTION_IN
6169005ce   Brandon Maier   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   Matti Vaittinen   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   Brandon Maier   gpio: zynq: Repor...
390
391
392
  }
  
  /**
3242ba117   Harini Katakam   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   Linus Walleij   gpio: zynq: use c...
403
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
404
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
3242ba117   Harini Katakam   gpio: Add driver ...
405
406
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
407
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   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   Linus Walleij   gpio: zynq: use c...
424
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
425
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
3242ba117   Harini Katakam   gpio: Add driver ...
426
427
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
428
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
429
430
431
432
433
  	writel_relaxed(BIT(bank_pin_num),
  		       gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num));
  }
  
  /**
190dc2e68   Lars-Peter Clausen   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   Linus Walleij   gpio: zynq: use c...
444
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
445
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
446
447
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
448
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
190dc2e68   Lars-Peter Clausen   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   Colin Cronin   Drivers: gpio: Fi...
458
   * Clears the INTSTS bit and unmasks the given interrupt.
190dc2e68   Lars-Peter Clausen   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   Harini Katakam   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   Linus Walleij   gpio: zynq: use c...
495
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
496
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
3242ba117   Harini Katakam   gpio: Add driver ...
497
498
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
499
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   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   Lars-Peter Clausen   gpio: zynq: Fix I...
545

16ee62e56   Michal Simek   gpio: zynq: Fix d...
546
  	if (type & IRQ_TYPE_LEVEL_MASK)
47c084629   Thomas Gleixner   gpio/zynq: Use ir...
547
  		irq_set_chip_handler_name_locked(irq_data,
16ee62e56   Michal Simek   gpio: zynq: Fix d...
548
549
550
  						 &zynq_gpio_level_irqchip,
  						 handle_fasteoi_irq, NULL);
  	else
47c084629   Thomas Gleixner   gpio/zynq: Use ir...
551
  		irq_set_chip_handler_name_locked(irq_data,
16ee62e56   Michal Simek   gpio: zynq: Fix d...
552
553
  						 &zynq_gpio_edge_irqchip,
  						 handle_level_irq, NULL);
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
554

3242ba117   Harini Katakam   gpio: Add driver ...
555
556
557
558
559
  	return 0;
  }
  
  static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
  {
fa9795d11   Linus Walleij   gpio: zynq: use c...
560
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
561
  		gpiochip_get_data(irq_data_get_irq_chip_data(data));
59e22114b   Ezra Savard   gpio: zynq: Fixed...
562
563
  
  	irq_set_irq_wake(gpio->irq, on);
3242ba117   Harini Katakam   gpio: Add driver ...
564
565
566
  
  	return 0;
  }
c2df3de0d   Thomas Petazzoni   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   Qinglang Miao   gpio: zynq: fix r...
571
  	ret = pm_runtime_resume_and_get(chip->parent);
c2df3de0d   Thomas Petazzoni   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   Harini Katakam   gpio: Add driver ...
585
  /* irq chip descriptor */
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
586
  static struct irq_chip zynq_gpio_level_irqchip = {
3242ba117   Harini Katakam   gpio: Add driver ...
587
  	.name		= DRIVER_NAME,
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
588
  	.irq_enable	= zynq_gpio_irq_enable,
6dd859508   Lars-Peter Clausen   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   Thomas Petazzoni   gpio: zynq: prope...
594
595
  	.irq_request_resources = zynq_gpio_irq_reqres,
  	.irq_release_resources = zynq_gpio_irq_relres,
a19467788   Ezra Savard   gpio: zynq: Mask ...
596
597
  	.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
  			  IRQCHIP_MASK_ON_SUSPEND,
6dd859508   Lars-Peter Clausen   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   Harini Katakam   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   Thomas Petazzoni   gpio: zynq: prope...
608
609
  	.irq_request_resources = zynq_gpio_irq_reqres,
  	.irq_release_resources = zynq_gpio_irq_relres,
a19467788   Ezra Savard   gpio: zynq: Mask ...
610
  	.flags		= IRQCHIP_MASK_ON_SUSPEND,
3242ba117   Harini Katakam   gpio: Add driver ...
611
  };
5a2533a74   Lars-Peter Clausen   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   Anurag Kumar Vulisha   gpio: Added suppo...
616
  	unsigned int bank_offset = gpio->p_data->bank_min[bank_num];
f0fbe7bce   Thierry Reding   gpio: Move irqdom...
617
  	struct irq_domain *irqdomain = gpio->chip.irq.domain;
5a2533a74   Lars-Peter Clausen   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   Lars-Peter Clausen   gpio: zynq: Take ...
625
  		gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset);
5a2533a74   Lars-Peter Clausen   gpio: zynq: Reduc...
626
627
628
  		generic_handle_irq(gpio_irq);
  	}
  }
3242ba117   Harini Katakam   gpio: Add driver ...
629
630
  /**
   * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device
3242ba117   Harini Katakam   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   Thomas Gleixner   genirq: Remove ir...
639
  static void zynq_gpio_irqhandler(struct irq_desc *desc)
3242ba117   Harini Katakam   gpio: Add driver ...
640
641
642
  {
  	u32 int_sts, int_enb;
  	unsigned int bank_num;
fa9795d11   Linus Walleij   gpio: zynq: use c...
643
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
644
  		gpiochip_get_data(irq_desc_get_handler_data(desc));
3242ba117   Harini Katakam   gpio: Add driver ...
645
646
647
  	struct irq_chip *irqchip = irq_desc_get_chip(desc);
  
  	chained_irq_enter(irqchip, desc);
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
648
  	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
3242ba117   Harini Katakam   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   Lars-Peter Clausen   gpio: zynq: Reduc...
653
  		zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
654
655
  		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
  			bank_num = bank_num + VERSAL_UNUSED_BANKS;
3242ba117   Harini Katakam   gpio: Add driver ...
656
657
658
659
  	}
  
  	chained_irq_exit(irqchip, desc);
  }
e11de4de2   Shubhrajyoti Datta   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   Shubhrajyoti Datta   gpio: zynq: Add V...
684
685
  		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
  			bank_num = bank_num + VERSAL_UNUSED_BANKS;
e11de4de2   Shubhrajyoti Datta   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   Swapna Manupati   gpio: zynq: Fix f...
694
695
  		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
  				ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
e11de4de2   Shubhrajyoti Datta   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   Shubhrajyoti Datta   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   Swapna Manupati   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   Shubhrajyoti Datta   gpio: zynq: Add V...
717
718
  		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
  			bank_num = bank_num + VERSAL_UNUSED_BANKS;
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
719
720
  	}
  }
eb73d6eaa   Michal Simek   gpio: zynq: Fix e...
721

3242ba117   Harini Katakam   gpio: Add driver ...
722
723
  static int __maybe_unused zynq_gpio_suspend(struct device *dev)
  {
a76e865ee   Shubhrajyoti Datta   gpio: zynq: simpl...
724
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
5e3a8ecd7   Shubhrajyoti Datta   gpio: zynq: Remov...
725
  	struct irq_data *data = irq_get_irq_data(gpio->irq);
59e22114b   Ezra Savard   gpio: zynq: Fixed...
726

26ebdbf8c   Shubhrajyoti Datta   gpio: zynq: Disab...
727
728
  	if (!device_may_wakeup(dev))
  		disable_irq(gpio->irq);
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
729
730
  	if (!irqd_is_wakeup_set(data)) {
  		zynq_gpio_save_context(gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
731
  		return pm_runtime_force_suspend(dev);
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
732
  	}
3242ba117   Harini Katakam   gpio: Add driver ...
733
734
735
736
737
738
  
  	return 0;
  }
  
  static int __maybe_unused zynq_gpio_resume(struct device *dev)
  {
a76e865ee   Shubhrajyoti Datta   gpio: zynq: simpl...
739
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
5e3a8ecd7   Shubhrajyoti Datta   gpio: zynq: Remov...
740
  	struct irq_data *data = irq_get_irq_data(gpio->irq);
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
741
  	int ret;
59e22114b   Ezra Savard   gpio: zynq: Fixed...
742

26ebdbf8c   Shubhrajyoti Datta   gpio: zynq: Disab...
743
744
  	if (!device_may_wakeup(dev))
  		enable_irq(gpio->irq);
e11de4de2   Shubhrajyoti Datta   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   Harini Katakam   gpio: Add driver ...
750
751
752
753
754
755
  
  	return 0;
  }
  
  static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev)
  {
38ccad024   Wolfram Sang   gpio: gpio-zynq: ...
756
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
3242ba117   Harini Katakam   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   Wolfram Sang   gpio: gpio-zynq: ...
765
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
3242ba117   Harini Katakam   gpio: Add driver ...
766
767
768
  
  	return clk_prepare_enable(gpio->clk);
  }
2717cfcaf   Nava kishore Manne   gpio: zynq: Fix w...
769
  static int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset)
3242ba117   Harini Katakam   gpio: Add driver ...
770
771
  {
  	int ret;
58383c784   Linus Walleij   gpio: change memb...
772
  	ret = pm_runtime_get_sync(chip->parent);
3242ba117   Harini Katakam   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   Nava kishore Manne   gpio: zynq: Fix w...
780
  static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset)
3242ba117   Harini Katakam   gpio: Add driver ...
781
  {
58383c784   Linus Walleij   gpio: change memb...
782
  	pm_runtime_put(chip->parent);
3242ba117   Harini Katakam   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   Rafael J. Wysocki   PM: Merge the SET...
787
  	SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
16ee62e56   Michal Simek   gpio: zynq: Fix d...
788
  			   zynq_gpio_runtime_resume, NULL)
3242ba117   Harini Katakam   gpio: Add driver ...
789
  };
675002448   Shubhrajyoti Datta   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   Shubhrajyoti Datta   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   Anurag Kumar Vulisha   gpio: Added suppo...
813
814
  static const struct zynq_platform_data zynqmp_gpio_def = {
  	.label = "zynqmp_gpio",
06aa09081   Swapna Manupati   gpio: zynq: Provi...
815
  	.quirks = GPIO_QUIRK_DATA_RO_BUG,
bdf7a4ae3   Anurag Kumar Vulisha   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   Swapna Manupati   gpio: zynq: Provi...
834
  	.quirks = ZYNQ_GPIO_QUIRK_IS_ZYNQ | GPIO_QUIRK_DATA_RO_BUG,
bdf7a4ae3   Anurag Kumar Vulisha   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   Masahiro Yamada   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   Shubhrajyoti Datta   gpio: zynq: Add V...
850
  	{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
73c612fe2   Shubhrajyoti Datta   gpio: zynq: Add p...
851
  	{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def },
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
852
853
854
  	{ /* end of table */ }
  };
  MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
3242ba117   Harini Katakam   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   Ezra Savard   gpio: zynq: Fixed...
868
  	int ret, bank_num;
3242ba117   Harini Katakam   gpio: Add driver ...
869
870
  	struct zynq_gpio *gpio;
  	struct gpio_chip *chip;
f6a7053dd   Linus Walleij   gpio: zynq: Pass ...
871
  	struct gpio_irq_chip *girq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
872
  	const struct of_device_id *match;
3242ba117   Harini Katakam   gpio: Add driver ...
873
874
875
876
  
  	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
  	if (!gpio)
  		return -ENOMEM;
bdf7a4ae3   Anurag Kumar Vulisha   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   Harini Katakam   gpio: Add driver ...
884
  	platform_set_drvdata(pdev, gpio);
77bc0e69c   Enrico Weigelt, metux IT consult   gpio: zynq: use d...
885
  	gpio->base_addr = devm_platform_ioremap_resource(pdev, 0);
3242ba117   Harini Katakam   gpio: Add driver ...
886
887
  	if (IS_ERR(gpio->base_addr))
  		return PTR_ERR(gpio->base_addr);
59e22114b   Ezra Savard   gpio: zynq: Fixed...
888
  	gpio->irq = platform_get_irq(pdev, 0);
15bddb7d7   Stephen Boyd   gpio: Remove dev_...
889
  	if (gpio->irq < 0)
59e22114b   Ezra Savard   gpio: zynq: Fixed...
890
  		return gpio->irq;
3242ba117   Harini Katakam   gpio: Add driver ...
891
892
893
  
  	/* configure the gpio chip */
  	chip = &gpio->chip;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
894
  	chip->label = gpio->p_data->label;
3242ba117   Harini Katakam   gpio: Add driver ...
895
  	chip->owner = THIS_MODULE;
58383c784   Linus Walleij   gpio: change memb...
896
  	chip->parent = &pdev->dev;
3242ba117   Harini Katakam   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   Brandon Maier   gpio: zynq: Repor...
903
  	chip->get_direction = zynq_gpio_get_direction;
060f3ebf6   Michal Simek   gpio: zynq: Setup...
904
  	chip->base = of_alias_get_id(pdev->dev.of_node, "gpio");
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
905
  	chip->ngpio = gpio->p_data->ngpio;
3242ba117   Harini Katakam   gpio: Add driver ...
906

3773c195d   Michal Simek   gpio: zynq: Do PM...
907
  	/* Retrieve GPIO clock */
3242ba117   Harini Katakam   gpio: Add driver ...
908
  	gpio->clk = devm_clk_get(&pdev->dev, NULL);
805a6ef8a   Krzysztof Kozlowski   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   Helmut Grohne   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   Michal Simek   gpio: zynq: Do PM...
918

fdcfec11b   Glenn Langedock   gpio: zynq: prote...
919
  	spin_lock_init(&gpio->dirlock);
0f84f29ff   Helmut Grohne   gpio: zynq: initi...
920
  	pm_runtime_set_active(&pdev->dev);
3773c195d   Michal Simek   gpio: zynq: Do PM...
921
  	pm_runtime_enable(&pdev->dev);
7f57b295f   Qinglang Miao   gpio: zynq: fix r...
922
  	ret = pm_runtime_resume_and_get(&pdev->dev);
3773c195d   Michal Simek   gpio: zynq: Do PM...
923
  	if (ret < 0)
615d23f80   Shubhrajyoti Datta   gpio: zynq: Fix t...
924
  		goto err_pm_dis;
3242ba117   Harini Katakam   gpio: Add driver ...
925

3242ba117   Harini Katakam   gpio: Add driver ...
926
  	/* disable interrupts for all banks */
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
927
  	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
3242ba117   Harini Katakam   gpio: Add driver ...
928
929
  		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
  			       ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
675002448   Shubhrajyoti Datta   gpio: zynq: Add V...
930
931
932
  		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
  			bank_num = bank_num + VERSAL_UNUSED_BANKS;
  	}
3242ba117   Harini Katakam   gpio: Add driver ...
933

f6a7053dd   Linus Walleij   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   Harini Katakam   gpio: Add driver ...
945
  	}
f6a7053dd   Linus Walleij   gpio: zynq: Pass ...
946
947
948
  	girq->parents[0] = gpio->irq;
  	girq->default_type = IRQ_TYPE_NONE;
  	girq->handler = handle_level_irq;
3242ba117   Harini Katakam   gpio: Add driver ...
949

f6a7053dd   Linus Walleij   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   Harini Katakam   gpio: Add driver ...
957

26ebdbf8c   Shubhrajyoti Datta   gpio: zynq: Disab...
958
959
  	irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY);
  	device_init_wakeup(&pdev->dev, 1);
3773c195d   Michal Simek   gpio: zynq: Do PM...
960
  	pm_runtime_put(&pdev->dev);
3242ba117   Harini Katakam   gpio: Add driver ...
961

3242ba117   Harini Katakam   gpio: Add driver ...
962
  	return 0;
3773c195d   Michal Simek   gpio: zynq: Do PM...
963
964
  err_pm_put:
  	pm_runtime_put(&pdev->dev);
615d23f80   Shubhrajyoti Datta   gpio: zynq: Fix t...
965
966
  err_pm_dis:
  	pm_runtime_disable(&pdev->dev);
0f84f29ff   Helmut Grohne   gpio: zynq: initi...
967
  	clk_disable_unprepare(gpio->clk);
3242ba117   Harini Katakam   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   Harini Katakam   gpio: Add driver ...
980
981
982
  	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
  
  	pm_runtime_get_sync(&pdev->dev);
da26d5d80   Linus Walleij   gpio: remove rema...
983
  	gpiochip_remove(&gpio->chip);
3242ba117   Harini Katakam   gpio: Add driver ...
984
985
  	clk_disable_unprepare(gpio->clk);
  	device_set_wakeup_capable(&pdev->dev, 0);
6b956af08   Michal Simek   gpio: zynq: Fix p...
986
  	pm_runtime_disable(&pdev->dev);
3242ba117   Harini Katakam   gpio: Add driver ...
987
988
  	return 0;
  }
3242ba117   Harini Katakam   gpio: Add driver ...
989
990
991
  static struct platform_driver zynq_gpio_driver = {
  	.driver	= {
  		.name = DRIVER_NAME,
3242ba117   Harini Katakam   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   Masahiro Yamada   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   Harini Katakam   gpio: Add driver ...
1014
1015
1016
  MODULE_AUTHOR("Xilinx Inc.");
  MODULE_DESCRIPTION("Zynq GPIO driver");
  MODULE_LICENSE("GPL");