Blame view

drivers/gpio/gpio-zynq.c 29.2 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
13
14
15
16
   */
  
  #include <linux/bitops.h>
  #include <linux/clk.h>
  #include <linux/gpio/driver.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/pm_runtime.h>
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
17
  #include <linux/of.h>
3242ba117   Harini Katakam   gpio: Add driver ...
18
19
20
21
22
  
  #define DRIVER_NAME "zynq-gpio"
  
  /* Maximum banks */
  #define ZYNQ_GPIO_MAX_BANK	4
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
23
  #define ZYNQMP_GPIO_MAX_BANK	6
3242ba117   Harini Katakam   gpio: Add driver ...
24
25
26
27
28
  
  #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...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  #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 ...
57

3242ba117   Harini Katakam   gpio: Add driver ...
58
59
60
61
62
63
  /* 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...
64
  #define ZYNQ_GPIO_DATA_OFFSET(BANK)	(0x040 + (4 * BANK))
3242ba117   Harini Katakam   gpio: Add driver ...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  #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...
93
94
  /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
  #define ZYNQ_GPIO_QUIRK_IS_ZYNQ	BIT(0)
06aa09081   Swapna Manupati   gpio: zynq: Provi...
95
  #define GPIO_QUIRK_DATA_RO_BUG	BIT(1)
e3296f19c   Nava kishore Manne   gpio: Added zynq ...
96

e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
97
98
99
100
101
102
103
104
105
106
107
  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...
108

3242ba117   Harini Katakam   gpio: Add driver ...
109
110
111
112
113
  /**
   * 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...
114
   * @irq:	interrupt for the GPIO device
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
115
   * @p_data:	pointer to platform data
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
116
   * @context:	context registers
3242ba117   Harini Katakam   gpio: Add driver ...
117
118
119
120
121
   */
  struct zynq_gpio {
  	struct gpio_chip chip;
  	void __iomem *base_addr;
  	struct clk *clk;
59e22114b   Ezra Savard   gpio: zynq: Fixed...
122
  	int irq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
123
  	const struct zynq_platform_data *p_data;
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
124
  	struct gpio_regs context;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
125
126
127
128
129
  };
  
  /**
   * struct zynq_platform_data -  zynq gpio platform data structure
   * @label:	string to store in gpio->label
6ae5104cb   Nava kishore Manne   gpio: zynq: Fix k...
130
   * @quirks:	Flags is used to identify the platform
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
131
132
133
134
   * @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...
135
   */
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
136
137
  struct zynq_platform_data {
  	const char *label;
e3296f19c   Nava kishore Manne   gpio: Added zynq ...
138
  	u32 quirks;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
139
140
141
142
  	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 ...
143
  };
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
144
145
  static struct irq_chip zynq_gpio_level_irqchip;
  static struct irq_chip zynq_gpio_edge_irqchip;
fa9795d11   Linus Walleij   gpio: zynq: use c...
146

3242ba117   Harini Katakam   gpio: Add driver ...
147
  /**
3638bd4a0   Soren Brinkmann   gpio: zynq: Clari...
148
149
150
151
152
153
154
155
156
157
158
   * 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...
159
160
161
162
163
164
165
166
167
168
169
   * 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 ...
170
171
172
173
174
175
176
   * 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...
177
   * @gpio:	gpio device data structure
3242ba117   Harini Katakam   gpio: Add driver ...
178
179
180
181
182
   *
   * 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...
183
184
  					  unsigned int *bank_pin_num,
  					  struct zynq_gpio *gpio)
3242ba117   Harini Katakam   gpio: Add driver ...
185
  {
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
186
187
188
189
  	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...
190
  		    (pin_num <= gpio->p_data->bank_max[bank])) {
2717cfcaf   Nava kishore Manne   gpio: zynq: Fix w...
191
192
193
194
  			*bank_num = bank;
  			*bank_pin_num = pin_num -
  					gpio->p_data->bank_min[bank];
  			return;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
195
  		}
3242ba117   Harini Katakam   gpio: Add driver ...
196
  	}
3242ba117   Harini Katakam   gpio: Add driver ...
197

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
198
199
200
201
202
  	/* default */
  	WARN(true, "invalid GPIO pin number: %u", pin_num);
  	*bank_num = 0;
  	*bank_pin_num = 0;
  }
