xref: /openbmc/linux/drivers/gpio/gpio-ftgpio010.c (revision 9d3a15aa)
1 /*
2  * Faraday Technolog FTGPIO010 gpiochip and interrupt routines
3  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
4  *
5  * Based on arch/arm/mach-gemini/gpio.c:
6  * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
7  *
8  * Based on plat-mxc/gpio.c:
9  * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
10  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
11  */
12 #include <linux/gpio/driver.h>
13 #include <linux/io.h>
14 #include <linux/interrupt.h>
15 #include <linux/platform_device.h>
16 #include <linux/of_gpio.h>
17 #include <linux/bitops.h>
18 
19 /* GPIO registers definition */
20 #define GPIO_DATA_OUT		0x00
21 #define GPIO_DATA_IN		0x04
22 #define GPIO_DIR		0x08
23 #define GPIO_DATA_SET		0x10
24 #define GPIO_DATA_CLR		0x14
25 #define GPIO_PULL_EN		0x18
26 #define GPIO_PULL_TYPE		0x1C
27 #define GPIO_INT_EN		0x20
28 #define GPIO_INT_STAT		0x24
29 #define GPIO_INT_MASK		0x2C
30 #define GPIO_INT_CLR		0x30
31 #define GPIO_INT_TYPE		0x34
32 #define GPIO_INT_BOTH_EDGE	0x38
33 #define GPIO_INT_LEVEL		0x3C
34 #define GPIO_DEBOUNCE_EN	0x40
35 #define GPIO_DEBOUNCE_PRESCALE	0x44
36 
37 /**
38  * struct ftgpio_gpio - Gemini GPIO state container
39  * @dev: containing device for this instance
40  * @gc: gpiochip for this instance
41  */
42 struct ftgpio_gpio {
43 	struct device *dev;
44 	struct gpio_chip gc;
45 	void __iomem *base;
46 };
47 
48 static void ftgpio_gpio_ack_irq(struct irq_data *d)
49 {
50 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
51 	struct ftgpio_gpio *g = gpiochip_get_data(gc);
52 
53 	writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR);
54 }
55 
56 static void ftgpio_gpio_mask_irq(struct irq_data *d)
57 {
58 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
59 	struct ftgpio_gpio *g = gpiochip_get_data(gc);
60 	u32 val;
61 
62 	val = readl(g->base + GPIO_INT_EN);
63 	val &= ~BIT(irqd_to_hwirq(d));
64 	writel(val, g->base + GPIO_INT_EN);
65 }
66 
67 static void ftgpio_gpio_unmask_irq(struct irq_data *d)
68 {
69 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
70 	struct ftgpio_gpio *g = gpiochip_get_data(gc);
71 	u32 val;
72 
73 	val = readl(g->base + GPIO_INT_EN);
74 	val |= BIT(irqd_to_hwirq(d));
75 	writel(val, g->base + GPIO_INT_EN);
76 }
77 
78 static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type)
79 {
80 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
81 	struct ftgpio_gpio *g = gpiochip_get_data(gc);
82 	u32 mask = BIT(irqd_to_hwirq(d));
83 	u32 reg_both, reg_level, reg_type;
84 
85 	reg_type = readl(g->base + GPIO_INT_TYPE);
86 	reg_level = readl(g->base + GPIO_INT_LEVEL);
87 	reg_both = readl(g->base + GPIO_INT_BOTH_EDGE);
88 
89 	switch (type) {
90 	case IRQ_TYPE_EDGE_BOTH:
91 		irq_set_handler_locked(d, handle_edge_irq);
92 		reg_type &= ~mask;
93 		reg_both |= mask;
94 		break;
95 	case IRQ_TYPE_EDGE_RISING:
96 		irq_set_handler_locked(d, handle_edge_irq);
97 		reg_type &= ~mask;
98 		reg_both &= ~mask;
99 		reg_level &= ~mask;
100 		break;
101 	case IRQ_TYPE_EDGE_FALLING:
102 		irq_set_handler_locked(d, handle_edge_irq);
103 		reg_type &= ~mask;
104 		reg_both &= ~mask;
105 		reg_level |= mask;
106 		break;
107 	case IRQ_TYPE_LEVEL_HIGH:
108 		irq_set_handler_locked(d, handle_level_irq);
109 		reg_type |= mask;
110 		reg_level &= ~mask;
111 		break;
112 	case IRQ_TYPE_LEVEL_LOW:
113 		irq_set_handler_locked(d, handle_level_irq);
114 		reg_type |= mask;
115 		reg_level |= mask;
116 		break;
117 	default:
118 		irq_set_handler_locked(d, handle_bad_irq);
119 		return -EINVAL;
120 	}
121 
122 	writel(reg_type, g->base + GPIO_INT_TYPE);
123 	writel(reg_level, g->base + GPIO_INT_LEVEL);
124 	writel(reg_both, g->base + GPIO_INT_BOTH_EDGE);
125 
126 	ftgpio_gpio_ack_irq(d);
127 
128 	return 0;
129 }
130 
131 static struct irq_chip ftgpio_gpio_irqchip = {
132 	.name = "FTGPIO010",
133 	.irq_ack = ftgpio_gpio_ack_irq,
134 	.irq_mask = ftgpio_gpio_mask_irq,
135 	.irq_unmask = ftgpio_gpio_unmask_irq,
136 	.irq_set_type = ftgpio_gpio_set_irq_type,
137 };
138 
139 static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
140 {
141 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
142 	struct ftgpio_gpio *g = gpiochip_get_data(gc);
143 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
144 	int offset;
145 	unsigned long stat;
146 
147 	chained_irq_enter(irqchip, desc);
148 
149 	stat = readl(g->base + GPIO_INT_STAT);
150 	if (stat)
151 		for_each_set_bit(offset, &stat, gc->ngpio)
152 			generic_handle_irq(irq_find_mapping(gc->irqdomain,
153 							    offset));
154 
155 	chained_irq_exit(irqchip, desc);
156 }
157 
158 static int ftgpio_gpio_probe(struct platform_device *pdev)
159 {
160 	struct device *dev = &pdev->dev;
161 	struct resource *res;
162 	struct ftgpio_gpio *g;
163 	int irq;
164 	int ret;
165 
166 	g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
167 	if (!g)
168 		return -ENOMEM;
169 
170 	g->dev = dev;
171 
172 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
173 	g->base = devm_ioremap_resource(dev, res);
174 	if (IS_ERR(g->base))
175 		return PTR_ERR(g->base);
176 
177 	irq = platform_get_irq(pdev, 0);
178 	if (!irq)
179 		return -EINVAL;
180 
181 	ret = bgpio_init(&g->gc, dev, 4,
182 			 g->base + GPIO_DATA_IN,
183 			 g->base + GPIO_DATA_SET,
184 			 g->base + GPIO_DATA_CLR,
185 			 g->base + GPIO_DIR,
186 			 NULL,
187 			 0);
188 	if (ret) {
189 		dev_err(dev, "unable to init generic GPIO\n");
190 		return ret;
191 	}
192 	g->gc.label = "FTGPIO010";
193 	g->gc.base = -1;
194 	g->gc.parent = dev;
195 	g->gc.owner = THIS_MODULE;
196 	/* ngpio is set by bgpio_init() */
197 
198 	ret = devm_gpiochip_add_data(dev, &g->gc, g);
199 	if (ret)
200 		return ret;
201 
202 	/* Disable, unmask and clear all interrupts */
203 	writel(0x0, g->base + GPIO_INT_EN);
204 	writel(0x0, g->base + GPIO_INT_MASK);
205 	writel(~0x0, g->base + GPIO_INT_CLR);
206 
207 	ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip,
208 				   0, handle_bad_irq,
209 				   IRQ_TYPE_NONE);
210 	if (ret) {
211 		dev_info(dev, "could not add irqchip\n");
212 		return ret;
213 	}
214 	gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip,
215 				     irq, ftgpio_gpio_irq_handler);
216 
217 	dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
218 
219 	return 0;
220 }
221 
222 static const struct of_device_id ftgpio_gpio_of_match[] = {
223 	{
224 		.compatible = "cortina,gemini-gpio",
225 	},
226 	{
227 		.compatible = "moxa,moxart-gpio",
228 	},
229 	{
230 		.compatible = "faraday,ftgpio010",
231 	},
232 	{},
233 };
234 
235 static struct platform_driver ftgpio_gpio_driver = {
236 	.driver = {
237 		.name		= "ftgpio010-gpio",
238 		.of_match_table = of_match_ptr(ftgpio_gpio_of_match),
239 	},
240 	.probe	= ftgpio_gpio_probe,
241 };
242 builtin_platform_driver(ftgpio_gpio_driver);
243