Blame view

drivers/gpio/gpio-bcm-kona.c 17.3 KB
757651e3d   Markus Mayer   gpio: bcm281xx: A...
1
  /*
8f3e19fae   Paul Gortmaker   gpio: bcm-kona: m...
2
3
4
   * Broadcom Kona GPIO Driver
   *
   * Author: Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>
6f587c9f7   Markus Mayer   gpio: bcm281xx: U...
5
   * Copyright (C) 2012-2014 Broadcom Corporation
757651e3d   Markus Mayer   gpio: bcm281xx: A...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation version 2.
   *
   * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   * kind, whether express or implied; without even the implied warranty
   * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   */
  
  #include <linux/bitops.h>
  #include <linux/err.h>
  #include <linux/io.h>
  #include <linux/gpio.h>
  #include <linux/of_device.h>
  #include <linux/of_irq.h>
8f3e19fae   Paul Gortmaker   gpio: bcm-kona: m...
23
  #include <linux/init.h>
757651e3d   Markus Mayer   gpio: bcm281xx: A...
24
25
26
27
28
29
30
31
32
  #include <linux/irqdomain.h>
  #include <linux/irqchip/chained_irq.h>
  
  #define BCM_GPIO_PASSWD				0x00a5a501
  #define GPIO_PER_BANK				32
  #define GPIO_MAX_BANK_NUM			8
  
  #define GPIO_BANK(gpio)				((gpio) >> 5)
  #define GPIO_BIT(gpio)				((gpio) & (GPIO_PER_BANK - 1))
d762bae45   Markus Mayer   gpio: bcm281xx: F...
33
34
35
36
  /* There is a GPIO control register for each GPIO */
  #define GPIO_CONTROL(gpio)			(0x00000100 + ((gpio) << 2))
  
  /* The remaining registers are per GPIO bank */
757651e3d   Markus Mayer   gpio: bcm281xx: A...
37
38
39
40
41
42
43
  #define GPIO_OUT_STATUS(bank)			(0x00000000 + ((bank) << 2))
  #define GPIO_IN_STATUS(bank)			(0x00000020 + ((bank) << 2))
  #define GPIO_OUT_SET(bank)			(0x00000040 + ((bank) << 2))
  #define GPIO_OUT_CLEAR(bank)			(0x00000060 + ((bank) << 2))
  #define GPIO_INT_STATUS(bank)			(0x00000080 + ((bank) << 2))
  #define GPIO_INT_MASK(bank)			(0x000000a0 + ((bank) << 2))
  #define GPIO_INT_MSKCLR(bank)			(0x000000c0 + ((bank) << 2))
757651e3d   Markus Mayer   gpio: bcm281xx: A...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  #define GPIO_PWD_STATUS(bank)			(0x00000500 + ((bank) << 2))
  
  #define GPIO_GPPWR_OFFSET			0x00000520
  
  #define GPIO_GPCTR0_DBR_SHIFT			5
  #define GPIO_GPCTR0_DBR_MASK			0x000001e0
  
  #define GPIO_GPCTR0_ITR_SHIFT			3
  #define GPIO_GPCTR0_ITR_MASK			0x00000018
  #define GPIO_GPCTR0_ITR_CMD_RISING_EDGE		0x00000001
  #define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE	0x00000002
  #define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE		0x00000003
  
  #define GPIO_GPCTR0_IOTR_MASK			0x00000001
  #define GPIO_GPCTR0_IOTR_CMD_0UTPUT		0x00000000
  #define GPIO_GPCTR0_IOTR_CMD_INPUT		0x00000001
  
  #define GPIO_GPCTR0_DB_ENABLE_MASK		0x00000100
  
  #define LOCK_CODE				0xffffffff
  #define UNLOCK_CODE				0x00000000
  
  struct bcm_kona_gpio {
  	void __iomem *reg_base;
  	int num_bank;
  	spinlock_t lock;
  	struct gpio_chip gpio_chip;
  	struct irq_domain *irq_domain;
  	struct bcm_kona_gpio_bank *banks;
  	struct platform_device *pdev;
  };
  
  struct bcm_kona_gpio_bank {
  	int id;
  	int irq;
  	/* Used in the interrupt handler */
  	struct bcm_kona_gpio *kona_gpio;
  };
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
82
83
  static inline void bcm_kona_gpio_write_lock_regs(void __iomem *reg_base,
  						int bank_id, u32 lockcode)