016da1443   Lars-Peter Clausen   gpio: zynq: Take ...
203

3242ba117   Harini Katakam   gpio: Add driver ...
204
205
206
207
208
209
210
211
212
213
214
215
216
  /**
   * 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...
217
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
218

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

06aa09081   Swapna Manupati   gpio: zynq: Provi...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  	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 ...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  	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...
260
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
261

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
262
  	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
263
264
265
266
267
268
269
270
271
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
  
  	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;
31a894475   Linus Walleij   gpio: zynq: use g...
297
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
298

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

e3296f19c   Nava kishore Manne   gpio: Added zynq ...
301
302
303
304
  	/*
  	 * On zynq bank 0 pins 7 and 8 are special and cannot be used
  	 * as inputs.
  	 */
3638bd4a0   Soren Brinkmann   gpio: zynq: Clari...
305
  	if (zynq_gpio_is_zynq(gpio) && bank_num == 0 &&
16ee62e56   Michal Simek   gpio: zynq: Fix d...
306
  	    (bank_pin_num == 7 || bank_pin_num == 8))
3242ba117   Harini Katakam   gpio: Add driver ...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  		return -EINVAL;
  
  	/* clear the bit in direction mode reg to set the pin as input */
  	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
  	reg &= ~BIT(bank_pin_num);
  	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
  
  	return 0;
  }
  
  /**
   * zynq_gpio_dir_out - Set the direction of the specified GPIO pin as output
   * @chip:	gpio_chip instance to be worked on
   * @pin:	gpio pin number within the device
   * @state:	value to be written to specified pin
   *
   * This function sets the direction of specified GPIO pin as output, configures
   * the Output Enable register for the pin and uses zynq_gpio_set to set
   * the state of the pin to the value specified.
   *
   * Return: 0 always
   */
  static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
  			     int state)
  {
  	u32 reg;
  	unsigned int bank_num, bank_pin_num;
31a894475   Linus Walleij   gpio: zynq: use g...
334
  	struct zynq_gpio *gpio = gpiochip_get_data(chip);
3242ba117   Harini Katakam   gpio: Add driver ...
335

bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
336
  	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  
  	/* set the GPIO pin as output */
  	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
  	reg |= BIT(bank_pin_num);
  	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
  
  	/* configure the output enable reg for the pin */
  	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
  	reg |= BIT(bank_pin_num);
  	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
  
  	/* set the state of the pin */
  	zynq_gpio_set_value(chip, pin, state);
  	return 0;
  }
  
  /**
6169005ce   Brandon Maier   gpio: zynq: Repor...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
   * 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.
   *
   * Return: 0 for output, 1 for input
   */
  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));
  
  	return !(reg & BIT(bank_pin_num));
  }
  
  /**
3242ba117   Harini Katakam   gpio: Add driver ...
376
377
378
379
380
381
382
383
384
385
   * 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...
386
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
387
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
3242ba117   Harini Katakam   gpio: Add driver ...
388
389
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
390
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  	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...
407
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
408
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
3242ba117   Harini Katakam   gpio: Add driver ...
409
410
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
411
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
412
413
414
415
416
  	writel_relaxed(BIT(bank_pin_num),
  		       gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num));
  }
  
  /**
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
417
418
419
420
421
422
423
424
425
426
   * 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...
427
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
428
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
429
430
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
431
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
432
433
434
435
436
437
438
439
440
  	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...
441
   * Clears the INTSTS bit and unmasks the given interrupt.
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
   */
  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 ...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
   * 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...
478
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
479
  		gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
