1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/module.h>
24#include <linux/io.h>
25#include <linux/platform_device.h>
26#include <linux/of_gpio.h>
27#include <linux/gpio/driver.h>
28#include <linux/acpi.h>
29
30#include "gpiolib.h"
31#include "gpiolib-acpi.h"
32
33
34#define XGENE_NIRQ_PROPERTY "apm,nr-irqs"
35#define XGENE_NGPIO_PROPERTY "apm,nr-gpios"
36#define XGENE_IRQ_START_PROPERTY "apm,irq-start"
37
38#define XGENE_DFLT_MAX_NGPIO 22
39#define XGENE_DFLT_MAX_NIRQ 6
40#define XGENE_DFLT_IRQ_START_PIN 8
41#define GPIO_MASK(x) (1U << ((x) % 32))
42
43#define MPA_GPIO_INT_LVL 0x0290
44#define MPA_GPIO_OE_ADDR 0x029c
45#define MPA_GPIO_OUT_ADDR 0x02a0
46#define MPA_GPIO_IN_ADDR 0x02a4
47#define MPA_GPIO_SEL_LO 0x0294
48
49#define GPIO_INT_LEVEL_H 0x000001
50#define GPIO_INT_LEVEL_L 0x000000
51
52
53
54
55
56
57
58
59
60
61struct xgene_gpio_sb {
62 struct gpio_chip gc;
63 void __iomem *regs;
64 struct irq_domain *irq_domain;
65 u16 irq_start;
66 u16 nirq;
67 u16 parent_irq_base;
68};
69
70#define HWIRQ_TO_GPIO(priv, hwirq) ((hwirq) + (priv)->irq_start)
71#define GPIO_TO_HWIRQ(priv, gpio) ((gpio) - (priv)->irq_start)
72
73static void xgene_gpio_set_bit(struct gpio_chip *gc,
74 void __iomem *reg, u32 gpio, int val)
75{
76 u32 data;
77
78 data = gc->read_reg(reg);
79 if (val)
80 data |= GPIO_MASK(gpio);
81 else
82 data &= ~GPIO_MASK(gpio);
83 gc->write_reg(reg, data);
84}
85
86static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
87{
88 struct xgene_gpio_sb *priv = irq_data_get_irq_chip_data(d);
89 int gpio = HWIRQ_TO_GPIO(priv, d->hwirq);
90 int lvl_type = GPIO_INT_LEVEL_H;
91
92 switch (type & IRQ_TYPE_SENSE_MASK) {
93 case IRQ_TYPE_EDGE_RISING:
94 case IRQ_TYPE_LEVEL_HIGH:
95 lvl_type = GPIO_INT_LEVEL_H;
96 break;
97 case IRQ_TYPE_EDGE_FALLING:
98 case IRQ_TYPE_LEVEL_LOW:
99 lvl_type = GPIO_INT_LEVEL_L;
100 break;
101 default:
102 break;
103 }
104
105 xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
106 gpio * 2, 1);
107 xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_INT_LVL,
108 d->hwirq, lvl_type);
109
110
111 if (type & IRQ_TYPE_EDGE_BOTH)
112 return irq_chip_set_type_parent(d, IRQ_TYPE_EDGE_RISING);
113 else
114 return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
115}
116
117static struct irq_chip xgene_gpio_sb_irq_chip = {
118 .name = "sbgpio",
119 .irq_eoi = irq_chip_eoi_parent,
120 .irq_mask = irq_chip_mask_parent,
121 .irq_unmask = irq_chip_unmask_parent,
122 .irq_set_type = xgene_gpio_sb_irq_set_type,
123};
124
125static int xgene_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
126{
127 struct xgene_gpio_sb *priv = gpiochip_get_data(gc);
128 struct irq_fwspec fwspec;
129
130 if ((gpio < priv->irq_start) ||
131 (gpio > HWIRQ_TO_GPIO(priv, priv->nirq)))
132 return -ENXIO;
133
134 fwspec.fwnode = gc->parent->fwnode;
135 fwspec.param_count = 2;
136 fwspec.param[0] = GPIO_TO_HWIRQ(priv, gpio);
137 fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
138 return irq_create_fwspec_mapping(&fwspec);
139}
140
141static int xgene_gpio_sb_domain_activate(struct irq_domain *d,
142 struct irq_data *irq_data,
143 bool reserve)
144{
145 struct xgene_gpio_sb *priv = d->host_data;
146 u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
147
148 if (gpiochip_lock_as_irq(&priv->gc, gpio)) {
149 dev_err(priv->gc.parent,
150 "Unable to configure XGene GPIO standby pin %d as IRQ\n",
151 gpio);
152 return -ENOSPC;
153 }
154
155 xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
156 gpio * 2, 1);
157 return 0;
158}
159
160static void xgene_gpio_sb_domain_deactivate(struct irq_domain *d,
161 struct irq_data *irq_data)
162{
163 struct xgene_gpio_sb *priv = d->host_data;
164 u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
165
166 gpiochip_unlock_as_irq(&priv->gc, gpio);
167 xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
168 gpio * 2, 0);
169}
170
171static int xgene_gpio_sb_domain_translate(struct irq_domain *d,
172 struct irq_fwspec *fwspec,
173 unsigned long *hwirq,
174 unsigned int *type)
175{
176 struct xgene_gpio_sb *priv = d->host_data;
177
178 if ((fwspec->param_count != 2) ||
179 (fwspec->param[0] >= priv->nirq))
180 return -EINVAL;
181 *hwirq = fwspec->param[0];
182 *type = fwspec->param[1];
183 return 0;
184}
185
186static int xgene_gpio_sb_domain_alloc(struct irq_domain *domain,
187 unsigned int virq,
188 unsigned int nr_irqs, void *data)
189{
190 struct irq_fwspec *fwspec = data;
191 struct irq_fwspec parent_fwspec;
192 struct xgene_gpio_sb *priv = domain->host_data;
193 irq_hw_number_t hwirq;
194 unsigned int i;
195
196 hwirq = fwspec->param[0];
197 for (i = 0; i < nr_irqs; i++)
198 irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
199 &xgene_gpio_sb_irq_chip, priv);
200
201 parent_fwspec.fwnode = domain->parent->fwnode;
202 if (is_of_node(parent_fwspec.fwnode)) {
203 parent_fwspec.param_count = 3;
204 parent_fwspec.param[0] = 0;
205
206 parent_fwspec.param[1] = hwirq + priv->parent_irq_base - 32;
207 parent_fwspec.param[2] = fwspec->param[1];
208 } else if (is_fwnode_irqchip(parent_fwspec.fwnode)) {
209 parent_fwspec.param_count = 2;
210 parent_fwspec.param[0] = hwirq + priv->parent_irq_base;
211 parent_fwspec.param[1] = fwspec->param[1];
212 } else
213 return -EINVAL;
214
215 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
216 &parent_fwspec);
217}
218
219static const struct irq_domain_ops xgene_gpio_sb_domain_ops = {
220 .translate = xgene_gpio_sb_domain_translate,
221 .alloc = xgene_gpio_sb_domain_alloc,
222 .free = irq_domain_free_irqs_common,
223 .activate = xgene_gpio_sb_domain_activate,
224 .deactivate = xgene_gpio_sb_domain_deactivate,
225};
226
227static int xgene_gpio_sb_probe(struct platform_device *pdev)
228{
229 struct xgene_gpio_sb *priv;
230 int ret;
231 struct resource *res;
232 void __iomem *regs;
233 struct irq_domain *parent_domain = NULL;
234 u32 val32;
235
236 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
237 if (!priv)
238 return -ENOMEM;
239
240 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
241 regs = devm_ioremap_resource(&pdev->dev, res);
242 if (IS_ERR(regs))
243 return PTR_ERR(regs);
244
245 priv->regs = regs;
246
247 ret = platform_get_irq(pdev, 0);
248 if (ret > 0) {
249 priv->parent_irq_base = irq_get_irq_data(ret)->hwirq;
250 parent_domain = irq_get_irq_data(ret)->domain;
251 }
252 if (!parent_domain) {
253 dev_err(&pdev->dev, "unable to obtain parent domain\n");
254 return -ENODEV;
255 }
256
257 ret = bgpio_init(&priv->gc, &pdev->dev, 4,
258 regs + MPA_GPIO_IN_ADDR,
259 regs + MPA_GPIO_OUT_ADDR, NULL,
260 regs + MPA_GPIO_OE_ADDR, NULL, 0);
261 if (ret)
262 return ret;
263
264 priv->gc.to_irq = xgene_gpio_sb_to_irq;
265
266
267 priv->irq_start = XGENE_DFLT_IRQ_START_PIN;
268 if (!device_property_read_u32(&pdev->dev,
269 XGENE_IRQ_START_PROPERTY, &val32))
270 priv->irq_start = val32;
271
272
273 priv->nirq = XGENE_DFLT_MAX_NIRQ;
274 if (!device_property_read_u32(&pdev->dev, XGENE_NIRQ_PROPERTY, &val32))
275 priv->nirq = val32;
276
277
278 priv->gc.ngpio = XGENE_DFLT_MAX_NGPIO;
279 if (!device_property_read_u32(&pdev->dev, XGENE_NGPIO_PROPERTY, &val32))
280 priv->gc.ngpio = val32;
281
282 dev_info(&pdev->dev, "Support %d gpios, %d irqs start from pin %d\n",
283 priv->gc.ngpio, priv->nirq, priv->irq_start);
284
285 platform_set_drvdata(pdev, priv);
286
287 priv->irq_domain = irq_domain_create_hierarchy(parent_domain,
288 0, priv->nirq, pdev->dev.fwnode,
289 &xgene_gpio_sb_domain_ops, priv);
290 if (!priv->irq_domain)
291 return -ENODEV;
292
293 priv->gc.irq.domain = priv->irq_domain;
294
295 ret = devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
296 if (ret) {
297 dev_err(&pdev->dev,
298 "failed to register X-Gene GPIO Standby driver\n");
299 irq_domain_remove(priv->irq_domain);
300 return ret;
301 }
302
303 dev_info(&pdev->dev, "X-Gene GPIO Standby driver registered\n");
304
305 if (priv->nirq > 0) {
306
307 acpi_gpiochip_request_interrupts(&priv->gc);
308 }
309
310 return ret;
311}
312
313static int xgene_gpio_sb_remove(struct platform_device *pdev)
314{
315 struct xgene_gpio_sb *priv = platform_get_drvdata(pdev);
316
317 if (priv->nirq > 0) {
318 acpi_gpiochip_free_interrupts(&priv->gc);
319 }
320
321 irq_domain_remove(priv->irq_domain);
322
323 return 0;
324}
325
326static const struct of_device_id xgene_gpio_sb_of_match[] = {
327 {.compatible = "apm,xgene-gpio-sb", },
328 {},
329};
330MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match);
331
332#ifdef CONFIG_ACPI
333static const struct acpi_device_id xgene_gpio_sb_acpi_match[] = {
334 {"APMC0D15", 0},
335 {},
336};
337MODULE_DEVICE_TABLE(acpi, xgene_gpio_sb_acpi_match);
338#endif
339
340static struct platform_driver xgene_gpio_sb_driver = {
341 .driver = {
342 .name = "xgene-gpio-sb",
343 .of_match_table = xgene_gpio_sb_of_match,
344 .acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match),
345 },
346 .probe = xgene_gpio_sb_probe,
347 .remove = xgene_gpio_sb_remove,
348};
349module_platform_driver(xgene_gpio_sb_driver);
350
351MODULE_AUTHOR("AppliedMicro");
352MODULE_DESCRIPTION("APM X-Gene GPIO Standby driver");
353MODULE_LICENSE("GPL");
354