757651e3d   Markus Mayer   gpio: bcm281xx: A...
84
85
86
87
  {
  	writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET);
  	writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id));
  }
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
88
89
  static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
  					unsigned gpio)
757651e3d   Markus Mayer   gpio: bcm281xx: A...
90
  {
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
91
92
93
94
95
96
97
98
99
100
101
  	u32 val;
  	unsigned long flags;
  	int bank_id = GPIO_BANK(gpio);
  
  	spin_lock_irqsave(&kona_gpio->lock, flags);
  
  	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
  	val |= BIT(gpio);
  	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
  
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
102
  }
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
103
104
  static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
  					unsigned gpio)
757651e3d   Markus Mayer   gpio: bcm281xx: A...
105
  {
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
106
107
108
109
110
111
112
113
114
115
116
  	u32 val;
  	unsigned long flags;
  	int bank_id = GPIO_BANK(gpio);
  
  	spin_lock_irqsave(&kona_gpio->lock, flags);
  
  	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
  	val &= ~BIT(gpio);
  	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
  
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
117
  }
0218d5a8b   Axel Lin   gpio: bcm-kona: I...
118
119
  static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
  {
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
120
  	struct bcm_kona_gpio *kona_gpio = gpiochip_get_data(chip);
0218d5a8b   Axel Lin   gpio: bcm-kona: I...
121
122
123
124
125
126
  	void __iomem *reg_base = kona_gpio->reg_base;
  	u32 val;
  
  	val = readl(reg_base + GPIO_CONTROL(gpio)) & GPIO_GPCTR0_IOTR_MASK;
  	return val ? GPIOF_DIR_IN : GPIOF_DIR_OUT;
  }
757651e3d   Markus Mayer   gpio: bcm281xx: A...
127
128
129
130
131
132
133
134
  static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
  	int bank_id = GPIO_BANK(gpio);
  	int bit = GPIO_BIT(gpio);
  	u32 val, reg_offset;
  	unsigned long flags;
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
135
  	kona_gpio = gpiochip_get_data(chip);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
136
137
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
138

757651e3d   Markus Mayer   gpio: bcm281xx: A...
139
  	/* this function only applies to output pin */
0218d5a8b   Axel Lin   gpio: bcm-kona: I...
140
  	if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
757651e3d   Markus Mayer   gpio: bcm281xx: A...
141
142
143
144
145
146
147
148
149
  		goto out;
  
  	reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
  
  	val = readl(reg_base + reg_offset);
  	val |= BIT(bit);
  	writel(val, reg_base + reg_offset);
  
  out:
757651e3d   Markus Mayer   gpio: bcm281xx: A...
150
151
152
153
154
155
156
157
158
159
160
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  }
  
  static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
  	int bank_id = GPIO_BANK(gpio);
  	int bit = GPIO_BIT(gpio);
  	u32 val, reg_offset;
  	unsigned long flags;
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
161
  	kona_gpio = gpiochip_get_data(chip);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
162
163
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
164

0218d5a8b   Axel Lin   gpio: bcm-kona: I...
165
166
167
168
  	if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
  		reg_offset = GPIO_IN_STATUS(bank_id);
  	else
  		reg_offset = GPIO_OUT_STATUS(bank_id);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
169
170
  
  	/* read the GPIO bank status */
757651e3d   Markus Mayer   gpio: bcm281xx: A...
171
  	val = readl(reg_base + reg_offset);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
172
173
174
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  
  	/* return the specified bit status */
e2f0b0056   Markus Mayer   gpio: bcm281xx: F...
175
  	return !!(val & BIT(bit));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