3242ba117   Harini Katakam   gpio: Add driver ...
480
481
  
  	device_pin_num = irq_data->hwirq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
482
  	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
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
  
  	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...
528

16ee62e56   Michal Simek   gpio: zynq: Fix d...
529
  	if (type & IRQ_TYPE_LEVEL_MASK)
47c084629   Thomas Gleixner   gpio/zynq: Use ir...
530
  		irq_set_chip_handler_name_locked(irq_data,
16ee62e56   Michal Simek   gpio: zynq: Fix d...
531
532
533
  						 &zynq_gpio_level_irqchip,
  						 handle_fasteoi_irq, NULL);
  	else
47c084629   Thomas Gleixner   gpio/zynq: Use ir...
534
  		irq_set_chip_handler_name_locked(irq_data,
16ee62e56   Michal Simek   gpio: zynq: Fix d...
535
536
  						 &zynq_gpio_edge_irqchip,
  						 handle_level_irq, NULL);
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
537

3242ba117   Harini Katakam   gpio: Add driver ...
538
539
540
541
542
  	return 0;
  }
  
  static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
  {
fa9795d11   Linus Walleij   gpio: zynq: use c...
543
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
544
  		gpiochip_get_data(irq_data_get_irq_chip_data(data));
59e22114b   Ezra Savard   gpio: zynq: Fixed...
545
546
  
  	irq_set_irq_wake(gpio->irq, on);
3242ba117   Harini Katakam   gpio: Add driver ...
547
548
549
  
  	return 0;
  }
c2df3de0d   Thomas Petazzoni   gpio: zynq: prope...
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
  static int zynq_gpio_irq_reqres(struct irq_data *d)
  {
  	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
  	int ret;
  
  	ret = pm_runtime_get_sync(chip->parent);
  	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 ...
569
  /* irq chip descriptor */
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
570
  static struct irq_chip zynq_gpio_level_irqchip = {
3242ba117   Harini Katakam   gpio: Add driver ...
571
  	.name		= DRIVER_NAME,
190dc2e68   Lars-Peter Clausen   gpio: zynq: Clear...
572
  	.irq_enable	= zynq_gpio_irq_enable,
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
573
574
575
576
577
  	.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...
578
579
  	.irq_request_resources = zynq_gpio_irq_reqres,
  	.irq_release_resources = zynq_gpio_irq_relres,
a19467788   Ezra Savard   gpio: zynq: Mask ...
580
581
  	.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
  			  IRQCHIP_MASK_ON_SUSPEND,
6dd859508   Lars-Peter Clausen   gpio: zynq: Fix I...
582
583
584
585
586
587
  };
  
  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 ...
588
589
590
591
  	.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...
592
593
  	.irq_request_resources = zynq_gpio_irq_reqres,
  	.irq_release_resources = zynq_gpio_irq_relres,
a19467788   Ezra Savard   gpio: zynq: Mask ...
594
  	.flags		= IRQCHIP_MASK_ON_SUSPEND,
3242ba117   Harini Katakam   gpio: Add driver ...
595
  };
5a2533a74   Lars-Peter Clausen   gpio: zynq: Reduc...
596
597
598
599
  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...
600
  	unsigned int bank_offset = gpio->p_data->bank_min[bank_num];
f0fbe7bce   Thierry Reding   gpio: Move irqdom...
601
  	struct irq_domain *irqdomain = gpio->chip.irq.domain;
5a2533a74   Lars-Peter Clausen   gpio: zynq: Reduc...
602
603
604
605
606
607
608
  	int offset;
  
  	if (!pending)
  		return;
  
  	for_each_set_bit(offset, &pending, 32) {
  		unsigned int gpio_irq;
016da1443   Lars-Peter Clausen   gpio: zynq: Take ...
609
  		gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset);
5a2533a74   Lars-Peter Clausen   gpio: zynq: Reduc...
610
611
612
  		generic_handle_irq(gpio_irq);
  	}
  }
