blob: b3968f66b1d2fd56f4dbe03c1324fca97b06a9f6 [file] [log] [blame]
Joel Stanley361b7912016-08-30 17:24:27 +09301/*
2 * Copyright 2015 IBM Corp.
3 *
4 * Joel Stanley <joel@jms.id.au>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093012#include <asm/div64.h>
13#include <linux/clk.h>
14#include <linux/gpio/driver.h>
15#include <linux/hashtable.h>
Joel Stanley361b7912016-08-30 17:24:27 +093016#include <linux/init.h>
17#include <linux/io.h>
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093018#include <linux/kernel.h>
19#include <linux/module.h>
Joel Stanley361b7912016-08-30 17:24:27 +093020#include <linux/pinctrl/consumer.h>
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093021#include <linux/platform_device.h>
22#include <linux/spinlock.h>
23#include <linux/string.h>
Joel Stanley361b7912016-08-30 17:24:27 +093024
Andrew Jeffery1736f752017-01-24 16:46:46 +103025struct aspeed_bank_props {
26 unsigned int bank;
27 u32 input;
28 u32 output;
29};
30
31struct aspeed_gpio_config {
32 unsigned int nr_gpios;
33 const struct aspeed_bank_props *props;
34};
35
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093036/*
37 * @offset_timer: Maps an offset to an @timer_users index, or zero if disabled
38 * @timer_users: Tracks the number of users for each timer
39 *
40 * The @timer_users has four elements but the first element is unused. This is
41 * to simplify accounting and indexing, as a zero value in @offset_timer
42 * represents disabled debouncing for the GPIO. Any other value for an element
43 * of @offset_timer is used as an index into @timer_users. This behaviour of
44 * the zero value aligns with the behaviour of zero built from the timer
45 * configuration registers (i.e. debouncing is disabled).
46 */
Joel Stanley361b7912016-08-30 17:24:27 +093047struct aspeed_gpio {
48 struct gpio_chip chip;
49 spinlock_t lock;
50 void __iomem *base;
51 int irq;
Andrew Jeffery1736f752017-01-24 16:46:46 +103052 const struct aspeed_gpio_config *config;
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093053
54 u8 *offset_timer;
55 unsigned int timer_users[4];
56 struct clk *clk;
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +100057
58 u32 *dcache;
Joel Stanley361b7912016-08-30 17:24:27 +093059};
60
61struct aspeed_gpio_bank {
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +100062 uint16_t val_regs; /* +0: Rd: read input value, Wr: set write latch
63 * +4: Rd/Wr: Direction (0=in, 1=out)
64 */
65 uint16_t rdata_reg; /* Rd: read write latch, Wr: <none> */
Joel Stanley361b7912016-08-30 17:24:27 +093066 uint16_t irq_regs;
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093067 uint16_t debounce_regs;
Andrew Jeffery1b43d262017-11-30 14:25:25 +103068 uint16_t tolerance_regs;
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +100069 uint16_t cmdsrc_regs;
Joel Stanley7153f8e2017-01-23 15:56:06 +103070 const char names[4][3];
Joel Stanley361b7912016-08-30 17:24:27 +093071};
72
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +100073/*
74 * Note: The "value" register returns the input value sampled on the
75 * line even when the GPIO is configured as an output. Since
76 * that input goes through synchronizers, writing, then reading
77 * back may not return the written value right away.
78 *
79 * The "rdata" register returns the content of the write latch
80 * and thus can be used to read back what was last written
81 * reliably.
82 */
83
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093084static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };
85
Joel Stanley361b7912016-08-30 17:24:27 +093086static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
87 {
88 .val_regs = 0x0000,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +100089 .rdata_reg = 0x00c0,
Joel Stanley361b7912016-08-30 17:24:27 +093090 .irq_regs = 0x0008,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +093091 .debounce_regs = 0x0040,
Andrew Jeffery1b43d262017-11-30 14:25:25 +103092 .tolerance_regs = 0x001c,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +100093 .cmdsrc_regs = 0x0060,
Joel Stanley7153f8e2017-01-23 15:56:06 +103094 .names = { "A", "B", "C", "D" },
Joel Stanley361b7912016-08-30 17:24:27 +093095 },
96 {
97 .val_regs = 0x0020,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +100098 .rdata_reg = 0x00c4,
Joel Stanley361b7912016-08-30 17:24:27 +093099 .irq_regs = 0x0028,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930100 .debounce_regs = 0x0048,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030101 .tolerance_regs = 0x003c,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000102 .cmdsrc_regs = 0x0068,
Joel Stanley7153f8e2017-01-23 15:56:06 +1030103 .names = { "E", "F", "G", "H" },
Joel Stanley361b7912016-08-30 17:24:27 +0930104 },
105 {
106 .val_regs = 0x0070,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000107 .rdata_reg = 0x00c8,
Joel Stanley361b7912016-08-30 17:24:27 +0930108 .irq_regs = 0x0098,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930109 .debounce_regs = 0x00b0,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030110 .tolerance_regs = 0x00ac,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000111 .cmdsrc_regs = 0x0090,
Joel Stanley7153f8e2017-01-23 15:56:06 +1030112 .names = { "I", "J", "K", "L" },
Joel Stanley361b7912016-08-30 17:24:27 +0930113 },
114 {
115 .val_regs = 0x0078,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000116 .rdata_reg = 0x00cc,
Joel Stanley361b7912016-08-30 17:24:27 +0930117 .irq_regs = 0x00e8,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930118 .debounce_regs = 0x0100,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030119 .tolerance_regs = 0x00fc,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000120 .cmdsrc_regs = 0x00e0,
Joel Stanley7153f8e2017-01-23 15:56:06 +1030121 .names = { "M", "N", "O", "P" },
Joel Stanley361b7912016-08-30 17:24:27 +0930122 },
123 {
124 .val_regs = 0x0080,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000125 .rdata_reg = 0x00d0,
Joel Stanley361b7912016-08-30 17:24:27 +0930126 .irq_regs = 0x0118,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930127 .debounce_regs = 0x0130,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030128 .tolerance_regs = 0x012c,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000129 .cmdsrc_regs = 0x0110,
Joel Stanley7153f8e2017-01-23 15:56:06 +1030130 .names = { "Q", "R", "S", "T" },
Joel Stanley361b7912016-08-30 17:24:27 +0930131 },
132 {
133 .val_regs = 0x0088,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000134 .rdata_reg = 0x00d4,
Joel Stanley361b7912016-08-30 17:24:27 +0930135 .irq_regs = 0x0148,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930136 .debounce_regs = 0x0160,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030137 .tolerance_regs = 0x015c,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000138 .cmdsrc_regs = 0x0140,
Joel Stanley7153f8e2017-01-23 15:56:06 +1030139 .names = { "U", "V", "W", "X" },
Joel Stanley361b7912016-08-30 17:24:27 +0930140 },
Andrew Jeffery1736f752017-01-24 16:46:46 +1030141 {
142 .val_regs = 0x01E0,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000143 .rdata_reg = 0x00d8,
Andrew Jeffery1736f752017-01-24 16:46:46 +1030144 .irq_regs = 0x0178,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930145 .debounce_regs = 0x0190,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030146 .tolerance_regs = 0x018c,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000147 .cmdsrc_regs = 0x0170,
Andrew Jeffery1736f752017-01-24 16:46:46 +1030148 .names = { "Y", "Z", "AA", "AB" },
149 },
150 {
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030151 .val_regs = 0x01e8,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000152 .rdata_reg = 0x00dc,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030153 .irq_regs = 0x01a8,
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930154 .debounce_regs = 0x01c0,
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030155 .tolerance_regs = 0x01bc,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000156 .cmdsrc_regs = 0x01a0,
Andrew Jeffery1736f752017-01-24 16:46:46 +1030157 .names = { "AC", "", "", "" },
158 },
Joel Stanley361b7912016-08-30 17:24:27 +0930159};
160
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000161enum aspeed_gpio_reg {
162 reg_val,
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000163 reg_rdata,
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000164 reg_dir,
165 reg_irq_enable,
166 reg_irq_type0,
167 reg_irq_type1,
168 reg_irq_type2,
169 reg_irq_status,
170 reg_debounce_sel1,
171 reg_debounce_sel2,
172 reg_tolerance,
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000173 reg_cmdsrc0,
174 reg_cmdsrc1,
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000175};
Joel Stanley361b7912016-08-30 17:24:27 +0930176
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000177#define GPIO_VAL_VALUE 0x00
178#define GPIO_VAL_DIR 0x04
Joel Stanley361b7912016-08-30 17:24:27 +0930179
180#define GPIO_IRQ_ENABLE 0x00
181#define GPIO_IRQ_TYPE0 0x04
182#define GPIO_IRQ_TYPE1 0x08
183#define GPIO_IRQ_TYPE2 0x0c
184#define GPIO_IRQ_STATUS 0x10
185
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930186#define GPIO_DEBOUNCE_SEL1 0x00
187#define GPIO_DEBOUNCE_SEL2 0x04
188
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000189#define GPIO_CMDSRC_0 0x00
190#define GPIO_CMDSRC_1 0x04
191#define GPIO_CMDSRC_ARM 0
192#define GPIO_CMDSRC_LPC 1
193#define GPIO_CMDSRC_COLDFIRE 2
194#define GPIO_CMDSRC_RESERVED 3
195
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000196/* This will be resolved at compile time */
197static inline void __iomem *bank_reg(struct aspeed_gpio *gpio,
198 const struct aspeed_gpio_bank *bank,
199 const enum aspeed_gpio_reg reg)
200{
201 switch (reg) {
202 case reg_val:
203 return gpio->base + bank->val_regs + GPIO_VAL_VALUE;
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +1000204 case reg_rdata:
205 return gpio->base + bank->rdata_reg;
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000206 case reg_dir:
207 return gpio->base + bank->val_regs + GPIO_VAL_DIR;
208 case reg_irq_enable:
209 return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE;
210 case reg_irq_type0:
211 return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0;
212 case reg_irq_type1:
213 return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1;
214 case reg_irq_type2:
215 return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
216 case reg_irq_status:
217 return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
218 case reg_debounce_sel1:
219 return gpio->base + bank->debounce_regs + GPIO_DEBOUNCE_SEL1;
220 case reg_debounce_sel2:
221 return gpio->base + bank->debounce_regs + GPIO_DEBOUNCE_SEL2;
222 case reg_tolerance:
223 return gpio->base + bank->tolerance_regs;
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000224 case reg_cmdsrc0:
225 return gpio->base + bank->cmdsrc_regs + GPIO_CMDSRC_0;
226 case reg_cmdsrc1:
227 return gpio->base + bank->cmdsrc_regs + GPIO_CMDSRC_1;
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000228 }
229 BUG_ON(1);
230}
231
232#define GPIO_BANK(x) ((x) >> 5)
233#define GPIO_OFFSET(x) ((x) & 0x1f)
234#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
235
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930236#define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o))
237#define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1)
238#define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0)
239
Joel Stanley361b7912016-08-30 17:24:27 +0930240static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
241{
242 unsigned int bank = GPIO_BANK(offset);
243
Vasyl Gomonovychfe138622017-12-21 16:55:10 +0100244 WARN_ON(bank >= ARRAY_SIZE(aspeed_gpio_banks));
Joel Stanley361b7912016-08-30 17:24:27 +0930245 return &aspeed_gpio_banks[bank];
246}
247
Andrew Jeffery1736f752017-01-24 16:46:46 +1030248static inline bool is_bank_props_sentinel(const struct aspeed_bank_props *props)
249{
250 return !(props->input || props->output);
251}
252
253static inline const struct aspeed_bank_props *find_bank_props(
254 struct aspeed_gpio *gpio, unsigned int offset)
255{
256 const struct aspeed_bank_props *props = gpio->config->props;
257
258 while (!is_bank_props_sentinel(props)) {
259 if (props->bank == GPIO_BANK(offset))
260 return props;
261 props++;
262 }
263
264 return NULL;
265}
266
267static inline bool have_gpio(struct aspeed_gpio *gpio, unsigned int offset)
268{
269 const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
270 const struct aspeed_gpio_bank *bank = to_bank(offset);
271 unsigned int group = GPIO_OFFSET(offset) / 8;
272
273 return bank->names[group][0] != '\0' &&
274 (!props || ((props->input | props->output) & GPIO_BIT(offset)));
275}
276
277static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
278{
279 const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
280
281 return !props || (props->input & GPIO_BIT(offset));
282}
283
284#define have_irq(g, o) have_input((g), (o))
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930285#define have_debounce(g, o) have_input((g), (o))
Andrew Jeffery1736f752017-01-24 16:46:46 +1030286
287static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
288{
289 const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
290
291 return !props || (props->output & GPIO_BIT(offset));
292}
293
Benjamin Herrenschmidt0f1e03c2018-06-29 14:11:18 +1000294static void aspeed_gpio_change_cmd_source(struct aspeed_gpio *gpio,
295 const struct aspeed_gpio_bank *bank,
296 int bindex, int cmdsrc)
297{
298 void __iomem *c0 = bank_reg(gpio, bank, reg_cmdsrc0);
299 void __iomem *c1 = bank_reg(gpio, bank, reg_cmdsrc1);
300 u32 bit, reg;
301
302 /*
303 * Each register controls 4 banks, so take the bottom 2
304 * bits of the bank index, and use them to select the
305 * right control bit (0, 8, 16 or 24).
306 */
307 bit = BIT((bindex & 3) << 3);
308
309 /* Source 1 first to avoid illegal 11 combination */
310 reg = ioread32(c1);
311 if (cmdsrc & 2)
312 reg |= bit;
313 else
314 reg &= ~bit;
315 iowrite32(reg, c1);
316
317 /* Then Source 0 */
318 reg = ioread32(c0);
319 if (cmdsrc & 1)
320 reg |= bit;
321 else
322 reg &= ~bit;
323 iowrite32(reg, c0);
324}
325
Joel Stanley361b7912016-08-30 17:24:27 +0930326static int aspeed_gpio_get(struct gpio_chip *gc, unsigned int offset)
327{
328 struct aspeed_gpio *gpio = gpiochip_get_data(gc);
329 const struct aspeed_gpio_bank *bank = to_bank(offset);
330
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000331 return !!(ioread32(bank_reg(gpio, bank, reg_val)) & GPIO_BIT(offset));
Joel Stanley361b7912016-08-30 17:24:27 +0930332}
333
334static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
335 int val)
336{
337 struct aspeed_gpio *gpio = gpiochip_get_data(gc);
338 const struct aspeed_gpio_bank *bank = to_bank(offset);
339 void __iomem *addr;
340 u32 reg;
341
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000342 addr = bank_reg(gpio, bank, reg_val);
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +1000343 reg = gpio->dcache[GPIO_BANK(offset)];
Joel Stanley361b7912016-08-30 17:24:27 +0930344
345 if (val)
346 reg |= GPIO_BIT(offset);
347 else
348 reg &= ~GPIO_BIT(offset);
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +1000349 gpio->dcache[GPIO_BANK(offset)] = reg;
Joel Stanley361b7912016-08-30 17:24:27 +0930350
351 iowrite32(reg, addr);
352}
353
354static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
355 int val)
356{
357 struct aspeed_gpio *gpio = gpiochip_get_data(gc);
358 unsigned long flags;
359
360 spin_lock_irqsave(&gpio->lock, flags);
361
362 __aspeed_gpio_set(gc, offset, val);
363
364 spin_unlock_irqrestore(&gpio->lock, flags);
365}
366
367static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
368{
369 struct aspeed_gpio *gpio = gpiochip_get_data(gc);
370 const struct aspeed_gpio_bank *bank = to_bank(offset);
371 unsigned long flags;
372 u32 reg;
373
Andrew Jeffery1736f752017-01-24 16:46:46 +1030374 if (!have_input(gpio, offset))
375 return -ENOTSUPP;
376
Joel Stanley361b7912016-08-30 17:24:27 +0930377 spin_lock_irqsave(&gpio->lock, flags);
378
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000379 reg = ioread32(bank_reg(gpio, bank, reg_dir));
380 iowrite32(reg & ~GPIO_BIT(offset), bank_reg(gpio, bank, reg_dir));
Joel Stanley361b7912016-08-30 17:24:27 +0930381
382 spin_unlock_irqrestore(&gpio->lock, flags);
383
384 return 0;
385}
386
387static int aspeed_gpio_dir_out(struct gpio_chip *gc,
388 unsigned int offset, int val)
389{
390 struct aspeed_gpio *gpio = gpiochip_get_data(gc);
391 const struct aspeed_gpio_bank *bank = to_bank(offset);
392 unsigned long flags;
393 u32 reg;
394
Andrew Jeffery1736f752017-01-24 16:46:46 +1030395 if (!have_output(gpio, offset))
396 return -ENOTSUPP;
397
Joel Stanley361b7912016-08-30 17:24:27 +0930398 spin_lock_irqsave(&gpio->lock, flags);
399
Benjamin Herrenschmidtaf794922018-05-17 18:11:56 +1000400 __aspeed_gpio_set(gc, offset, val);
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000401 reg = ioread32(bank_reg(gpio, bank, reg_dir));
402 iowrite32(reg | GPIO_BIT(offset), bank_reg(gpio, bank, reg_dir));
Joel Stanley361b7912016-08-30 17:24:27 +0930403
Joel Stanley361b7912016-08-30 17:24:27 +0930404 spin_unlock_irqrestore(&gpio->lock, flags);
405
406 return 0;
407}
408
409static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
410{
411 struct aspeed_gpio *gpio = gpiochip_get_data(gc);
412 const struct aspeed_gpio_bank *bank = to_bank(offset);
413 unsigned long flags;
414 u32 val;
415
Andrew Jeffery1736f752017-01-24 16:46:46 +1030416 if (!have_input(gpio, offset))
Andrew Jeffery619e96f2017-02-02 14:58:17 +1030417 return 0;
Andrew Jeffery1736f752017-01-24 16:46:46 +1030418
419 if (!have_output(gpio, offset))
Andrew Jeffery619e96f2017-02-02 14:58:17 +1030420 return 1;
Andrew Jeffery1736f752017-01-24 16:46:46 +1030421
Joel Stanley361b7912016-08-30 17:24:27 +0930422 spin_lock_irqsave(&gpio->lock, flags);
423
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000424 val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset);
Joel Stanley361b7912016-08-30 17:24:27 +0930425
426 spin_unlock_irqrestore(&gpio->lock, flags);
427
428 return !val;
429
430}
431
432static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
433 struct aspeed_gpio **gpio,
434 const struct aspeed_gpio_bank **bank,
435 u32 *bit)
436{
437 int offset;
Andrew Jeffery1736f752017-01-24 16:46:46 +1030438 struct aspeed_gpio *internal;
Joel Stanley361b7912016-08-30 17:24:27 +0930439
440 offset = irqd_to_hwirq(d);
441
Andrew Jeffery1736f752017-01-24 16:46:46 +1030442 internal = irq_data_get_irq_chip_data(d);
443
444 /* This might be a bit of a questionable place to check */
445 if (!have_irq(internal, offset))
446 return -ENOTSUPP;
447
448 *gpio = internal;
Joel Stanley361b7912016-08-30 17:24:27 +0930449 *bank = to_bank(offset);
450 *bit = GPIO_BIT(offset);
451
452 return 0;
453}
454
455static void aspeed_gpio_irq_ack(struct irq_data *d)
456{
457 const struct aspeed_gpio_bank *bank;
458 struct aspeed_gpio *gpio;
459 unsigned long flags;
460 void __iomem *status_addr;
461 u32 bit;
462 int rc;
463
464 rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit);
465 if (rc)
466 return;
467
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000468 status_addr = bank_reg(gpio, bank, reg_irq_status);
Joel Stanley361b7912016-08-30 17:24:27 +0930469
470 spin_lock_irqsave(&gpio->lock, flags);
471 iowrite32(bit, status_addr);
472 spin_unlock_irqrestore(&gpio->lock, flags);
473}
474
475static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
476{
477 const struct aspeed_gpio_bank *bank;
478 struct aspeed_gpio *gpio;
479 unsigned long flags;
480 u32 reg, bit;
481 void __iomem *addr;
482 int rc;
483
484 rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit);
485 if (rc)
486 return;
487
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000488 addr = bank_reg(gpio, bank, reg_irq_enable);
Joel Stanley361b7912016-08-30 17:24:27 +0930489
490 spin_lock_irqsave(&gpio->lock, flags);
491
492 reg = ioread32(addr);
493 if (set)
494 reg |= bit;
495 else
Govert Overgaauwf2416322018-04-06 14:41:35 +0200496 reg &= ~bit;
Joel Stanley361b7912016-08-30 17:24:27 +0930497 iowrite32(reg, addr);
498
499 spin_unlock_irqrestore(&gpio->lock, flags);
500}
501
502static void aspeed_gpio_irq_mask(struct irq_data *d)
503{
504 aspeed_gpio_irq_set_mask(d, false);
505}
506
507static void aspeed_gpio_irq_unmask(struct irq_data *d)
508{
509 aspeed_gpio_irq_set_mask(d, true);
510}
511
512static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
513{
514 u32 type0 = 0;
515 u32 type1 = 0;
516 u32 type2 = 0;
517 u32 bit, reg;
518 const struct aspeed_gpio_bank *bank;
519 irq_flow_handler_t handler;
520 struct aspeed_gpio *gpio;
521 unsigned long flags;
522 void __iomem *addr;
523 int rc;
524
525 rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit);
526 if (rc)
527 return -EINVAL;
528
529 switch (type & IRQ_TYPE_SENSE_MASK) {
530 case IRQ_TYPE_EDGE_BOTH:
531 type2 |= bit;
Gustavo A. R. Silvae80df7b2017-10-13 15:43:53 -0500532 /* fall through */
Joel Stanley361b7912016-08-30 17:24:27 +0930533 case IRQ_TYPE_EDGE_RISING:
534 type0 |= bit;
Gustavo A. R. Silvae80df7b2017-10-13 15:43:53 -0500535 /* fall through */
Joel Stanley361b7912016-08-30 17:24:27 +0930536 case IRQ_TYPE_EDGE_FALLING:
537 handler = handle_edge_irq;
538 break;
539 case IRQ_TYPE_LEVEL_HIGH:
540 type0 |= bit;
Gustavo A. R. Silvae80df7b2017-10-13 15:43:53 -0500541 /* fall through */
Joel Stanley361b7912016-08-30 17:24:27 +0930542 case IRQ_TYPE_LEVEL_LOW:
543 type1 |= bit;
544 handler = handle_level_irq;
545 break;
546 default:
547 return -EINVAL;
548 }
549
550 spin_lock_irqsave(&gpio->lock, flags);
551
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000552 addr = bank_reg(gpio, bank, reg_irq_type0);
Joel Stanley361b7912016-08-30 17:24:27 +0930553 reg = ioread32(addr);
554 reg = (reg & ~bit) | type0;
555 iowrite32(reg, addr);
556
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000557 addr = bank_reg(gpio, bank, reg_irq_type1);
Joel Stanley361b7912016-08-30 17:24:27 +0930558 reg = ioread32(addr);
559 reg = (reg & ~bit) | type1;
560 iowrite32(reg, addr);
561
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000562 addr = bank_reg(gpio, bank, reg_irq_type2);
Joel Stanley361b7912016-08-30 17:24:27 +0930563 reg = ioread32(addr);
564 reg = (reg & ~bit) | type2;
565 iowrite32(reg, addr);
566
567 spin_unlock_irqrestore(&gpio->lock, flags);
568
569 irq_set_handler_locked(d, handler);
570
571 return 0;
572}
573
574static void aspeed_gpio_irq_handler(struct irq_desc *desc)
575{
576 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
577 struct irq_chip *ic = irq_desc_get_chip(desc);
578 struct aspeed_gpio *data = gpiochip_get_data(gc);
579 unsigned int i, p, girq;
580 unsigned long reg;
581
582 chained_irq_enter(ic, desc);
583
584 for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) {
585 const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
586
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000587 reg = ioread32(bank_reg(data, bank, reg_irq_status));
Joel Stanley361b7912016-08-30 17:24:27 +0930588
589 for_each_set_bit(p, &reg, 32) {
Thierry Redingf0fbe7b2017-11-07 19:15:47 +0100590 girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
Joel Stanley361b7912016-08-30 17:24:27 +0930591 generic_handle_irq(girq);
592 }
593
594 }
595
596 chained_irq_exit(ic, desc);
597}
598
599static struct irq_chip aspeed_gpio_irqchip = {
600 .name = "aspeed-gpio",
601 .irq_ack = aspeed_gpio_irq_ack,
602 .irq_mask = aspeed_gpio_irq_mask,
603 .irq_unmask = aspeed_gpio_irq_unmask,
604 .irq_set_type = aspeed_gpio_set_type,
605};
606
Andrew Jeffery1736f752017-01-24 16:46:46 +1030607static void set_irq_valid_mask(struct aspeed_gpio *gpio)
608{
609 const struct aspeed_bank_props *props = gpio->config->props;
610
611 while (!is_bank_props_sentinel(props)) {
612 unsigned int offset;
613 const unsigned long int input = props->input;
614
615 /* Pretty crummy approach, but similar to GPIO core */
616 for_each_clear_bit(offset, &input, 32) {
617 unsigned int i = props->bank * 32 + offset;
618
619 if (i >= gpio->config->nr_gpios)
620 break;
621
Thierry Redingdc7b0382017-11-07 19:15:52 +0100622 clear_bit(i, gpio->chip.irq.valid_mask);
Andrew Jeffery1736f752017-01-24 16:46:46 +1030623 }
624
625 props++;
626 }
627}
628
Joel Stanley361b7912016-08-30 17:24:27 +0930629static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
630 struct platform_device *pdev)
631{
632 int rc;
633
634 rc = platform_get_irq(pdev, 0);
635 if (rc < 0)
636 return rc;
637
638 gpio->irq = rc;
639
Andrew Jeffery1736f752017-01-24 16:46:46 +1030640 set_irq_valid_mask(gpio);
641
Joel Stanley361b7912016-08-30 17:24:27 +0930642 rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
643 0, handle_bad_irq, IRQ_TYPE_NONE);
644 if (rc) {
645 dev_info(&pdev->dev, "Could not add irqchip\n");
646 return rc;
647 }
648
649 gpiochip_set_chained_irqchip(&gpio->chip, &aspeed_gpio_irqchip,
650 gpio->irq, aspeed_gpio_irq_handler);
651
652 return 0;
653}
654
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030655static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
656 unsigned int offset, bool enable)
657{
658 struct aspeed_gpio *gpio = gpiochip_get_data(chip);
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030659 unsigned long flags;
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000660 void __iomem *treg;
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030661 u32 val;
662
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000663 treg = bank_reg(gpio, to_bank(offset), reg_tolerance);
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030664
665 spin_lock_irqsave(&gpio->lock, flags);
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000666 val = readl(treg);
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030667
668 if (enable)
669 val |= GPIO_BIT(offset);
670 else
671 val &= ~GPIO_BIT(offset);
672
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000673 writel(val, treg);
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030674 spin_unlock_irqrestore(&gpio->lock, flags);
675
676 return 0;
677}
678
Joel Stanley361b7912016-08-30 17:24:27 +0930679static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
680{
Andrew Jeffery1736f752017-01-24 16:46:46 +1030681 if (!have_gpio(gpiochip_get_data(chip), offset))
682 return -ENODEV;
683
Linus Walleija9a1d2a2017-09-22 11:02:10 +0200684 return pinctrl_gpio_request(chip->base + offset);
Joel Stanley361b7912016-08-30 17:24:27 +0930685}
686
687static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
688{
Linus Walleija9a1d2a2017-09-22 11:02:10 +0200689 pinctrl_gpio_free(chip->base + offset);
Joel Stanley361b7912016-08-30 17:24:27 +0930690}
691
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930692static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs,
693 u32 *cycles)
694{
695 u64 rate;
696 u64 n;
697 u32 r;
698
699 rate = clk_get_rate(gpio->clk);
700 if (!rate)
701 return -ENOTSUPP;
702
703 n = rate * usecs;
704 r = do_div(n, 1000000);
705
706 if (n >= U32_MAX)
707 return -ERANGE;
708
709 /* At least as long as the requested time */
710 *cycles = n + (!!r);
711
712 return 0;
713}
714
715/* Call under gpio->lock */
716static int register_allocated_timer(struct aspeed_gpio *gpio,
717 unsigned int offset, unsigned int timer)
718{
719 if (WARN(gpio->offset_timer[offset] != 0,
720 "Offset %d already allocated timer %d\n",
721 offset, gpio->offset_timer[offset]))
722 return -EINVAL;
723
724 if (WARN(gpio->timer_users[timer] == UINT_MAX,
725 "Timer user count would overflow\n"))
726 return -EPERM;
727
728 gpio->offset_timer[offset] = timer;
729 gpio->timer_users[timer]++;
730
731 return 0;
732}
733
734/* Call under gpio->lock */
735static int unregister_allocated_timer(struct aspeed_gpio *gpio,
736 unsigned int offset)
737{
738 if (WARN(gpio->offset_timer[offset] == 0,
739 "No timer allocated to offset %d\n", offset))
740 return -EINVAL;
741
742 if (WARN(gpio->timer_users[gpio->offset_timer[offset]] == 0,
743 "No users recorded for timer %d\n",
744 gpio->offset_timer[offset]))
745 return -EINVAL;
746
747 gpio->timer_users[gpio->offset_timer[offset]]--;
748 gpio->offset_timer[offset] = 0;
749
750 return 0;
751}
752
753/* Call under gpio->lock */
754static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
755 unsigned int offset)
756{
757 return gpio->offset_timer[offset] > 0;
758}
759
760/* Call under gpio->lock */
761static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,
762 unsigned int timer)
763{
764 const struct aspeed_gpio_bank *bank = to_bank(offset);
765 const u32 mask = GPIO_BIT(offset);
766 void __iomem *addr;
767 u32 val;
768
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000769 addr = bank_reg(gpio, bank, reg_debounce_sel1);
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930770 val = ioread32(addr);
771 iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr);
772
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +1000773 addr = bank_reg(gpio, bank, reg_debounce_sel2);
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930774 val = ioread32(addr);
775 iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr);
776}
777
778static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
779 unsigned long usecs)
780{
781 struct aspeed_gpio *gpio = gpiochip_get_data(chip);
782 u32 requested_cycles;
783 unsigned long flags;
784 int rc;
785 int i;
786
Joel Stanleydf563c82017-05-02 15:38:24 +0930787 if (!gpio->clk)
788 return -EINVAL;
789
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930790 rc = usecs_to_cycles(gpio, usecs, &requested_cycles);
791 if (rc < 0) {
792 dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n",
793 usecs, clk_get_rate(gpio->clk), rc);
794 return rc;
795 }
796
797 spin_lock_irqsave(&gpio->lock, flags);
798
799 if (timer_allocation_registered(gpio, offset)) {
800 rc = unregister_allocated_timer(gpio, offset);
801 if (rc < 0)
802 goto out;
803 }
804
805 /* Try to find a timer already configured for the debounce period */
806 for (i = 1; i < ARRAY_SIZE(debounce_timers); i++) {
807 u32 cycles;
808
809 cycles = ioread32(gpio->base + debounce_timers[i]);
810 if (requested_cycles == cycles)
811 break;
812 }
813
814 if (i == ARRAY_SIZE(debounce_timers)) {
815 int j;
816
817 /*
818 * As there are no timers configured for the requested debounce
819 * period, find an unused timer instead
820 */
821 for (j = 1; j < ARRAY_SIZE(gpio->timer_users); j++) {
822 if (gpio->timer_users[j] == 0)
823 break;
824 }
825
826 if (j == ARRAY_SIZE(gpio->timer_users)) {
827 dev_warn(chip->parent,
828 "Debounce timers exhausted, cannot debounce for period %luus\n",
829 usecs);
830
831 rc = -EPERM;
832
833 /*
834 * We already adjusted the accounting to remove @offset
835 * as a user of its previous timer, so also configure
836 * the hardware so @offset has timers disabled for
837 * consistency.
838 */
839 configure_timer(gpio, offset, 0);
840 goto out;
841 }
842
843 i = j;
844
845 iowrite32(requested_cycles, gpio->base + debounce_timers[i]);
846 }
847
848 if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
849 rc = -EINVAL;
850 goto out;
851 }
852
853 register_allocated_timer(gpio, offset, i);
854 configure_timer(gpio, offset, i);
855
856out:
857 spin_unlock_irqrestore(&gpio->lock, flags);
858
859 return rc;
860}
861
862static int disable_debounce(struct gpio_chip *chip, unsigned int offset)
863{
864 struct aspeed_gpio *gpio = gpiochip_get_data(chip);
865 unsigned long flags;
866 int rc;
867
868 spin_lock_irqsave(&gpio->lock, flags);
869
870 rc = unregister_allocated_timer(gpio, offset);
871 if (!rc)
872 configure_timer(gpio, offset, 0);
873
874 spin_unlock_irqrestore(&gpio->lock, flags);
875
876 return rc;
877}
878
879static int set_debounce(struct gpio_chip *chip, unsigned int offset,
880 unsigned long usecs)
881{
882 struct aspeed_gpio *gpio = gpiochip_get_data(chip);
883
884 if (!have_debounce(gpio, offset))
885 return -ENOTSUPP;
886
887 if (usecs)
888 return enable_debounce(chip, offset, usecs);
889
890 return disable_debounce(chip, offset);
891}
892
893static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
894 unsigned long config)
895{
896 unsigned long param = pinconf_to_config_param(config);
897 u32 arg = pinconf_to_config_argument(config);
898
899 if (param == PIN_CONFIG_INPUT_DEBOUNCE)
900 return set_debounce(chip, offset, arg);
901 else if (param == PIN_CONFIG_BIAS_DISABLE ||
902 param == PIN_CONFIG_BIAS_PULL_DOWN ||
903 param == PIN_CONFIG_DRIVE_STRENGTH)
904 return pinctrl_gpio_set_config(offset, config);
Andrew Jefferyc3bafe02017-04-07 22:29:02 +0930905 else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
906 param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
907 /* Return -ENOTSUPP to trigger emulation, as per datasheet */
908 return -ENOTSUPP;
Andrew Jeffery1b43d262017-11-30 14:25:25 +1030909 else if (param == PIN_CONFIG_PERSIST_STATE)
910 return aspeed_gpio_reset_tolerance(chip, offset, arg);
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930911
912 return -ENOTSUPP;
913}
914
Andrew Jeffery1736f752017-01-24 16:46:46 +1030915/*
916 * Any banks not specified in a struct aspeed_bank_props array are assumed to
917 * have the properties:
918 *
919 * { .input = 0xffffffff, .output = 0xffffffff }
920 */
921
922static const struct aspeed_bank_props ast2400_bank_props[] = {
923 /* input output */
924 { 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
925 { 6, 0x0000000f, 0x0fffff0f }, /* Y/Z/AA/AB, two 4-GPIO holes */
926 { },
927};
928
929static const struct aspeed_gpio_config ast2400_config =
930 /* 220 for simplicity, really 216 with two 4-GPIO holes, four at end */
931 { .nr_gpios = 220, .props = ast2400_bank_props, };
932
933static const struct aspeed_bank_props ast2500_bank_props[] = {
934 /* input output */
935 { 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
936 { 6, 0x0fffffff, 0x0fffffff }, /* Y/Z/AA/AB, 4-GPIO hole */
937 { 7, 0x000000ff, 0x000000ff }, /* AC */
938 { },
939};
940
941static const struct aspeed_gpio_config ast2500_config =
942 /* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
943 { .nr_gpios = 232, .props = ast2500_bank_props, };
944
945static const struct of_device_id aspeed_gpio_of_table[] = {
946 { .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
947 { .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
948 {}
949};
950MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
951
Joel Stanley361b7912016-08-30 17:24:27 +0930952static int __init aspeed_gpio_probe(struct platform_device *pdev)
953{
Andrew Jeffery1736f752017-01-24 16:46:46 +1030954 const struct of_device_id *gpio_id;
Joel Stanley361b7912016-08-30 17:24:27 +0930955 struct aspeed_gpio *gpio;
956 struct resource *res;
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +1000957 int rc, i, banks;
Joel Stanley361b7912016-08-30 17:24:27 +0930958
959 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
960 if (!gpio)
961 return -ENOMEM;
962
963 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Joel Stanley361b7912016-08-30 17:24:27 +0930964 gpio->base = devm_ioremap_resource(&pdev->dev, res);
Wei Yongjun7f8b9652016-09-15 01:30:32 +0000965 if (IS_ERR(gpio->base))
966 return PTR_ERR(gpio->base);
Joel Stanley361b7912016-08-30 17:24:27 +0930967
968 spin_lock_init(&gpio->lock);
969
Andrew Jeffery1736f752017-01-24 16:46:46 +1030970 gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
971 if (!gpio_id)
972 return -EINVAL;
Joel Stanley361b7912016-08-30 17:24:27 +0930973
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930974 gpio->clk = of_clk_get(pdev->dev.of_node, 0);
975 if (IS_ERR(gpio->clk)) {
976 dev_warn(&pdev->dev,
Andrew Jeffery754c0452017-08-08 15:37:36 +0930977 "Failed to get clock from devicetree, debouncing disabled\n");
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930978 gpio->clk = NULL;
979 }
980
Andrew Jeffery1736f752017-01-24 16:46:46 +1030981 gpio->config = gpio_id->data;
982
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930983 gpio->chip.parent = &pdev->dev;
Andrew Jeffery1736f752017-01-24 16:46:46 +1030984 gpio->chip.ngpio = gpio->config->nr_gpios;
Joel Stanley361b7912016-08-30 17:24:27 +0930985 gpio->chip.parent = &pdev->dev;
986 gpio->chip.direction_input = aspeed_gpio_dir_in;
987 gpio->chip.direction_output = aspeed_gpio_dir_out;
988 gpio->chip.get_direction = aspeed_gpio_get_direction;
989 gpio->chip.request = aspeed_gpio_request;
990 gpio->chip.free = aspeed_gpio_free;
991 gpio->chip.get = aspeed_gpio_get;
992 gpio->chip.set = aspeed_gpio_set;
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +0930993 gpio->chip.set_config = aspeed_gpio_set_config;
Joel Stanley361b7912016-08-30 17:24:27 +0930994 gpio->chip.label = dev_name(&pdev->dev);
995 gpio->chip.base = -1;
Thierry Redingdc7b0382017-11-07 19:15:52 +0100996 gpio->chip.irq.need_valid_mask = true;
Joel Stanley361b7912016-08-30 17:24:27 +0930997
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +1000998 /* Allocate a cache of the output registers */
999 banks = gpio->config->nr_gpios >> 5;
Kees Cooka86854d2018-06-12 14:07:58 -07001000 gpio->dcache = devm_kcalloc(&pdev->dev,
1001 banks, sizeof(u32), GFP_KERNEL);
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +10001002 if (!gpio->dcache)
1003 return -ENOMEM;
1004
1005 /* Populate it with initial values read from the HW */
1006 for (i = 0; i < banks; i++) {
Benjamin Herrenschmidtc67dda82018-06-29 14:11:17 +10001007 void __iomem *addr = bank_reg(gpio, &aspeed_gpio_banks[i], reg_rdata);
Benjamin Herrenschmidt44ddf552018-06-29 14:11:16 +10001008 gpio->dcache[i] = ioread32(addr);
Benjamin Herrenschmidted5cab42018-05-17 18:12:02 +10001009 }
1010
Joel Stanley361b7912016-08-30 17:24:27 +09301011 rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
1012 if (rc < 0)
1013 return rc;
1014
Andrew Jeffery5ae4cb92017-04-07 22:29:01 +09301015 gpio->offset_timer =
1016 devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
1017
Joel Stanley361b7912016-08-30 17:24:27 +09301018 return aspeed_gpio_setup_irqs(gpio, pdev);
1019}
1020
Joel Stanley361b7912016-08-30 17:24:27 +09301021static struct platform_driver aspeed_gpio_driver = {
1022 .driver = {
1023 .name = KBUILD_MODNAME,
1024 .of_match_table = aspeed_gpio_of_table,
1025 },
1026};
1027
1028module_platform_driver_probe(aspeed_gpio_driver, aspeed_gpio_probe);
1029
1030MODULE_DESCRIPTION("Aspeed GPIO Driver");
Linus Walleije50237c2016-09-13 13:43:34 +02001031MODULE_LICENSE("GPL");