176
  }
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
177
178
  static int bcm_kona_gpio_request(struct gpio_chip *chip, unsigned gpio)
  {
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
179
  	struct bcm_kona_gpio *kona_gpio = gpiochip_get_data(chip);
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
180
181
182
183
184
185
186
  
  	bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
  	return 0;
  }
  
  static void bcm_kona_gpio_free(struct gpio_chip *chip, unsigned gpio)
  {
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
187
  	struct bcm_kona_gpio *kona_gpio = gpiochip_get_data(chip);
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
188
189
190
  
  	bcm_kona_gpio_lock_gpio(kona_gpio, gpio);
  }
757651e3d   Markus Mayer   gpio: bcm281xx: A...
191
192
193
194
195
196
  static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
  	u32 val;
  	unsigned long flags;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
197

ba4a74485   Linus Walleij   gpio: bcm-kona: u...
198
  	kona_gpio = gpiochip_get_data(chip);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
199
200
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
201
202
203
204
205
  
  	val = readl(reg_base + GPIO_CONTROL(gpio));
  	val &= ~GPIO_GPCTR0_IOTR_MASK;
  	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
  	writel(val, reg_base + GPIO_CONTROL(gpio));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  
  	return 0;
  }
  
  static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
  					  unsigned gpio, int value)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
  	int bank_id = GPIO_BANK(gpio);
  	int bit = GPIO_BIT(gpio);
  	u32 val, reg_offset;
  	unsigned long flags;
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
220
  	kona_gpio = gpiochip_get_data(chip);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
221
222
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
223
224
225
226
227
228
229
230
231
232
  
  	val = readl(reg_base + GPIO_CONTROL(gpio));
  	val &= ~GPIO_GPCTR0_IOTR_MASK;
  	val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
  	writel(val, reg_base + GPIO_CONTROL(gpio));
  	reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
  
  	val = readl(reg_base + reg_offset);
  	val |= BIT(bit);
  	writel(val, reg_base + reg_offset);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
233
234
235
236
237
238
239
240
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  
  	return 0;
  }
  
  static int bcm_kona_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
  {
  	struct bcm_kona_gpio *kona_gpio;
ba4a74485   Linus Walleij   gpio: bcm-kona: u...
241
  	kona_gpio = gpiochip_get_data(chip);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
242
243
244
245
246
247
248
249
250
251
252
253
  	if (gpio >= kona_gpio->gpio_chip.ngpio)
  		return -ENXIO;
  	return irq_create_mapping(kona_gpio->irq_domain, gpio);
  }
  
  static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
  				      unsigned debounce)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
  	u32 val, res;
  	unsigned long flags;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
254

ba4a74485   Linus Walleij   gpio: bcm-kona: u...
255
  	kona_gpio = gpiochip_get_data(chip);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
256
257
258
  	reg_base = kona_gpio->reg_base;
  	/* debounce must be 1-128ms (or 0) */
  	if ((debounce > 0 && debounce < 1000) || debounce > 128000) {
58383c784   Linus Walleij   gpio: change memb...
259
260
  		dev_err(chip->parent, "Debounce value %u not in range
  ",
757651e3d   Markus Mayer   gpio: bcm281xx: A...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  			debounce);
  		return -EINVAL;
  	}
  
  	/* calculate debounce bit value */
  	if (debounce != 0) {
  		/* Convert to ms */
  		debounce /= 1000;
  		/* find the MSB */
  		res = fls(debounce) - 1;
  		/* Check if MSB-1 is set (round up or down) */
  		if (res > 0 && (debounce & BIT(res - 1)))
  			res++;
  	}
  
  	/* spin lock for read-modify-write of the GPIO register */
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
278
279
280
281
282
283
284
285
286
287
288
289
290
  
  	val = readl(reg_base + GPIO_CONTROL(gpio));
  	val &= ~GPIO_GPCTR0_DBR_MASK;
  
  	if (debounce == 0) {
  		/* disable debounce */
  		val &= ~GPIO_GPCTR0_DB_ENABLE_MASK;
  	} else {
  		val |= GPIO_GPCTR0_DB_ENABLE_MASK |
  		    (res << GPIO_GPCTR0_DBR_SHIFT);
  	}
  
  	writel(val, reg_base + GPIO_CONTROL(gpio));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
291
292
293
294
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  
  	return 0;
  }