3242ba117   Harini Katakam   gpio: Add driver ...
613
614
  /**
   * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device
3242ba117   Harini Katakam   gpio: Add driver ...
615
616
617
618
619
620
621
622
   * @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...
623
  static void zynq_gpio_irqhandler(struct irq_desc *desc)
3242ba117   Harini Katakam   gpio: Add driver ...
624
625
626
  {
  	u32 int_sts, int_enb;
  	unsigned int bank_num;
fa9795d11   Linus Walleij   gpio: zynq: use c...
627
  	struct zynq_gpio *gpio =
31a894475   Linus Walleij   gpio: zynq: use g...
628
  		gpiochip_get_data(irq_desc_get_handler_data(desc));
3242ba117   Harini Katakam   gpio: Add driver ...
629
630
631
  	struct irq_chip *irqchip = irq_desc_get_chip(desc);
  
  	chained_irq_enter(irqchip, desc);
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
632
  	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
3242ba117   Harini Katakam   gpio: Add driver ...
633
634
635
636
  		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...
637
  		zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
3242ba117   Harini Katakam   gpio: Add driver ...
638
639
640
641
  	}
  
  	chained_irq_exit(irqchip, desc);
  }
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
  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));
  	}
  }
  
  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++) {
8457f26af   Swapna Manupati   gpio: zynq: Fix f...
674
675
  		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
  				ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
676
677
678
679
680
681
682
683
684
  		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...
685
686
687
688
689
690
691
692
693
  		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));
8457f26af   Swapna Manupati   gpio: zynq: Fix f...
694
695
696
  		writel_relaxed(~(gpio->context.int_en[bank_num]),
  			       gpio->base_addr +
  			       ZYNQ_GPIO_INTEN_OFFSET(bank_num));
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
697
698
  	}
  }
eb73d6eaa   Michal Simek   gpio: zynq: Fix e...
699

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

e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
705
706
  	if (!irqd_is_wakeup_set(data)) {
  		zynq_gpio_save_context(gpio);
3242ba117   Harini Katakam   gpio: Add driver ...
707
  		return pm_runtime_force_suspend(dev);
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
708
  	}
3242ba117   Harini Katakam   gpio: Add driver ...
709
710
711
712
713
714
  
  	return 0;
  }
  
  static int __maybe_unused zynq_gpio_resume(struct device *dev)
  {
a76e865ee   Shubhrajyoti Datta   gpio: zynq: simpl...
715
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
5e3a8ecd7   Shubhrajyoti Datta   gpio: zynq: Remov...
716
  	struct irq_data *data = irq_get_irq_data(gpio->irq);
e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
717
  	int ret;
59e22114b   Ezra Savard   gpio: zynq: Fixed...
718

e11de4de2   Shubhrajyoti Datta   gpio: zynq: Add s...
719
720
721
722
723
  	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 ...
724
725
726
727
728
729
  
  	return 0;
  }
  
  static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev)
  {
38ccad024   Wolfram Sang   gpio: gpio-zynq: ...
730
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
3242ba117   Harini Katakam   gpio: Add driver ...
731
732
733
734
735
736
737
738
  
  	clk_disable_unprepare(gpio->clk);
  
  	return 0;
  }
  
  static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev)
  {
38ccad024   Wolfram Sang   gpio: gpio-zynq: ...
739
  	struct zynq_gpio *gpio = dev_get_drvdata(dev);
3242ba117   Harini Katakam   gpio: Add driver ...
740
741
742
  
  	return clk_prepare_enable(gpio->clk);
  }
2717cfcaf   Nava kishore Manne   gpio: zynq: Fix w...
743
  static int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset)
3242ba117   Harini Katakam   gpio: Add driver ...
744
745
  {
  	int ret;
58383c784   Linus Walleij   gpio: change memb...
746
  	ret = pm_runtime_get_sync(chip->parent);
3242ba117   Harini Katakam   gpio: Add driver ...
747
748
749
750
751
752
753
  
  	/*
  	 * 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...
754
  static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset)
3242ba117   Harini Katakam   gpio: Add driver ...
755
  {
58383c784   Linus Walleij   gpio: change memb...
756
  	pm_runtime_put(chip->parent);
3242ba117   Harini Katakam   gpio: Add driver ...
757
758
759
760
  }
  
  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...
761
  	SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
16ee62e56   Michal Simek   gpio: zynq: Fix d...
762
  			   zynq_gpio_runtime_resume, NULL)
3242ba117   Harini Katakam   gpio: Add driver ...
763
  };
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
764
765
  static const struct zynq_platform_data zynqmp_gpio_def = {
  	.label = "zynqmp_gpio",
06aa09081   Swapna Manupati   gpio: zynq: Provi...
766
  	.quirks = GPIO_QUIRK_DATA_RO_BUG,
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  	.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...
785
  	.quirks = ZYNQ_GPIO_QUIRK_IS_ZYNQ | GPIO_QUIRK_DATA_RO_BUG,
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
786
787
788
789
790
791
792
793
794
795
796
797
798
  	.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...
799
800
  	{ .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def },
  	{ .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
801
802
803
  	{ /* end of table */ }
  };
  MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
