1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * arch/arm/mach-tegra/gpio.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2010 Google, Inc
6*4882a593Smuzhiyun * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Author:
9*4882a593Smuzhiyun * Erik Gilling <konkers@google.com>
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/irq.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/io.h>
17*4882a593Smuzhiyun #include <linux/gpio/driver.h>
18*4882a593Smuzhiyun #include <linux/of_device.h>
19*4882a593Smuzhiyun #include <linux/platform_device.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun #include <linux/irqdomain.h>
22*4882a593Smuzhiyun #include <linux/irqchip/chained_irq.h>
23*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
24*4882a593Smuzhiyun #include <linux/pm.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #define GPIO_BANK(x) ((x) >> 5)
27*4882a593Smuzhiyun #define GPIO_PORT(x) (((x) >> 3) & 0x3)
28*4882a593Smuzhiyun #define GPIO_BIT(x) ((x) & 0x7)
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define GPIO_REG(tgi, x) (GPIO_BANK(x) * tgi->soc->bank_stride + \
31*4882a593Smuzhiyun GPIO_PORT(x) * 4)
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define GPIO_CNF(t, x) (GPIO_REG(t, x) + 0x00)
34*4882a593Smuzhiyun #define GPIO_OE(t, x) (GPIO_REG(t, x) + 0x10)
35*4882a593Smuzhiyun #define GPIO_OUT(t, x) (GPIO_REG(t, x) + 0X20)
36*4882a593Smuzhiyun #define GPIO_IN(t, x) (GPIO_REG(t, x) + 0x30)
37*4882a593Smuzhiyun #define GPIO_INT_STA(t, x) (GPIO_REG(t, x) + 0x40)
38*4882a593Smuzhiyun #define GPIO_INT_ENB(t, x) (GPIO_REG(t, x) + 0x50)
39*4882a593Smuzhiyun #define GPIO_INT_LVL(t, x) (GPIO_REG(t, x) + 0x60)
40*4882a593Smuzhiyun #define GPIO_INT_CLR(t, x) (GPIO_REG(t, x) + 0x70)
41*4882a593Smuzhiyun #define GPIO_DBC_CNT(t, x) (GPIO_REG(t, x) + 0xF0)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #define GPIO_MSK_CNF(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x00)
45*4882a593Smuzhiyun #define GPIO_MSK_OE(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x10)
46*4882a593Smuzhiyun #define GPIO_MSK_OUT(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0X20)
47*4882a593Smuzhiyun #define GPIO_MSK_DBC_EN(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x30)
48*4882a593Smuzhiyun #define GPIO_MSK_INT_STA(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x40)
49*4882a593Smuzhiyun #define GPIO_MSK_INT_ENB(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x50)
50*4882a593Smuzhiyun #define GPIO_MSK_INT_LVL(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x60)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define GPIO_INT_LVL_MASK 0x010101
53*4882a593Smuzhiyun #define GPIO_INT_LVL_EDGE_RISING 0x000101
54*4882a593Smuzhiyun #define GPIO_INT_LVL_EDGE_FALLING 0x000100
55*4882a593Smuzhiyun #define GPIO_INT_LVL_EDGE_BOTH 0x010100
56*4882a593Smuzhiyun #define GPIO_INT_LVL_LEVEL_HIGH 0x000001
57*4882a593Smuzhiyun #define GPIO_INT_LVL_LEVEL_LOW 0x000000
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun struct tegra_gpio_info;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun struct tegra_gpio_bank {
62*4882a593Smuzhiyun unsigned int bank;
63*4882a593Smuzhiyun unsigned int irq;
64*4882a593Smuzhiyun spinlock_t lvl_lock[4];
65*4882a593Smuzhiyun spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */
66*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
67*4882a593Smuzhiyun u32 cnf[4];
68*4882a593Smuzhiyun u32 out[4];
69*4882a593Smuzhiyun u32 oe[4];
70*4882a593Smuzhiyun u32 int_enb[4];
71*4882a593Smuzhiyun u32 int_lvl[4];
72*4882a593Smuzhiyun u32 wake_enb[4];
73*4882a593Smuzhiyun u32 dbc_enb[4];
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun u32 dbc_cnt[4];
76*4882a593Smuzhiyun struct tegra_gpio_info *tgi;
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun struct tegra_gpio_soc_config {
80*4882a593Smuzhiyun bool debounce_supported;
81*4882a593Smuzhiyun u32 bank_stride;
82*4882a593Smuzhiyun u32 upper_offset;
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun struct tegra_gpio_info {
86*4882a593Smuzhiyun struct device *dev;
87*4882a593Smuzhiyun void __iomem *regs;
88*4882a593Smuzhiyun struct irq_domain *irq_domain;
89*4882a593Smuzhiyun struct tegra_gpio_bank *bank_info;
90*4882a593Smuzhiyun const struct tegra_gpio_soc_config *soc;
91*4882a593Smuzhiyun struct gpio_chip gc;
92*4882a593Smuzhiyun struct irq_chip ic;
93*4882a593Smuzhiyun u32 bank_count;
94*4882a593Smuzhiyun };
95*4882a593Smuzhiyun
tegra_gpio_writel(struct tegra_gpio_info * tgi,u32 val,u32 reg)96*4882a593Smuzhiyun static inline void tegra_gpio_writel(struct tegra_gpio_info *tgi,
97*4882a593Smuzhiyun u32 val, u32 reg)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun writel_relaxed(val, tgi->regs + reg);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
tegra_gpio_readl(struct tegra_gpio_info * tgi,u32 reg)102*4882a593Smuzhiyun static inline u32 tegra_gpio_readl(struct tegra_gpio_info *tgi, u32 reg)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun return readl_relaxed(tgi->regs + reg);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
tegra_gpio_compose(unsigned int bank,unsigned int port,unsigned int bit)107*4882a593Smuzhiyun static unsigned int tegra_gpio_compose(unsigned int bank, unsigned int port,
108*4882a593Smuzhiyun unsigned int bit)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
tegra_gpio_mask_write(struct tegra_gpio_info * tgi,u32 reg,unsigned int gpio,u32 value)113*4882a593Smuzhiyun static void tegra_gpio_mask_write(struct tegra_gpio_info *tgi, u32 reg,
114*4882a593Smuzhiyun unsigned int gpio, u32 value)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun u32 val;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun val = 0x100 << GPIO_BIT(gpio);
119*4882a593Smuzhiyun if (value)
120*4882a593Smuzhiyun val |= 1 << GPIO_BIT(gpio);
121*4882a593Smuzhiyun tegra_gpio_writel(tgi, val, reg);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
tegra_gpio_enable(struct tegra_gpio_info * tgi,unsigned int gpio)124*4882a593Smuzhiyun static void tegra_gpio_enable(struct tegra_gpio_info *tgi, unsigned int gpio)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 1);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
tegra_gpio_disable(struct tegra_gpio_info * tgi,unsigned int gpio)129*4882a593Smuzhiyun static void tegra_gpio_disable(struct tegra_gpio_info *tgi, unsigned int gpio)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 0);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
tegra_gpio_request(struct gpio_chip * chip,unsigned int offset)134*4882a593Smuzhiyun static int tegra_gpio_request(struct gpio_chip *chip, unsigned int offset)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun return pinctrl_gpio_request(chip->base + offset);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
tegra_gpio_free(struct gpio_chip * chip,unsigned int offset)139*4882a593Smuzhiyun static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun pinctrl_gpio_free(chip->base + offset);
144*4882a593Smuzhiyun tegra_gpio_disable(tgi, offset);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
tegra_gpio_set(struct gpio_chip * chip,unsigned int offset,int value)147*4882a593Smuzhiyun static void tegra_gpio_set(struct gpio_chip *chip, unsigned int offset,
148*4882a593Smuzhiyun int value)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_OUT(tgi, offset), offset, value);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
tegra_gpio_get(struct gpio_chip * chip,unsigned int offset)155*4882a593Smuzhiyun static int tegra_gpio_get(struct gpio_chip *chip, unsigned int offset)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
158*4882a593Smuzhiyun unsigned int bval = BIT(GPIO_BIT(offset));
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* If gpio is in output mode then read from the out value */
161*4882a593Smuzhiyun if (tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)) & bval)
162*4882a593Smuzhiyun return !!(tegra_gpio_readl(tgi, GPIO_OUT(tgi, offset)) & bval);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun return !!(tegra_gpio_readl(tgi, GPIO_IN(tgi, offset)) & bval);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
tegra_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)167*4882a593Smuzhiyun static int tegra_gpio_direction_input(struct gpio_chip *chip,
168*4882a593Smuzhiyun unsigned int offset)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
171*4882a593Smuzhiyun int ret;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
174*4882a593Smuzhiyun tegra_gpio_enable(tgi, offset);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun ret = pinctrl_gpio_direction_input(chip->base + offset);
177*4882a593Smuzhiyun if (ret < 0)
178*4882a593Smuzhiyun dev_err(tgi->dev,
179*4882a593Smuzhiyun "Failed to set pinctrl input direction of GPIO %d: %d",
180*4882a593Smuzhiyun chip->base + offset, ret);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun return ret;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
tegra_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)185*4882a593Smuzhiyun static int tegra_gpio_direction_output(struct gpio_chip *chip,
186*4882a593Smuzhiyun unsigned int offset,
187*4882a593Smuzhiyun int value)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
190*4882a593Smuzhiyun int ret;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun tegra_gpio_set(chip, offset, value);
193*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
194*4882a593Smuzhiyun tegra_gpio_enable(tgi, offset);
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun ret = pinctrl_gpio_direction_output(chip->base + offset);
197*4882a593Smuzhiyun if (ret < 0)
198*4882a593Smuzhiyun dev_err(tgi->dev,
199*4882a593Smuzhiyun "Failed to set pinctrl output direction of GPIO %d: %d",
200*4882a593Smuzhiyun chip->base + offset, ret);
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun return ret;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
tegra_gpio_get_direction(struct gpio_chip * chip,unsigned int offset)205*4882a593Smuzhiyun static int tegra_gpio_get_direction(struct gpio_chip *chip,
206*4882a593Smuzhiyun unsigned int offset)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
209*4882a593Smuzhiyun u32 pin_mask = BIT(GPIO_BIT(offset));
210*4882a593Smuzhiyun u32 cnf, oe;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun cnf = tegra_gpio_readl(tgi, GPIO_CNF(tgi, offset));
213*4882a593Smuzhiyun if (!(cnf & pin_mask))
214*4882a593Smuzhiyun return -EINVAL;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset));
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (oe & pin_mask)
219*4882a593Smuzhiyun return GPIO_LINE_DIRECTION_OUT;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun return GPIO_LINE_DIRECTION_IN;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
tegra_gpio_set_debounce(struct gpio_chip * chip,unsigned int offset,unsigned int debounce)224*4882a593Smuzhiyun static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
225*4882a593Smuzhiyun unsigned int debounce)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
228*4882a593Smuzhiyun struct tegra_gpio_bank *bank = &tgi->bank_info[GPIO_BANK(offset)];
229*4882a593Smuzhiyun unsigned int debounce_ms = DIV_ROUND_UP(debounce, 1000);
230*4882a593Smuzhiyun unsigned long flags;
231*4882a593Smuzhiyun unsigned int port;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun if (!debounce_ms) {
234*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset),
235*4882a593Smuzhiyun offset, 0);
236*4882a593Smuzhiyun return 0;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun debounce_ms = min(debounce_ms, 255U);
240*4882a593Smuzhiyun port = GPIO_PORT(offset);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* There is only one debounce count register per port and hence
243*4882a593Smuzhiyun * set the maximum of current and requested debounce time.
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun spin_lock_irqsave(&bank->dbc_lock[port], flags);
246*4882a593Smuzhiyun if (bank->dbc_cnt[port] < debounce_ms) {
247*4882a593Smuzhiyun tegra_gpio_writel(tgi, debounce_ms, GPIO_DBC_CNT(tgi, offset));
248*4882a593Smuzhiyun bank->dbc_cnt[port] = debounce_ms;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun spin_unlock_irqrestore(&bank->dbc_lock[port], flags);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), offset, 1);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return 0;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
tegra_gpio_set_config(struct gpio_chip * chip,unsigned int offset,unsigned long config)257*4882a593Smuzhiyun static int tegra_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
258*4882a593Smuzhiyun unsigned long config)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun u32 debounce;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
263*4882a593Smuzhiyun return -ENOTSUPP;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun debounce = pinconf_to_config_argument(config);
266*4882a593Smuzhiyun return tegra_gpio_set_debounce(chip, offset, debounce);
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
tegra_gpio_to_irq(struct gpio_chip * chip,unsigned int offset)269*4882a593Smuzhiyun static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun return irq_find_mapping(tgi->irq_domain, offset);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
tegra_gpio_irq_ack(struct irq_data * d)276*4882a593Smuzhiyun static void tegra_gpio_irq_ack(struct irq_data *d)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
279*4882a593Smuzhiyun struct tegra_gpio_info *tgi = bank->tgi;
280*4882a593Smuzhiyun unsigned int gpio = d->hwirq;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun tegra_gpio_writel(tgi, 1 << GPIO_BIT(gpio), GPIO_INT_CLR(tgi, gpio));
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
tegra_gpio_irq_mask(struct irq_data * d)285*4882a593Smuzhiyun static void tegra_gpio_irq_mask(struct irq_data *d)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
288*4882a593Smuzhiyun struct tegra_gpio_info *tgi = bank->tgi;
289*4882a593Smuzhiyun unsigned int gpio = d->hwirq;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 0);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
tegra_gpio_irq_unmask(struct irq_data * d)294*4882a593Smuzhiyun static void tegra_gpio_irq_unmask(struct irq_data *d)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
297*4882a593Smuzhiyun struct tegra_gpio_info *tgi = bank->tgi;
298*4882a593Smuzhiyun unsigned int gpio = d->hwirq;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 1);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
tegra_gpio_irq_set_type(struct irq_data * d,unsigned int type)303*4882a593Smuzhiyun static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun unsigned int gpio = d->hwirq, port = GPIO_PORT(gpio), lvl_type;
306*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
307*4882a593Smuzhiyun struct tegra_gpio_info *tgi = bank->tgi;
308*4882a593Smuzhiyun unsigned long flags;
309*4882a593Smuzhiyun u32 val;
310*4882a593Smuzhiyun int ret;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun switch (type & IRQ_TYPE_SENSE_MASK) {
313*4882a593Smuzhiyun case IRQ_TYPE_EDGE_RISING:
314*4882a593Smuzhiyun lvl_type = GPIO_INT_LVL_EDGE_RISING;
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun case IRQ_TYPE_EDGE_FALLING:
318*4882a593Smuzhiyun lvl_type = GPIO_INT_LVL_EDGE_FALLING;
319*4882a593Smuzhiyun break;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun case IRQ_TYPE_EDGE_BOTH:
322*4882a593Smuzhiyun lvl_type = GPIO_INT_LVL_EDGE_BOTH;
323*4882a593Smuzhiyun break;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun case IRQ_TYPE_LEVEL_HIGH:
326*4882a593Smuzhiyun lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun case IRQ_TYPE_LEVEL_LOW:
330*4882a593Smuzhiyun lvl_type = GPIO_INT_LVL_LEVEL_LOW;
331*4882a593Smuzhiyun break;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun default:
334*4882a593Smuzhiyun return -EINVAL;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun spin_lock_irqsave(&bank->lvl_lock[port], flags);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
340*4882a593Smuzhiyun val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
341*4882a593Smuzhiyun val |= lvl_type << GPIO_BIT(gpio);
342*4882a593Smuzhiyun tegra_gpio_writel(tgi, val, GPIO_INT_LVL(tgi, gpio));
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0);
347*4882a593Smuzhiyun tegra_gpio_enable(tgi, gpio);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun ret = gpiochip_lock_as_irq(&tgi->gc, gpio);
350*4882a593Smuzhiyun if (ret) {
351*4882a593Smuzhiyun dev_err(tgi->dev,
352*4882a593Smuzhiyun "unable to lock Tegra GPIO %u as IRQ\n", gpio);
353*4882a593Smuzhiyun tegra_gpio_disable(tgi, gpio);
354*4882a593Smuzhiyun return ret;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
358*4882a593Smuzhiyun irq_set_handler_locked(d, handle_level_irq);
359*4882a593Smuzhiyun else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
360*4882a593Smuzhiyun irq_set_handler_locked(d, handle_edge_irq);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun return 0;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
tegra_gpio_irq_shutdown(struct irq_data * d)365*4882a593Smuzhiyun static void tegra_gpio_irq_shutdown(struct irq_data *d)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
368*4882a593Smuzhiyun struct tegra_gpio_info *tgi = bank->tgi;
369*4882a593Smuzhiyun unsigned int gpio = d->hwirq;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun tegra_gpio_irq_mask(d);
372*4882a593Smuzhiyun gpiochip_unlock_as_irq(&tgi->gc, gpio);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
tegra_gpio_irq_handler(struct irq_desc * desc)375*4882a593Smuzhiyun static void tegra_gpio_irq_handler(struct irq_desc *desc)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun unsigned int port, pin, gpio;
378*4882a593Smuzhiyun bool unmasked = false;
379*4882a593Smuzhiyun u32 lvl;
380*4882a593Smuzhiyun unsigned long sta;
381*4882a593Smuzhiyun struct irq_chip *chip = irq_desc_get_chip(desc);
382*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_desc_get_handler_data(desc);
383*4882a593Smuzhiyun struct tegra_gpio_info *tgi = bank->tgi;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun chained_irq_enter(chip, desc);
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun for (port = 0; port < 4; port++) {
388*4882a593Smuzhiyun gpio = tegra_gpio_compose(bank->bank, port, 0);
389*4882a593Smuzhiyun sta = tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)) &
390*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio));
391*4882a593Smuzhiyun lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun for_each_set_bit(pin, &sta, 8) {
394*4882a593Smuzhiyun tegra_gpio_writel(tgi, 1 << pin,
395*4882a593Smuzhiyun GPIO_INT_CLR(tgi, gpio));
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /* if gpio is edge triggered, clear condition
398*4882a593Smuzhiyun * before executing the handler so that we don't
399*4882a593Smuzhiyun * miss edges
400*4882a593Smuzhiyun */
401*4882a593Smuzhiyun if (!unmasked && lvl & (0x100 << pin)) {
402*4882a593Smuzhiyun unmasked = true;
403*4882a593Smuzhiyun chained_irq_exit(chip, desc);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun generic_handle_irq(irq_find_mapping(tgi->irq_domain,
407*4882a593Smuzhiyun gpio + pin));
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun if (!unmasked)
412*4882a593Smuzhiyun chained_irq_exit(chip, desc);
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
tegra_gpio_resume(struct device * dev)417*4882a593Smuzhiyun static int tegra_gpio_resume(struct device *dev)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun struct tegra_gpio_info *tgi = dev_get_drvdata(dev);
420*4882a593Smuzhiyun unsigned int b, p;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun for (b = 0; b < tgi->bank_count; b++) {
423*4882a593Smuzhiyun struct tegra_gpio_bank *bank = &tgi->bank_info[b];
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
426*4882a593Smuzhiyun unsigned int gpio = (b << 5) | (p << 3);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->cnf[p],
429*4882a593Smuzhiyun GPIO_CNF(tgi, gpio));
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun if (tgi->soc->debounce_supported) {
432*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->dbc_cnt[p],
433*4882a593Smuzhiyun GPIO_DBC_CNT(tgi, gpio));
434*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->dbc_enb[p],
435*4882a593Smuzhiyun GPIO_MSK_DBC_EN(tgi, gpio));
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->out[p],
439*4882a593Smuzhiyun GPIO_OUT(tgi, gpio));
440*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->oe[p],
441*4882a593Smuzhiyun GPIO_OE(tgi, gpio));
442*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->int_lvl[p],
443*4882a593Smuzhiyun GPIO_INT_LVL(tgi, gpio));
444*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->int_enb[p],
445*4882a593Smuzhiyun GPIO_INT_ENB(tgi, gpio));
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun return 0;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
tegra_gpio_suspend(struct device * dev)452*4882a593Smuzhiyun static int tegra_gpio_suspend(struct device *dev)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun struct tegra_gpio_info *tgi = dev_get_drvdata(dev);
455*4882a593Smuzhiyun unsigned int b, p;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun for (b = 0; b < tgi->bank_count; b++) {
458*4882a593Smuzhiyun struct tegra_gpio_bank *bank = &tgi->bank_info[b];
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
461*4882a593Smuzhiyun unsigned int gpio = (b << 5) | (p << 3);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun bank->cnf[p] = tegra_gpio_readl(tgi,
464*4882a593Smuzhiyun GPIO_CNF(tgi, gpio));
465*4882a593Smuzhiyun bank->out[p] = tegra_gpio_readl(tgi,
466*4882a593Smuzhiyun GPIO_OUT(tgi, gpio));
467*4882a593Smuzhiyun bank->oe[p] = tegra_gpio_readl(tgi,
468*4882a593Smuzhiyun GPIO_OE(tgi, gpio));
469*4882a593Smuzhiyun if (tgi->soc->debounce_supported) {
470*4882a593Smuzhiyun bank->dbc_enb[p] = tegra_gpio_readl(tgi,
471*4882a593Smuzhiyun GPIO_MSK_DBC_EN(tgi, gpio));
472*4882a593Smuzhiyun bank->dbc_enb[p] = (bank->dbc_enb[p] << 8) |
473*4882a593Smuzhiyun bank->dbc_enb[p];
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun bank->int_enb[p] = tegra_gpio_readl(tgi,
477*4882a593Smuzhiyun GPIO_INT_ENB(tgi, gpio));
478*4882a593Smuzhiyun bank->int_lvl[p] = tegra_gpio_readl(tgi,
479*4882a593Smuzhiyun GPIO_INT_LVL(tgi, gpio));
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /* Enable gpio irq for wake up source */
482*4882a593Smuzhiyun tegra_gpio_writel(tgi, bank->wake_enb[p],
483*4882a593Smuzhiyun GPIO_INT_ENB(tgi, gpio));
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
tegra_gpio_irq_set_wake(struct irq_data * d,unsigned int enable)490*4882a593Smuzhiyun static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
493*4882a593Smuzhiyun unsigned int gpio = d->hwirq;
494*4882a593Smuzhiyun u32 port, bit, mask;
495*4882a593Smuzhiyun int err;
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun err = irq_set_irq_wake(bank->irq, enable);
498*4882a593Smuzhiyun if (err)
499*4882a593Smuzhiyun return err;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun port = GPIO_PORT(gpio);
502*4882a593Smuzhiyun bit = GPIO_BIT(gpio);
503*4882a593Smuzhiyun mask = BIT(bit);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (enable)
506*4882a593Smuzhiyun bank->wake_enb[port] |= mask;
507*4882a593Smuzhiyun else
508*4882a593Smuzhiyun bank->wake_enb[port] &= ~mask;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun return 0;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun #endif
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun #include <linux/debugfs.h>
517*4882a593Smuzhiyun #include <linux/seq_file.h>
518*4882a593Smuzhiyun
tegra_dbg_gpio_show(struct seq_file * s,void * unused)519*4882a593Smuzhiyun static int tegra_dbg_gpio_show(struct seq_file *s, void *unused)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun struct tegra_gpio_info *tgi = s->private;
522*4882a593Smuzhiyun unsigned int i, j;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun for (i = 0; i < tgi->bank_count; i++) {
525*4882a593Smuzhiyun for (j = 0; j < 4; j++) {
526*4882a593Smuzhiyun unsigned int gpio = tegra_gpio_compose(i, j, 0);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun seq_printf(s,
529*4882a593Smuzhiyun "%u:%u %02x %02x %02x %02x %02x %02x %06x\n",
530*4882a593Smuzhiyun i, j,
531*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_CNF(tgi, gpio)),
532*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_OE(tgi, gpio)),
533*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_OUT(tgi, gpio)),
534*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_IN(tgi, gpio)),
535*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)),
536*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio)),
537*4882a593Smuzhiyun tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)));
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun return 0;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(tegra_dbg_gpio);
544*4882a593Smuzhiyun
tegra_gpio_debuginit(struct tegra_gpio_info * tgi)545*4882a593Smuzhiyun static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun debugfs_create_file("tegra_gpio", 0444, NULL, tgi,
548*4882a593Smuzhiyun &tegra_dbg_gpio_fops);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun #else
552*4882a593Smuzhiyun
tegra_gpio_debuginit(struct tegra_gpio_info * tgi)553*4882a593Smuzhiyun static inline void tegra_gpio_debuginit(struct tegra_gpio_info *tgi)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun #endif
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun static const struct dev_pm_ops tegra_gpio_pm_ops = {
560*4882a593Smuzhiyun SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
561*4882a593Smuzhiyun };
562*4882a593Smuzhiyun
tegra_gpio_probe(struct platform_device * pdev)563*4882a593Smuzhiyun static int tegra_gpio_probe(struct platform_device *pdev)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun struct tegra_gpio_info *tgi;
566*4882a593Smuzhiyun struct tegra_gpio_bank *bank;
567*4882a593Smuzhiyun unsigned int gpio, i, j;
568*4882a593Smuzhiyun int ret;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL);
571*4882a593Smuzhiyun if (!tgi)
572*4882a593Smuzhiyun return -ENODEV;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun tgi->soc = of_device_get_match_data(&pdev->dev);
575*4882a593Smuzhiyun tgi->dev = &pdev->dev;
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun ret = platform_irq_count(pdev);
578*4882a593Smuzhiyun if (ret < 0)
579*4882a593Smuzhiyun return ret;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun tgi->bank_count = ret;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun if (!tgi->bank_count) {
584*4882a593Smuzhiyun dev_err(&pdev->dev, "Missing IRQ resource\n");
585*4882a593Smuzhiyun return -ENODEV;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun tgi->gc.label = "tegra-gpio";
589*4882a593Smuzhiyun tgi->gc.request = tegra_gpio_request;
590*4882a593Smuzhiyun tgi->gc.free = tegra_gpio_free;
591*4882a593Smuzhiyun tgi->gc.direction_input = tegra_gpio_direction_input;
592*4882a593Smuzhiyun tgi->gc.get = tegra_gpio_get;
593*4882a593Smuzhiyun tgi->gc.direction_output = tegra_gpio_direction_output;
594*4882a593Smuzhiyun tgi->gc.set = tegra_gpio_set;
595*4882a593Smuzhiyun tgi->gc.get_direction = tegra_gpio_get_direction;
596*4882a593Smuzhiyun tgi->gc.to_irq = tegra_gpio_to_irq;
597*4882a593Smuzhiyun tgi->gc.base = 0;
598*4882a593Smuzhiyun tgi->gc.ngpio = tgi->bank_count * 32;
599*4882a593Smuzhiyun tgi->gc.parent = &pdev->dev;
600*4882a593Smuzhiyun tgi->gc.of_node = pdev->dev.of_node;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun tgi->ic.name = "GPIO";
603*4882a593Smuzhiyun tgi->ic.irq_ack = tegra_gpio_irq_ack;
604*4882a593Smuzhiyun tgi->ic.irq_mask = tegra_gpio_irq_mask;
605*4882a593Smuzhiyun tgi->ic.irq_unmask = tegra_gpio_irq_unmask;
606*4882a593Smuzhiyun tgi->ic.irq_set_type = tegra_gpio_irq_set_type;
607*4882a593Smuzhiyun tgi->ic.irq_shutdown = tegra_gpio_irq_shutdown;
608*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
609*4882a593Smuzhiyun tgi->ic.irq_set_wake = tegra_gpio_irq_set_wake;
610*4882a593Smuzhiyun #endif
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun platform_set_drvdata(pdev, tgi);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun if (tgi->soc->debounce_supported)
615*4882a593Smuzhiyun tgi->gc.set_config = tegra_gpio_set_config;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun tgi->bank_info = devm_kcalloc(&pdev->dev, tgi->bank_count,
618*4882a593Smuzhiyun sizeof(*tgi->bank_info), GFP_KERNEL);
619*4882a593Smuzhiyun if (!tgi->bank_info)
620*4882a593Smuzhiyun return -ENOMEM;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun tgi->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
623*4882a593Smuzhiyun tgi->gc.ngpio,
624*4882a593Smuzhiyun &irq_domain_simple_ops, NULL);
625*4882a593Smuzhiyun if (!tgi->irq_domain)
626*4882a593Smuzhiyun return -ENODEV;
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun for (i = 0; i < tgi->bank_count; i++) {
629*4882a593Smuzhiyun ret = platform_get_irq(pdev, i);
630*4882a593Smuzhiyun if (ret < 0)
631*4882a593Smuzhiyun return ret;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun bank = &tgi->bank_info[i];
634*4882a593Smuzhiyun bank->bank = i;
635*4882a593Smuzhiyun bank->irq = ret;
636*4882a593Smuzhiyun bank->tgi = tgi;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun tgi->regs = devm_platform_ioremap_resource(pdev, 0);
640*4882a593Smuzhiyun if (IS_ERR(tgi->regs))
641*4882a593Smuzhiyun return PTR_ERR(tgi->regs);
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun for (i = 0; i < tgi->bank_count; i++) {
644*4882a593Smuzhiyun for (j = 0; j < 4; j++) {
645*4882a593Smuzhiyun int gpio = tegra_gpio_compose(i, j, 0);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun tegra_gpio_writel(tgi, 0x00, GPIO_INT_ENB(tgi, gpio));
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun ret = devm_gpiochip_add_data(&pdev->dev, &tgi->gc, tgi);
652*4882a593Smuzhiyun if (ret < 0) {
653*4882a593Smuzhiyun irq_domain_remove(tgi->irq_domain);
654*4882a593Smuzhiyun return ret;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun for (gpio = 0; gpio < tgi->gc.ngpio; gpio++) {
658*4882a593Smuzhiyun int irq = irq_create_mapping(tgi->irq_domain, gpio);
659*4882a593Smuzhiyun /* No validity check; all Tegra GPIOs are valid IRQs */
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun bank = &tgi->bank_info[GPIO_BANK(gpio)];
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun irq_set_chip_data(irq, bank);
664*4882a593Smuzhiyun irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq);
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun for (i = 0; i < tgi->bank_count; i++) {
668*4882a593Smuzhiyun bank = &tgi->bank_info[i];
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun irq_set_chained_handler_and_data(bank->irq,
671*4882a593Smuzhiyun tegra_gpio_irq_handler, bank);
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun for (j = 0; j < 4; j++) {
674*4882a593Smuzhiyun spin_lock_init(&bank->lvl_lock[j]);
675*4882a593Smuzhiyun spin_lock_init(&bank->dbc_lock[j]);
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun tegra_gpio_debuginit(tgi);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun return 0;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun static const struct tegra_gpio_soc_config tegra20_gpio_config = {
685*4882a593Smuzhiyun .bank_stride = 0x80,
686*4882a593Smuzhiyun .upper_offset = 0x800,
687*4882a593Smuzhiyun };
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun static const struct tegra_gpio_soc_config tegra30_gpio_config = {
690*4882a593Smuzhiyun .bank_stride = 0x100,
691*4882a593Smuzhiyun .upper_offset = 0x80,
692*4882a593Smuzhiyun };
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun static const struct tegra_gpio_soc_config tegra210_gpio_config = {
695*4882a593Smuzhiyun .debounce_supported = true,
696*4882a593Smuzhiyun .bank_stride = 0x100,
697*4882a593Smuzhiyun .upper_offset = 0x80,
698*4882a593Smuzhiyun };
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun static const struct of_device_id tegra_gpio_of_match[] = {
701*4882a593Smuzhiyun { .compatible = "nvidia,tegra210-gpio", .data = &tegra210_gpio_config },
702*4882a593Smuzhiyun { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
703*4882a593Smuzhiyun { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
704*4882a593Smuzhiyun { },
705*4882a593Smuzhiyun };
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun static struct platform_driver tegra_gpio_driver = {
708*4882a593Smuzhiyun .driver = {
709*4882a593Smuzhiyun .name = "tegra-gpio",
710*4882a593Smuzhiyun .pm = &tegra_gpio_pm_ops,
711*4882a593Smuzhiyun .of_match_table = tegra_gpio_of_match,
712*4882a593Smuzhiyun },
713*4882a593Smuzhiyun .probe = tegra_gpio_probe,
714*4882a593Smuzhiyun };
715*4882a593Smuzhiyun
tegra_gpio_init(void)716*4882a593Smuzhiyun static int __init tegra_gpio_init(void)
717*4882a593Smuzhiyun {
718*4882a593Smuzhiyun return platform_driver_register(&tegra_gpio_driver);
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun subsys_initcall(tegra_gpio_init);
721