e35b5ab0a   Julia Lawall   gpio: constify gp...
295
  static const struct gpio_chip template_chip = {
757651e3d   Markus Mayer   gpio: bcm281xx: A...
296
  	.label = "bcm-kona-gpio",
afb3690c3   Wei Yongjun   gpio: bcm-kona: a...
297
  	.owner = THIS_MODULE,
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
298
299
  	.request = bcm_kona_gpio_request,
  	.free = bcm_kona_gpio_free,
0218d5a8b   Axel Lin   gpio: bcm-kona: I...
300
  	.get_direction = bcm_kona_gpio_get_dir,
757651e3d   Markus Mayer   gpio: bcm281xx: A...
301
302
303
304
305
306
307
308
309
310
311
312
313
  	.direction_input = bcm_kona_gpio_direction_input,
  	.get = bcm_kona_gpio_get,
  	.direction_output = bcm_kona_gpio_direction_output,
  	.set = bcm_kona_gpio_set,
  	.set_debounce = bcm_kona_gpio_set_debounce,
  	.to_irq = bcm_kona_gpio_to_irq,
  	.base = 0,
  };
  
  static void bcm_kona_gpio_irq_ack(struct irq_data *d)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
b7ab69736   Markus Mayer   gpio: bcm281xx: U...
314
  	unsigned gpio = d->hwirq;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
315
316
317
318
319
320
321
322
  	int bank_id = GPIO_BANK(gpio);
  	int bit = GPIO_BIT(gpio);
  	u32 val;
  	unsigned long flags;
  
  	kona_gpio = irq_data_get_irq_chip_data(d);
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
323
324
325
326
  
  	val = readl(reg_base + GPIO_INT_STATUS(bank_id));
  	val |= BIT(bit);
  	writel(val, reg_base + GPIO_INT_STATUS(bank_id));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
327
328
329
330
331
332
333
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  }
  
  static void bcm_kona_gpio_irq_mask(struct irq_data *d)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
b7ab69736   Markus Mayer   gpio: bcm281xx: U...
334
  	unsigned gpio = d->hwirq;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
335
336
337
338
339
340
341
342
  	int bank_id = GPIO_BANK(gpio);
  	int bit = GPIO_BIT(gpio);
  	u32 val;
  	unsigned long flags;
  
  	kona_gpio = irq_data_get_irq_chip_data(d);
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
343
344
345
346
  
  	val = readl(reg_base + GPIO_INT_MASK(bank_id));
  	val |= BIT(bit);
  	writel(val, reg_base + GPIO_INT_MASK(bank_id));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
347
348
349
350
351
352
353
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  }
  
  static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
b7ab69736   Markus Mayer   gpio: bcm281xx: U...
354
  	unsigned gpio = d->hwirq;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
355
356
357
358
359
360
361
362
  	int bank_id = GPIO_BANK(gpio);
  	int bit = GPIO_BIT(gpio);
  	u32 val;
  	unsigned long flags;
  
  	kona_gpio = irq_data_get_irq_chip_data(d);
  	reg_base = kona_gpio->reg_base;
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
363
364
365
366
  
  	val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
  	val |= BIT(bit);
  	writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