3242ba117   Harini Katakam   gpio: Add driver ...
804
805
806
807
808
809
810
811
812
813
814
815
816
  /**
   * 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...
817
  	int ret, bank_num;
3242ba117   Harini Katakam   gpio: Add driver ...
818
819
  	struct zynq_gpio *gpio;
  	struct gpio_chip *chip;
f6a7053dd   Linus Walleij   gpio: zynq: Pass ...
820
  	struct gpio_irq_chip *girq;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
821
  	const struct of_device_id *match;
3242ba117   Harini Katakam   gpio: Add driver ...
822
823
824
825
  
  	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
  	if (!gpio)
  		return -ENOMEM;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
826
827
828
829
830
831
832
  	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 ...
833
  	platform_set_drvdata(pdev, gpio);
77bc0e69c   Enrico Weigelt, metux IT consult   gpio: zynq: use d...
834
  	gpio->base_addr = devm_platform_ioremap_resource(pdev, 0);
3242ba117   Harini Katakam   gpio: Add driver ...
835
836
  	if (IS_ERR(gpio->base_addr))
  		return PTR_ERR(gpio->base_addr);
59e22114b   Ezra Savard   gpio: zynq: Fixed...
837
  	gpio->irq = platform_get_irq(pdev, 0);
15bddb7d7   Stephen Boyd   gpio: Remove dev_...
838
  	if (gpio->irq < 0)
59e22114b   Ezra Savard   gpio: zynq: Fixed...
839
  		return gpio->irq;
3242ba117   Harini Katakam   gpio: Add driver ...
840
841
842
  
  	/* configure the gpio chip */
  	chip = &gpio->chip;
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
843
  	chip->label = gpio->p_data->label;
3242ba117   Harini Katakam   gpio: Add driver ...
844
  	chip->owner = THIS_MODULE;
58383c784   Linus Walleij   gpio: change memb...
845
  	chip->parent = &pdev->dev;
3242ba117   Harini Katakam   gpio: Add driver ...
846
847
848
849
850
851
  	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...
852
  	chip->get_direction = zynq_gpio_get_direction;
060f3ebf6   Michal Simek   gpio: zynq: Setup...
853
  	chip->base = of_alias_get_id(pdev->dev.of_node, "gpio");
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
854
  	chip->ngpio = gpio->p_data->ngpio;
3242ba117   Harini Katakam   gpio: Add driver ...
855

3773c195d   Michal Simek   gpio: zynq: Do PM...
856
  	/* Retrieve GPIO clock */
3242ba117   Harini Katakam   gpio: Add driver ...
857
858
859
860
861
862
  	gpio->clk = devm_clk_get(&pdev->dev, NULL);
  	if (IS_ERR(gpio->clk)) {
  		dev_err(&pdev->dev, "input clock not found.
  ");
  		return PTR_ERR(gpio->clk);
  	}
0f84f29ff   Helmut Grohne   gpio: zynq: initi...
863
864
865
866
867
868
  	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...
869

0f84f29ff   Helmut Grohne   gpio: zynq: initi...
870
  	pm_runtime_set_active(&pdev->dev);
3773c195d   Michal Simek   gpio: zynq: Do PM...
871
872
873
  	pm_runtime_enable(&pdev->dev);
  	ret = pm_runtime_get_sync(&pdev->dev);
  	if (ret < 0)
615d23f80   Shubhrajyoti Datta   gpio: zynq: Fix t...
874
  		goto err_pm_dis;
3242ba117   Harini Katakam   gpio: Add driver ...
875

3242ba117   Harini Katakam   gpio: Add driver ...
876
  	/* disable interrupts for all banks */
bdf7a4ae3   Anurag Kumar Vulisha   gpio: Added suppo...
877
  	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
3242ba117   Harini Katakam   gpio: Add driver ...
878
879
  		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
  			       ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
f6a7053dd   Linus Walleij   gpio: zynq: Pass ...
880
881
882
883
884
885
886
887
888
889
890
  	/* 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 ...
891
  	}
f6a7053dd   Linus Walleij   gpio: zynq: Pass ...
892
893
894
  	girq->parents[0] = gpio->irq;
  	girq->default_type = IRQ_TYPE_NONE;
  	girq->handler = handle_level_irq;
3242ba117   Harini Katakam   gpio: Add driver ...
895

f6a7053dd   Linus Walleij   gpio: zynq: Pass ...
896
897
898
899
900
901
902
  	/* 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 ...
903

3773c195d   Michal Simek   gpio: zynq: Do PM...
904
  	pm_runtime_put(&pdev->dev);
3242ba117   Harini Katakam   gpio: Add driver ...
905

3242ba117   Harini Katakam   gpio: Add driver ...
906
  	return 0;
3773c195d   Michal Simek   gpio: zynq: Do PM...
907
908
  err_pm_put:
  	pm_runtime_put(&pdev->dev);
615d23f80   Shubhrajyoti Datta   gpio: zynq: Fix t...
909
910
  err_pm_dis:
  	pm_runtime_disable(&pdev->dev);
0f84f29ff   Helmut Grohne   gpio: zynq: initi...
911
  	clk_disable_unprepare(gpio->clk);
3242ba117   Harini Katakam   gpio: Add driver ...
912
913
914
915
916
917
918
919
920
921
922
923
  
  	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 ...
924
925
926
  	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
  
  	pm_runtime_get_sync(&pdev->dev);
da26d5d80   Linus Walleij   gpio: remove rema...
927
  	gpiochip_remove(&gpio->chip);
3242ba117   Harini Katakam   gpio: Add driver ...
928
929
  	clk_disable_unprepare(gpio->clk);
  	device_set_wakeup_capable(&pdev->dev, 0);
6b956af08   Michal Simek   gpio: zynq: Fix p...
930
  	pm_runtime_disable(&pdev->dev);
3242ba117   Harini Katakam   gpio: Add driver ...
931
932
  	return 0;
  }
3242ba117   Harini Katakam   gpio: Add driver ...
933
934
935
  static struct platform_driver zynq_gpio_driver = {
  	.driver	= {
  		.name = DRIVER_NAME,
3242ba117   Harini Katakam   gpio: Add driver ...
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
  		.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...
953
954
955
956
957
  static void __exit zynq_gpio_exit(void)
  {
  	platform_driver_unregister(&zynq_gpio_driver);
  }
  module_exit(zynq_gpio_exit);
3242ba117   Harini Katakam   gpio: Add driver ...
958
959
960
  MODULE_AUTHOR("Xilinx Inc.");
  MODULE_DESCRIPTION("Zynq GPIO driver");
  MODULE_LICENSE("GPL");