367
368
369
370
371
372
373
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  }
  
  static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
  {
  	struct bcm_kona_gpio *kona_gpio;
  	void __iomem *reg_base;
b7ab69736   Markus Mayer   gpio: bcm281xx: U...
374
  	unsigned gpio = d->hwirq;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
375
376
377
  	u32 lvl_type;
  	u32 val;
  	unsigned long flags;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  
  	kona_gpio = irq_data_get_irq_chip_data(d);
  	reg_base = kona_gpio->reg_base;
  	switch (type & IRQ_TYPE_SENSE_MASK) {
  	case IRQ_TYPE_EDGE_RISING:
  		lvl_type = GPIO_GPCTR0_ITR_CMD_RISING_EDGE;
  		break;
  
  	case IRQ_TYPE_EDGE_FALLING:
  		lvl_type = GPIO_GPCTR0_ITR_CMD_FALLING_EDGE;
  		break;
  
  	case IRQ_TYPE_EDGE_BOTH:
  		lvl_type = GPIO_GPCTR0_ITR_CMD_BOTH_EDGE;
  		break;
  
  	case IRQ_TYPE_LEVEL_HIGH:
  	case IRQ_TYPE_LEVEL_LOW:
  		/* BCM GPIO doesn't support level triggering */
  	default:
58383c784   Linus Walleij   gpio: change memb...
398
  		dev_err(kona_gpio->gpio_chip.parent,
757651e3d   Markus Mayer   gpio: bcm281xx: A...
399
400
401
402
403
404
  			"Invalid BCM GPIO irq type 0x%x
  ", type);
  		return -EINVAL;
  	}
  
  	spin_lock_irqsave(&kona_gpio->lock, flags);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
405
406
407
408
409
  
  	val = readl(reg_base + GPIO_CONTROL(gpio));
  	val &= ~GPIO_GPCTR0_ITR_MASK;
  	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
  	writel(val, reg_base + GPIO_CONTROL(gpio));
757651e3d   Markus Mayer   gpio: bcm281xx: A...
410
411
412
413
  	spin_unlock_irqrestore(&kona_gpio->lock, flags);
  
  	return 0;
  }
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
414
  static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
757651e3d   Markus Mayer   gpio: bcm281xx: A...
415
416
417
418
  {
  	void __iomem *reg_base;
  	int bit, bank_id;
  	unsigned long sta;
476f8b4c9   Jiang Liu   gpio: Use irq_des...
419
  	struct bcm_kona_gpio_bank *bank = irq_desc_get_handler_data(desc);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
420
421
422
423
424
425
426
427
428
429
430
  	struct irq_chip *chip = irq_desc_get_chip(desc);
  
  	chained_irq_enter(chip, desc);
  
  	/*
  	 * For bank interrupts, we can't use chip_data to store the kona_gpio
  	 * pointer, since GIC needs it for its own purposes. Therefore, we get
  	 * our pointer from the bank structure.
  	 */
  	reg_base = bank->kona_gpio->reg_base;
  	bank_id = bank->id;
757651e3d   Markus Mayer   gpio: bcm281xx: A...
431
432
433
434
  
  	while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
  		    (~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
  		for_each_set_bit(bit, &sta, 32) {
d933cc619   Linus Walleij   gpio: bcm_kona: r...
435
436
437
438
  			int hwirq = GPIO_PER_BANK * bank_id + bit;
  			int child_irq =
  				irq_find_mapping(bank->kona_gpio->irq_domain,
  						 hwirq);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
439
440
441
442
443
444
445
  			/*
  			 * Clear interrupt before handler is called so we don't
  			 * miss any interrupt occurred during executing them.
  			 */
  			writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
  			       BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
  			/* Invoke interrupt handler */
d933cc619   Linus Walleij   gpio: bcm_kona: r...
446
  			generic_handle_irq(child_irq);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
447
448
  		}
  	}
757651e3d   Markus Mayer   gpio: bcm281xx: A...
449
450
  	chained_irq_exit(chip, desc);
  }
57ef04288   Linus Walleij   gpio: switch driv...
451
  static int bcm_kona_gpio_irq_reqres(struct irq_data *d)
db6b3ad17   Linus Walleij   gpio: bcm-kona: l...
452
453
  {
  	struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
e3a2e8789   Alexandre Courbot   gpio: rename gpio...
454
  	if (gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) {
58383c784   Linus Walleij   gpio: change memb...
455
  		dev_err(kona_gpio->gpio_chip.parent,
db6b3ad17   Linus Walleij   gpio: bcm-kona: l...
456
457
458
  			"unable to lock HW IRQ %lu for IRQ
  ",
  			d->hwirq);
57ef04288   Linus Walleij   gpio: switch driv...
459
460
  		return -EINVAL;
  	}
db6b3ad17   Linus Walleij   gpio: bcm-kona: l...
461
462
  	return 0;
  }
57ef04288   Linus Walleij   gpio: switch driv...
463
  static void bcm_kona_gpio_irq_relres(struct irq_data *d)
db6b3ad17   Linus Walleij   gpio: bcm-kona: l...
464
465
  {
  	struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
e3a2e8789   Alexandre Courbot   gpio: rename gpio...
466
  	gpiochip_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq);
db6b3ad17   Linus Walleij   gpio: bcm-kona: l...
467
  }
757651e3d   Markus Mayer   gpio: bcm281xx: A...
468
469
470
471
472
473
  static struct irq_chip bcm_gpio_irq_chip = {
  	.name = "bcm-kona-gpio",
  	.irq_ack = bcm_kona_gpio_irq_ack,
  	.irq_mask = bcm_kona_gpio_irq_mask,
  	.irq_unmask = bcm_kona_gpio_irq_unmask,
  	.irq_set_type = bcm_kona_gpio_irq_set_type,
57ef04288   Linus Walleij   gpio: switch driv...
474
475
  	.irq_request_resources = bcm_kona_gpio_irq_reqres,
  	.irq_release_resources = bcm_kona_gpio_irq_relres,
757651e3d   Markus Mayer   gpio: bcm281xx: A...
476
  };
377812920   Behan Webster   gpio, bcm-kona, L...
477
  static struct of_device_id const bcm_kona_gpio_of_match[] = {
757651e3d   Markus Mayer   gpio: bcm281xx: A...
478
479
480
  	{ .compatible = "brcm,kona-gpio" },
  	{}
  };
757651e3d   Markus Mayer   gpio: bcm281xx: A...
481
482
483
484
485
  /*
   * This lock class tells lockdep that GPIO irqs are in a different
   * category than their parents, so it won't report false recursion.
   */
  static struct lock_class_key gpio_lock_class;
1dc942721   Linus Walleij   gpio: bcm-kona: o...
486
  static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq,
757651e3d   Markus Mayer   gpio: bcm281xx: A...
487
488
489
  				 irq_hw_number_t hwirq)
  {
  	int ret;
1dc942721   Linus Walleij   gpio: bcm-kona: o...
490
  	ret = irq_set_chip_data(irq, d->host_data);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
491
492
  	if (ret < 0)
  		return ret;
1dc942721   Linus Walleij   gpio: bcm-kona: o...
493
494
  	irq_set_lockdep_class(irq, &gpio_lock_class);
  	irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq);
1dc942721   Linus Walleij   gpio: bcm-kona: o...
495
  	irq_set_noprobe(irq);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
496
497
498
  
  	return 0;
  }
d933cc619   Linus Walleij   gpio: bcm_kona: r...
499
  static void bcm_kona_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
757651e3d   Markus Mayer   gpio: bcm281xx: A...
500
  {
d933cc619   Linus Walleij   gpio: bcm_kona: r...
501
502
  	irq_set_chip_and_handler(irq, NULL, NULL);
  	irq_set_chip_data(irq, NULL);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
503
  }
0b354dc43   Krzysztof Kozlowski   gpio: Constify ir...
504
  static const struct irq_domain_ops bcm_kona_irq_ops = {
757651e3d   Markus Mayer   gpio: bcm281xx: A...
505
506
507
508
509
510
511
512
513
514
515
516
517
  	.map = bcm_kona_gpio_irq_map,
  	.unmap = bcm_kona_gpio_irq_unmap,
  	.xlate = irq_domain_xlate_twocell,
  };
  
  static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
  {
  	void __iomem *reg_base;
  	int i;
  
  	reg_base = kona_gpio->reg_base;
  	/* disable interrupts and clear status */
  	for (i = 0; i < kona_gpio->num_bank; i++) {
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
518
  		/* Unlock the entire bank first */
b66b2a0ad   Ben Dooks   gpio: bcm-kona: f...
519
  		bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
520
521
  		writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
  		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
bdb93c03c   Markus Mayer   gpio: bcm281xx: C...
522
  		/* Now re-lock the bank */
b66b2a0ad   Ben Dooks   gpio: bcm-kona: f...
523
  		bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
  	}
  }
  
  static int bcm_kona_gpio_probe(struct platform_device *pdev)
  {
  	struct device *dev = &pdev->dev;
  	const struct of_device_id *match;
  	struct resource *res;
  	struct bcm_kona_gpio_bank *bank;
  	struct bcm_kona_gpio *kona_gpio;
  	struct gpio_chip *chip;
  	int ret;
  	int i;
  
  	match = of_match_device(bcm_kona_gpio_of_match, dev);
  	if (!match) {
  		dev_err(dev, "Failed to find gpio controller
  ");
  		return -ENODEV;
  	}
  
  	kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL);
  	if (!kona_gpio)
  		return -ENOMEM;
  
  	kona_gpio->gpio_chip = template_chip;
  	chip = &kona_gpio->gpio_chip;
  	kona_gpio->num_bank = of_irq_count(dev->of_node);
  	if (kona_gpio->num_bank == 0) {
  		dev_err(dev, "Couldn't determine # GPIO banks
  ");
  		return -ENOENT;
  	}
  	if (kona_gpio->num_bank > GPIO_MAX_BANK_NUM) {
  		dev_err(dev, "Too many GPIO banks configured (max=%d)
  ",
  			GPIO_MAX_BANK_NUM);
  		return -ENXIO;
  	}
  	kona_gpio->banks = devm_kzalloc(dev,
  					kona_gpio->num_bank *
  					sizeof(*kona_gpio->banks), GFP_KERNEL);
  	if (!kona_gpio->banks)
  		return -ENOMEM;
  
  	kona_gpio->pdev = pdev;
  	platform_set_drvdata(pdev, kona_gpio);
  	chip->of_node = dev->of_node;
  	chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;
  
  	kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,
  						      chip->ngpio,
  						      &bcm_kona_irq_ops,
  						      kona_gpio);
  	if (!kona_gpio->irq_domain) {
  		dev_err(dev, "Couldn't allocate IRQ domain
  ");
  		return -ENXIO;
  	}
  
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	kona_gpio->reg_base = devm_ioremap_resource(dev, res);
  	if (IS_ERR(kona_gpio->reg_base)) {
  		ret = -ENXIO;
  		goto err_irq_domain;
  	}
  
  	for (i = 0; i < kona_gpio->num_bank; i++) {
  		bank = &kona_gpio->banks[i];
  		bank->id = i;
  		bank->irq = platform_get_irq(pdev, i);
  		bank->kona_gpio = kona_gpio;
  		if (bank->irq < 0) {
  			dev_err(dev, "Couldn't get IRQ for bank %d", i);
  			ret = -ENOENT;
  			goto err_irq_domain;
  		}
  	}
23b4faa9a   Markus Mayer   gpio: bcm281xx: D...
602
603
  	dev_info(&pdev->dev, "Setting up Kona GPIO
  ");
757651e3d   Markus Mayer   gpio: bcm281xx: A...
604
605
  
  	bcm_kona_gpio_reset(kona_gpio);
0b8931237   Laxman Dewangan   gpio: bcm-kona: U...
606
  	ret = devm_gpiochip_add_data(dev, chip, kona_gpio);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
607
608
609
610
611
  	if (ret < 0) {
  		dev_err(dev, "Couldn't add GPIO chip -- %d
  ", ret);
  		goto err_irq_domain;
  	}
757651e3d   Markus Mayer   gpio: bcm281xx: A...
612
613
  	for (i = 0; i < kona_gpio->num_bank; i++) {
  		bank = &kona_gpio->banks[i];
b34cc6208   Thomas Gleixner   gpio/bcm-kona: Fi...
614
615
616
  		irq_set_chained_handler_and_data(bank->irq,
  						 bcm_kona_gpio_irq_handler,
  						 bank);
757651e3d   Markus Mayer   gpio: bcm281xx: A...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  	}
  
  	spin_lock_init(&kona_gpio->lock);
  
  	return 0;
  
  err_irq_domain:
  	irq_domain_remove(kona_gpio->irq_domain);
  
  	return ret;
  }
  
  static struct platform_driver bcm_kona_gpio_driver = {
  	.driver = {
  			.name = "bcm-kona-gpio",
757651e3d   Markus Mayer   gpio: bcm281xx: A...
632
633
634
635
  			.of_match_table = bcm_kona_gpio_of_match,
  	},
  	.probe = bcm_kona_gpio_probe,
  };
8f3e19fae   Paul Gortmaker   gpio: bcm-kona: m...
636
  builtin_platform_driver(bcm_kona_gpio_driver);