Commit | Line | Data |
---|---|---|
3370dc91 BS |
1 | /* |
2 | * pinmux driver for CSR SiRFprimaII | |
3 | * | |
a9784e56 PG |
4 | * Authors: |
5 | * Rongjun Ying <rongjun.ying@csr.com> | |
6 | * Yuping Luo <yuping.luo@csr.com> | |
7 | * Barry Song <baohua.song@csr.com> | |
8 | * | |
019c12f4 BS |
9 | * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group |
10 | * company. | |
3370dc91 BS |
11 | * |
12 | * Licensed under GPLv2 or later. | |
13 | */ | |
14 | ||
15 | #include <linux/init.h> | |
3370dc91 BS |
16 | #include <linux/irq.h> |
17 | #include <linux/platform_device.h> | |
18 | #include <linux/io.h> | |
19 | #include <linux/slab.h> | |
20 | #include <linux/err.h> | |
3370dc91 BS |
21 | #include <linux/pinctrl/pinctrl.h> |
22 | #include <linux/pinctrl/pinmux.h> | |
23 | #include <linux/pinctrl/consumer.h> | |
24 | #include <linux/pinctrl/machine.h> | |
25 | #include <linux/of.h> | |
26 | #include <linux/of_address.h> | |
27 | #include <linux/of_device.h> | |
28 | #include <linux/of_platform.h> | |
29 | #include <linux/bitops.h> | |
30 | #include <linux/gpio.h> | |
31 | #include <linux/of_gpio.h> | |
3370dc91 BS |
32 | |
33 | #include "pinctrl-sirf.h" | |
34 | ||
35 | #define DRIVER_NAME "pinmux-sirf" | |
36 | ||
37 | struct sirfsoc_gpio_bank { | |
3370dc91 BS |
38 | int id; |
39 | int parent_irq; | |
40 | spinlock_t lock; | |
c5eb757c BS |
41 | }; |
42 | ||
43 | struct sirfsoc_gpio_chip { | |
44 | struct of_mm_gpio_chip chip; | |
c5eb757c | 45 | struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS]; |
1dfe0d15 | 46 | spinlock_t lock; |
3370dc91 BS |
47 | }; |
48 | ||
3370dc91 BS |
49 | static struct sirfsoc_pin_group *sirfsoc_pin_groups; |
50 | static int sirfsoc_pingrp_cnt; | |
51 | ||
52 | static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev) | |
53 | { | |
54 | return sirfsoc_pingrp_cnt; | |
55 | } | |
56 | ||
57 | static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev, | |
58 | unsigned selector) | |
59 | { | |
60 | return sirfsoc_pin_groups[selector].name; | |
61 | } | |
62 | ||
c09f80db BS |
63 | static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, |
64 | unsigned selector, | |
65 | const unsigned **pins, | |
66 | unsigned *num_pins) | |
3370dc91 BS |
67 | { |
68 | *pins = sirfsoc_pin_groups[selector].pins; | |
69 | *num_pins = sirfsoc_pin_groups[selector].num_pins; | |
70 | return 0; | |
71 | } | |
72 | ||
c09f80db BS |
73 | static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, |
74 | struct seq_file *s, unsigned offset) | |
3370dc91 BS |
75 | { |
76 | seq_printf(s, " " DRIVER_NAME); | |
77 | } | |
78 | ||
79 | static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev, | |
80 | struct device_node *np_config, | |
81 | struct pinctrl_map **map, unsigned *num_maps) | |
82 | { | |
83 | struct sirfsoc_pmx *spmx = pinctrl_dev_get_drvdata(pctldev); | |
84 | struct device_node *np; | |
85 | struct property *prop; | |
86 | const char *function, *group; | |
87 | int ret, index = 0, count = 0; | |
88 | ||
89 | /* calculate number of maps required */ | |
90 | for_each_child_of_node(np_config, np) { | |
91 | ret = of_property_read_string(np, "sirf,function", &function); | |
2d98023c JL |
92 | if (ret < 0) { |
93 | of_node_put(np); | |
3370dc91 | 94 | return ret; |
2d98023c | 95 | } |
3370dc91 BS |
96 | |
97 | ret = of_property_count_strings(np, "sirf,pins"); | |
2d98023c JL |
98 | if (ret < 0) { |
99 | of_node_put(np); | |
3370dc91 | 100 | return ret; |
2d98023c | 101 | } |
3370dc91 BS |
102 | |
103 | count += ret; | |
104 | } | |
105 | ||
106 | if (!count) { | |
107 | dev_err(spmx->dev, "No child nodes passed via DT\n"); | |
108 | return -ENODEV; | |
109 | } | |
110 | ||
6396bb22 | 111 | *map = kcalloc(count, sizeof(**map), GFP_KERNEL); |
3370dc91 BS |
112 | if (!*map) |
113 | return -ENOMEM; | |
114 | ||
115 | for_each_child_of_node(np_config, np) { | |
116 | of_property_read_string(np, "sirf,function", &function); | |
117 | of_property_for_each_string(np, "sirf,pins", prop, group) { | |
118 | (*map)[index].type = PIN_MAP_TYPE_MUX_GROUP; | |
119 | (*map)[index].data.mux.group = group; | |
120 | (*map)[index].data.mux.function = function; | |
121 | index++; | |
122 | } | |
123 | } | |
124 | ||
125 | *num_maps = count; | |
126 | ||
127 | return 0; | |
128 | } | |
129 | ||
130 | static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev, | |
131 | struct pinctrl_map *map, unsigned num_maps) | |
132 | { | |
133 | kfree(map); | |
134 | } | |
135 | ||
ecdc722f | 136 | static const struct pinctrl_ops sirfsoc_pctrl_ops = { |
3370dc91 BS |
137 | .get_groups_count = sirfsoc_get_groups_count, |
138 | .get_group_name = sirfsoc_get_group_name, | |
139 | .get_group_pins = sirfsoc_get_group_pins, | |
140 | .pin_dbg_show = sirfsoc_pin_dbg_show, | |
141 | .dt_node_to_map = sirfsoc_dt_node_to_map, | |
142 | .dt_free_map = sirfsoc_dt_free_map, | |
143 | }; | |
144 | ||
145 | static struct sirfsoc_pmx_func *sirfsoc_pmx_functions; | |
146 | static int sirfsoc_pmxfunc_cnt; | |
147 | ||
c09f80db BS |
148 | static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, |
149 | unsigned selector, bool enable) | |
3370dc91 BS |
150 | { |
151 | int i; | |
c09f80db BS |
152 | const struct sirfsoc_padmux *mux = |
153 | sirfsoc_pmx_functions[selector].padmux; | |
3370dc91 BS |
154 | const struct sirfsoc_muxmask *mask = mux->muxmask; |
155 | ||
156 | for (i = 0; i < mux->muxmask_counts; i++) { | |
157 | u32 muxval; | |
a17272a4 BS |
158 | muxval = readl(spmx->gpio_virtbase + |
159 | SIRFSOC_GPIO_PAD_EN(mask[i].group)); | |
160 | if (enable) | |
161 | muxval = muxval & ~mask[i].mask; | |
162 | else | |
163 | muxval = muxval | mask[i].mask; | |
164 | writel(muxval, spmx->gpio_virtbase + | |
165 | SIRFSOC_GPIO_PAD_EN(mask[i].group)); | |
3370dc91 BS |
166 | } |
167 | ||
168 | if (mux->funcmask && enable) { | |
169 | u32 func_en_val; | |
6a08a92e | 170 | |
3370dc91 | 171 | func_en_val = |
6a08a92e | 172 | readl(spmx->rsc_virtbase + mux->ctrlreg); |
3370dc91 | 173 | func_en_val = |
6a08a92e RW |
174 | (func_en_val & ~mux->funcmask) | (mux->funcval); |
175 | writel(func_en_val, spmx->rsc_virtbase + mux->ctrlreg); | |
3370dc91 BS |
176 | } |
177 | } | |
178 | ||
03e9f0ca LW |
179 | static int sirfsoc_pinmux_set_mux(struct pinctrl_dev *pmxdev, |
180 | unsigned selector, | |
181 | unsigned group) | |
3370dc91 BS |
182 | { |
183 | struct sirfsoc_pmx *spmx; | |
184 | ||
185 | spmx = pinctrl_dev_get_drvdata(pmxdev); | |
186 | sirfsoc_pinmux_endisable(spmx, selector, true); | |
187 | ||
188 | return 0; | |
189 | } | |
190 | ||
3370dc91 BS |
191 | static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev) |
192 | { | |
193 | return sirfsoc_pmxfunc_cnt; | |
194 | } | |
195 | ||
196 | static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev, | |
197 | unsigned selector) | |
198 | { | |
199 | return sirfsoc_pmx_functions[selector].name; | |
200 | } | |
201 | ||
c09f80db BS |
202 | static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev, |
203 | unsigned selector, | |
204 | const char * const **groups, | |
205 | unsigned * const num_groups) | |
3370dc91 BS |
206 | { |
207 | *groups = sirfsoc_pmx_functions[selector].groups; | |
208 | *num_groups = sirfsoc_pmx_functions[selector].num_groups; | |
209 | return 0; | |
210 | } | |
211 | ||
212 | static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, | |
213 | struct pinctrl_gpio_range *range, unsigned offset) | |
214 | { | |
215 | struct sirfsoc_pmx *spmx; | |
216 | ||
217 | int group = range->id; | |
218 | ||
219 | u32 muxval; | |
220 | ||
221 | spmx = pinctrl_dev_get_drvdata(pmxdev); | |
222 | ||
a17272a4 BS |
223 | muxval = readl(spmx->gpio_virtbase + |
224 | SIRFSOC_GPIO_PAD_EN(group)); | |
225 | muxval = muxval | (1 << (offset - range->pin_base)); | |
226 | writel(muxval, spmx->gpio_virtbase + | |
227 | SIRFSOC_GPIO_PAD_EN(group)); | |
3370dc91 BS |
228 | |
229 | return 0; | |
230 | } | |
231 | ||
ecdc722f | 232 | static const struct pinmux_ops sirfsoc_pinmux_ops = { |
03e9f0ca | 233 | .set_mux = sirfsoc_pinmux_set_mux, |
3370dc91 BS |
234 | .get_functions_count = sirfsoc_pinmux_get_funcs_count, |
235 | .get_function_name = sirfsoc_pinmux_get_func_name, | |
236 | .get_function_groups = sirfsoc_pinmux_get_groups, | |
237 | .gpio_request_enable = sirfsoc_pinmux_request_gpio, | |
238 | }; | |
239 | ||
240 | static struct pinctrl_desc sirfsoc_pinmux_desc = { | |
241 | .name = DRIVER_NAME, | |
242 | .pctlops = &sirfsoc_pctrl_ops, | |
243 | .pmxops = &sirfsoc_pinmux_ops, | |
244 | .owner = THIS_MODULE, | |
245 | }; | |
246 | ||
3370dc91 BS |
247 | static void __iomem *sirfsoc_rsc_of_iomap(void) |
248 | { | |
249 | const struct of_device_id rsc_ids[] = { | |
250 | { .compatible = "sirf,prima2-rsc" }, | |
3370dc91 BS |
251 | {} |
252 | }; | |
253 | struct device_node *np; | |
254 | ||
255 | np = of_find_matching_node(NULL, rsc_ids); | |
256 | if (!np) | |
257 | panic("unable to find compatible rsc node in dtb\n"); | |
258 | ||
259 | return of_iomap(np, 0); | |
260 | } | |
261 | ||
262 | static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc, | |
c5eb757c BS |
263 | const struct of_phandle_args *gpiospec, |
264 | u32 *flags) | |
3370dc91 | 265 | { |
c5eb757c | 266 | if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE) |
9c956909 | 267 | return -EINVAL; |
3370dc91 | 268 | |
c5eb757c | 269 | if (flags) |
9c956909 | 270 | *flags = gpiospec->args[1]; |
3370dc91 | 271 | |
c5eb757c | 272 | return gpiospec->args[0]; |
3370dc91 BS |
273 | } |
274 | ||
275 | static const struct of_device_id pinmux_ids[] = { | |
276 | { .compatible = "sirf,prima2-pinctrl", .data = &prima2_pinctrl_data, }, | |
277 | { .compatible = "sirf,atlas6-pinctrl", .data = &atlas6_pinctrl_data, }, | |
3370dc91 BS |
278 | {} |
279 | }; | |
280 | ||
281 | static int sirfsoc_pinmux_probe(struct platform_device *pdev) | |
282 | { | |
283 | int ret; | |
284 | struct sirfsoc_pmx *spmx; | |
285 | struct device_node *np = pdev->dev.of_node; | |
286 | const struct sirfsoc_pinctrl_data *pdata; | |
3370dc91 BS |
287 | |
288 | /* Create state holders etc for this driver */ | |
289 | spmx = devm_kzalloc(&pdev->dev, sizeof(*spmx), GFP_KERNEL); | |
290 | if (!spmx) | |
291 | return -ENOMEM; | |
292 | ||
293 | spmx->dev = &pdev->dev; | |
294 | ||
295 | platform_set_drvdata(pdev, spmx); | |
296 | ||
297 | spmx->gpio_virtbase = of_iomap(np, 0); | |
298 | if (!spmx->gpio_virtbase) { | |
299 | dev_err(&pdev->dev, "can't map gpio registers\n"); | |
300 | return -ENOMEM; | |
301 | } | |
302 | ||
303 | spmx->rsc_virtbase = sirfsoc_rsc_of_iomap(); | |
304 | if (!spmx->rsc_virtbase) { | |
305 | ret = -ENOMEM; | |
306 | dev_err(&pdev->dev, "can't map rsc registers\n"); | |
307 | goto out_no_rsc_remap; | |
308 | } | |
309 | ||
3370dc91 BS |
310 | pdata = of_match_node(pinmux_ids, np)->data; |
311 | sirfsoc_pin_groups = pdata->grps; | |
312 | sirfsoc_pingrp_cnt = pdata->grps_cnt; | |
313 | sirfsoc_pmx_functions = pdata->funcs; | |
314 | sirfsoc_pmxfunc_cnt = pdata->funcs_cnt; | |
315 | sirfsoc_pinmux_desc.pins = pdata->pads; | |
316 | sirfsoc_pinmux_desc.npins = pdata->pads_cnt; | |
317 | ||
318 | ||
319 | /* Now register the pin controller and all pins it handles */ | |
320 | spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx); | |
323de9ef | 321 | if (IS_ERR(spmx->pmx)) { |
3370dc91 | 322 | dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n"); |
323de9ef | 323 | ret = PTR_ERR(spmx->pmx); |
3370dc91 BS |
324 | goto out_no_pmx; |
325 | } | |
326 | ||
3370dc91 BS |
327 | dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n"); |
328 | ||
329 | return 0; | |
330 | ||
331 | out_no_pmx: | |
332 | iounmap(spmx->rsc_virtbase); | |
333 | out_no_rsc_remap: | |
334 | iounmap(spmx->gpio_virtbase); | |
335 | return ret; | |
336 | } | |
337 | ||
bc8d25a4 BS |
338 | #ifdef CONFIG_PM_SLEEP |
339 | static int sirfsoc_pinmux_suspend_noirq(struct device *dev) | |
340 | { | |
341 | int i, j; | |
342 | struct sirfsoc_pmx *spmx = dev_get_drvdata(dev); | |
343 | ||
344 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { | |
345 | for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) { | |
346 | spmx->gpio_regs[i][j] = readl(spmx->gpio_virtbase + | |
347 | SIRFSOC_GPIO_CTRL(i, j)); | |
348 | } | |
349 | spmx->ints_regs[i] = readl(spmx->gpio_virtbase + | |
350 | SIRFSOC_GPIO_INT_STATUS(i)); | |
351 | spmx->paden_regs[i] = readl(spmx->gpio_virtbase + | |
352 | SIRFSOC_GPIO_PAD_EN(i)); | |
353 | } | |
354 | spmx->dspen_regs = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0); | |
355 | ||
356 | for (i = 0; i < 3; i++) | |
357 | spmx->rsc_regs[i] = readl(spmx->rsc_virtbase + 4 * i); | |
358 | ||
359 | return 0; | |
360 | } | |
361 | ||
362 | static int sirfsoc_pinmux_resume_noirq(struct device *dev) | |
363 | { | |
364 | int i, j; | |
365 | struct sirfsoc_pmx *spmx = dev_get_drvdata(dev); | |
366 | ||
367 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { | |
368 | for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) { | |
369 | writel(spmx->gpio_regs[i][j], spmx->gpio_virtbase + | |
370 | SIRFSOC_GPIO_CTRL(i, j)); | |
371 | } | |
372 | writel(spmx->ints_regs[i], spmx->gpio_virtbase + | |
373 | SIRFSOC_GPIO_INT_STATUS(i)); | |
374 | writel(spmx->paden_regs[i], spmx->gpio_virtbase + | |
375 | SIRFSOC_GPIO_PAD_EN(i)); | |
376 | } | |
377 | writel(spmx->dspen_regs, spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0); | |
378 | ||
379 | for (i = 0; i < 3; i++) | |
380 | writel(spmx->rsc_regs[i], spmx->rsc_virtbase + 4 * i); | |
381 | ||
382 | return 0; | |
383 | } | |
384 | ||
385 | static const struct dev_pm_ops sirfsoc_pinmux_pm_ops = { | |
386 | .suspend_noirq = sirfsoc_pinmux_suspend_noirq, | |
387 | .resume_noirq = sirfsoc_pinmux_resume_noirq, | |
f6b17885 BS |
388 | .freeze_noirq = sirfsoc_pinmux_suspend_noirq, |
389 | .restore_noirq = sirfsoc_pinmux_resume_noirq, | |
bc8d25a4 BS |
390 | }; |
391 | #endif | |
392 | ||
3370dc91 BS |
393 | static struct platform_driver sirfsoc_pinmux_driver = { |
394 | .driver = { | |
395 | .name = DRIVER_NAME, | |
3370dc91 | 396 | .of_match_table = pinmux_ids, |
bc8d25a4 BS |
397 | #ifdef CONFIG_PM_SLEEP |
398 | .pm = &sirfsoc_pinmux_pm_ops, | |
399 | #endif | |
3370dc91 BS |
400 | }, |
401 | .probe = sirfsoc_pinmux_probe, | |
402 | }; | |
403 | ||
404 | static int __init sirfsoc_pinmux_init(void) | |
405 | { | |
406 | return platform_driver_register(&sirfsoc_pinmux_driver); | |
407 | } | |
408 | arch_initcall(sirfsoc_pinmux_init); | |
409 | ||
294d1351 LW |
410 | static inline struct sirfsoc_gpio_bank * |
411 | sirfsoc_gpio_to_bank(struct sirfsoc_gpio_chip *sgpio, unsigned int offset) | |
3370dc91 | 412 | { |
294d1351 | 413 | return &sgpio->sgpio_bank[offset / SIRFSOC_GPIO_BANK_SIZE]; |
3370dc91 BS |
414 | } |
415 | ||
294d1351 | 416 | static inline int sirfsoc_gpio_to_bankoff(unsigned int offset) |
3370dc91 | 417 | { |
294d1351 | 418 | return offset % SIRFSOC_GPIO_BANK_SIZE; |
3370dc91 | 419 | } |
7420d2d0 | 420 | |
3370dc91 BS |
421 | static void sirfsoc_gpio_irq_ack(struct irq_data *d) |
422 | { | |
294d1351 | 423 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
192d3507 | 424 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc); |
294d1351 LW |
425 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq); |
426 | int idx = sirfsoc_gpio_to_bankoff(d->hwirq); | |
3370dc91 BS |
427 | u32 val, offset; |
428 | unsigned long flags; | |
429 | ||
430 | offset = SIRFSOC_GPIO_CTRL(bank->id, idx); | |
431 | ||
1dfe0d15 | 432 | spin_lock_irqsave(&sgpio->lock, flags); |
3370dc91 | 433 | |
294d1351 | 434 | val = readl(sgpio->chip.regs + offset); |
3370dc91 | 435 | |
294d1351 | 436 | writel(val, sgpio->chip.regs + offset); |
3370dc91 | 437 | |
1dfe0d15 | 438 | spin_unlock_irqrestore(&sgpio->lock, flags); |
3370dc91 BS |
439 | } |
440 | ||
294d1351 LW |
441 | static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_chip *sgpio, |
442 | struct sirfsoc_gpio_bank *bank, | |
443 | int idx) | |
3370dc91 BS |
444 | { |
445 | u32 val, offset; | |
446 | unsigned long flags; | |
447 | ||
448 | offset = SIRFSOC_GPIO_CTRL(bank->id, idx); | |
449 | ||
1dfe0d15 | 450 | spin_lock_irqsave(&sgpio->lock, flags); |
3370dc91 | 451 | |
294d1351 | 452 | val = readl(sgpio->chip.regs + offset); |
3370dc91 BS |
453 | val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK; |
454 | val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK; | |
294d1351 | 455 | writel(val, sgpio->chip.regs + offset); |
3370dc91 | 456 | |
1dfe0d15 | 457 | spin_unlock_irqrestore(&sgpio->lock, flags); |
3370dc91 BS |
458 | } |
459 | ||
460 | static void sirfsoc_gpio_irq_mask(struct irq_data *d) | |
461 | { | |
294d1351 | 462 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
192d3507 | 463 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc); |
294d1351 | 464 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq); |
3370dc91 | 465 | |
294d1351 | 466 | __sirfsoc_gpio_irq_mask(sgpio, bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE); |
3370dc91 BS |
467 | } |
468 | ||
469 | static void sirfsoc_gpio_irq_unmask(struct irq_data *d) | |
470 | { | |
294d1351 | 471 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
192d3507 | 472 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc); |
294d1351 LW |
473 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq); |
474 | int idx = sirfsoc_gpio_to_bankoff(d->hwirq); | |
3370dc91 BS |
475 | u32 val, offset; |
476 | unsigned long flags; | |
477 | ||
478 | offset = SIRFSOC_GPIO_CTRL(bank->id, idx); | |
479 | ||
1dfe0d15 | 480 | spin_lock_irqsave(&sgpio->lock, flags); |
3370dc91 | 481 | |
294d1351 | 482 | val = readl(sgpio->chip.regs + offset); |
3370dc91 BS |
483 | val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK; |
484 | val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK; | |
294d1351 | 485 | writel(val, sgpio->chip.regs + offset); |
3370dc91 | 486 | |
1dfe0d15 | 487 | spin_unlock_irqrestore(&sgpio->lock, flags); |
3370dc91 BS |
488 | } |
489 | ||
490 | static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type) | |
491 | { | |
294d1351 | 492 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
192d3507 | 493 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc); |
294d1351 LW |
494 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq); |
495 | int idx = sirfsoc_gpio_to_bankoff(d->hwirq); | |
3370dc91 BS |
496 | u32 val, offset; |
497 | unsigned long flags; | |
498 | ||
499 | offset = SIRFSOC_GPIO_CTRL(bank->id, idx); | |
500 | ||
1dfe0d15 | 501 | spin_lock_irqsave(&sgpio->lock, flags); |
3370dc91 | 502 | |
294d1351 | 503 | val = readl(sgpio->chip.regs + offset); |
b07ddcdc | 504 | val &= ~(SIRFSOC_GPIO_CTL_INTR_STS_MASK | SIRFSOC_GPIO_CTL_OUT_EN_MASK); |
3370dc91 BS |
505 | |
506 | switch (type) { | |
507 | case IRQ_TYPE_NONE: | |
508 | break; | |
509 | case IRQ_TYPE_EDGE_RISING: | |
c09f80db BS |
510 | val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | |
511 | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK; | |
3370dc91 BS |
512 | val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK; |
513 | break; | |
514 | case IRQ_TYPE_EDGE_FALLING: | |
515 | val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK; | |
c09f80db BS |
516 | val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK | |
517 | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK; | |
3370dc91 BS |
518 | break; |
519 | case IRQ_TYPE_EDGE_BOTH: | |
c09f80db BS |
520 | val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | |
521 | SIRFSOC_GPIO_CTL_INTR_LOW_MASK | | |
522 | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK; | |
3370dc91 BS |
523 | break; |
524 | case IRQ_TYPE_LEVEL_LOW: | |
c09f80db BS |
525 | val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | |
526 | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK); | |
3370dc91 BS |
527 | val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK; |
528 | break; | |
529 | case IRQ_TYPE_LEVEL_HIGH: | |
530 | val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK; | |
c09f80db BS |
531 | val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | |
532 | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK); | |
3370dc91 BS |
533 | break; |
534 | } | |
535 | ||
294d1351 | 536 | writel(val, sgpio->chip.regs + offset); |
3370dc91 | 537 | |
1dfe0d15 | 538 | spin_unlock_irqrestore(&sgpio->lock, flags); |
3370dc91 BS |
539 | |
540 | return 0; | |
541 | } | |
542 | ||
543 | static struct irq_chip sirfsoc_irq_chip = { | |
544 | .name = "sirf-gpio-irq", | |
545 | .irq_ack = sirfsoc_gpio_irq_ack, | |
546 | .irq_mask = sirfsoc_gpio_irq_mask, | |
547 | .irq_unmask = sirfsoc_gpio_irq_unmask, | |
548 | .irq_set_type = sirfsoc_gpio_irq_type, | |
549 | }; | |
550 | ||
bd0b9ac4 | 551 | static void sirfsoc_gpio_handle_irq(struct irq_desc *desc) |
3370dc91 | 552 | { |
3b0d1561 | 553 | unsigned int irq = irq_desc_get_irq(desc); |
294d1351 | 554 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
192d3507 | 555 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc); |
7420d2d0 | 556 | struct sirfsoc_gpio_bank *bank; |
3370dc91 BS |
557 | u32 status, ctrl; |
558 | int idx = 0; | |
5663bb27 | 559 | struct irq_chip *chip = irq_desc_get_chip(desc); |
7420d2d0 LW |
560 | int i; |
561 | ||
648e42e1 | 562 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { |
29c7f1f5 | 563 | bank = &sgpio->sgpio_bank[i]; |
7420d2d0 LW |
564 | if (bank->parent_irq == irq) |
565 | break; | |
566 | } | |
648e42e1 | 567 | BUG_ON(i == SIRFSOC_GPIO_NO_OF_BANKS); |
3370dc91 BS |
568 | |
569 | chained_irq_enter(chip, desc); | |
570 | ||
294d1351 | 571 | status = readl(sgpio->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id)); |
3370dc91 BS |
572 | if (!status) { |
573 | printk(KERN_WARNING | |
28b30c30 | 574 | "%s: gpio id %d status %#x no interrupt is flagged\n", |
3370dc91 | 575 | __func__, bank->id, status); |
bd0b9ac4 | 576 | handle_bad_irq(desc); |
3370dc91 BS |
577 | return; |
578 | } | |
579 | ||
580 | while (status) { | |
294d1351 | 581 | ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx)); |
3370dc91 BS |
582 | |
583 | /* | |
584 | * Here we must check whether the corresponding GPIO's interrupt | |
585 | * has been enabled, otherwise just skip it | |
586 | */ | |
587 | if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) { | |
588 | pr_debug("%s: gpio id %d idx %d happens\n", | |
589 | __func__, bank->id, idx); | |
f0fbe7bc | 590 | generic_handle_irq(irq_find_mapping(gc->irq.domain, idx + |
8daeffb0 | 591 | bank->id * SIRFSOC_GPIO_BANK_SIZE)); |
3370dc91 BS |
592 | } |
593 | ||
594 | idx++; | |
595 | status = status >> 1; | |
596 | } | |
597 | ||
598 | chained_irq_exit(chip, desc); | |
599 | } | |
600 | ||
294d1351 LW |
601 | static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_chip *sgpio, |
602 | unsigned ctrl_offset) | |
3370dc91 BS |
603 | { |
604 | u32 val; | |
605 | ||
294d1351 | 606 | val = readl(sgpio->chip.regs + ctrl_offset); |
3370dc91 | 607 | val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK; |
294d1351 | 608 | writel(val, sgpio->chip.regs + ctrl_offset); |
3370dc91 BS |
609 | } |
610 | ||
611 | static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset) | |
612 | { | |
192d3507 | 613 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip); |
294d1351 | 614 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset); |
3370dc91 BS |
615 | unsigned long flags; |
616 | ||
a9a1d2a7 | 617 | if (pinctrl_gpio_request(chip->base + offset)) |
3370dc91 BS |
618 | return -ENODEV; |
619 | ||
620 | spin_lock_irqsave(&bank->lock, flags); | |
621 | ||
622 | /* | |
623 | * default status: | |
624 | * set direction as input and mask irq | |
625 | */ | |
294d1351 LW |
626 | sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset)); |
627 | __sirfsoc_gpio_irq_mask(sgpio, bank, offset); | |
3370dc91 BS |
628 | |
629 | spin_unlock_irqrestore(&bank->lock, flags); | |
630 | ||
631 | return 0; | |
632 | } | |
633 | ||
634 | static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset) | |
635 | { | |
192d3507 | 636 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip); |
294d1351 | 637 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset); |
3370dc91 BS |
638 | unsigned long flags; |
639 | ||
640 | spin_lock_irqsave(&bank->lock, flags); | |
641 | ||
294d1351 LW |
642 | __sirfsoc_gpio_irq_mask(sgpio, bank, offset); |
643 | sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset)); | |
3370dc91 BS |
644 | |
645 | spin_unlock_irqrestore(&bank->lock, flags); | |
646 | ||
a9a1d2a7 | 647 | pinctrl_gpio_free(chip->base + offset); |
3370dc91 BS |
648 | } |
649 | ||
650 | static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | |
651 | { | |
192d3507 | 652 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip); |
294d1351 | 653 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio); |
c5eb757c | 654 | int idx = sirfsoc_gpio_to_bankoff(gpio); |
3370dc91 BS |
655 | unsigned long flags; |
656 | unsigned offset; | |
657 | ||
658 | offset = SIRFSOC_GPIO_CTRL(bank->id, idx); | |
659 | ||
660 | spin_lock_irqsave(&bank->lock, flags); | |
661 | ||
294d1351 | 662 | sirfsoc_gpio_set_input(sgpio, offset); |
3370dc91 BS |
663 | |
664 | spin_unlock_irqrestore(&bank->lock, flags); | |
665 | ||
666 | return 0; | |
667 | } | |
668 | ||
294d1351 LW |
669 | static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_chip *sgpio, |
670 | struct sirfsoc_gpio_bank *bank, | |
671 | unsigned offset, | |
672 | int value) | |
3370dc91 BS |
673 | { |
674 | u32 out_ctrl; | |
675 | unsigned long flags; | |
676 | ||
677 | spin_lock_irqsave(&bank->lock, flags); | |
678 | ||
294d1351 | 679 | out_ctrl = readl(sgpio->chip.regs + offset); |
3370dc91 BS |
680 | if (value) |
681 | out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK; | |
682 | else | |
683 | out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK; | |
684 | ||
685 | out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK; | |
686 | out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK; | |
294d1351 | 687 | writel(out_ctrl, sgpio->chip.regs + offset); |
3370dc91 BS |
688 | |
689 | spin_unlock_irqrestore(&bank->lock, flags); | |
690 | } | |
691 | ||
c09f80db BS |
692 | static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, |
693 | unsigned gpio, int value) | |
3370dc91 | 694 | { |
192d3507 | 695 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip); |
294d1351 | 696 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio); |
c5eb757c | 697 | int idx = sirfsoc_gpio_to_bankoff(gpio); |
3370dc91 BS |
698 | u32 offset; |
699 | unsigned long flags; | |
700 | ||
701 | offset = SIRFSOC_GPIO_CTRL(bank->id, idx); | |
702 | ||
1dfe0d15 | 703 | spin_lock_irqsave(&sgpio->lock, flags); |
3370dc91 | 704 | |
294d1351 | 705 | sirfsoc_gpio_set_output(sgpio, bank, offset, value); |
3370dc91 | 706 | |
1dfe0d15 | 707 | spin_unlock_irqrestore(&sgpio->lock, flags); |
3370dc91 BS |
708 | |
709 | return 0; | |
710 | } | |
711 | ||
712 | static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset) | |
713 | { | |
192d3507 | 714 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip); |
294d1351 | 715 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset); |
3370dc91 BS |
716 | u32 val; |
717 | unsigned long flags; | |
718 | ||
719 | spin_lock_irqsave(&bank->lock, flags); | |
720 | ||
294d1351 | 721 | val = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset)); |
3370dc91 BS |
722 | |
723 | spin_unlock_irqrestore(&bank->lock, flags); | |
724 | ||
725 | return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK); | |
726 | } | |
727 | ||
728 | static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset, | |
729 | int value) | |
730 | { | |
192d3507 | 731 | struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip); |
294d1351 | 732 | struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset); |
3370dc91 BS |
733 | u32 ctrl; |
734 | unsigned long flags; | |
735 | ||
736 | spin_lock_irqsave(&bank->lock, flags); | |
737 | ||
294d1351 | 738 | ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset)); |
3370dc91 BS |
739 | if (value) |
740 | ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK; | |
741 | else | |
742 | ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK; | |
294d1351 | 743 | writel(ctrl, sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset)); |
3370dc91 BS |
744 | |
745 | spin_unlock_irqrestore(&bank->lock, flags); | |
746 | } | |
747 | ||
294d1351 LW |
748 | static void sirfsoc_gpio_set_pullup(struct sirfsoc_gpio_chip *sgpio, |
749 | const u32 *pullups) | |
3370dc91 BS |
750 | { |
751 | int i, n; | |
752 | const unsigned long *p = (const unsigned long *)pullups; | |
753 | ||
754 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { | |
755 | for_each_set_bit(n, p + i, BITS_PER_LONG) { | |
756 | u32 offset = SIRFSOC_GPIO_CTRL(i, n); | |
294d1351 | 757 | u32 val = readl(sgpio->chip.regs + offset); |
3370dc91 BS |
758 | val |= SIRFSOC_GPIO_CTL_PULL_MASK; |
759 | val |= SIRFSOC_GPIO_CTL_PULL_HIGH; | |
294d1351 | 760 | writel(val, sgpio->chip.regs + offset); |
3370dc91 BS |
761 | } |
762 | } | |
763 | } | |
764 | ||
294d1351 LW |
765 | static void sirfsoc_gpio_set_pulldown(struct sirfsoc_gpio_chip *sgpio, |
766 | const u32 *pulldowns) | |
3370dc91 BS |
767 | { |
768 | int i, n; | |
769 | const unsigned long *p = (const unsigned long *)pulldowns; | |
770 | ||
771 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { | |
772 | for_each_set_bit(n, p + i, BITS_PER_LONG) { | |
773 | u32 offset = SIRFSOC_GPIO_CTRL(i, n); | |
294d1351 | 774 | u32 val = readl(sgpio->chip.regs + offset); |
3370dc91 BS |
775 | val |= SIRFSOC_GPIO_CTL_PULL_MASK; |
776 | val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH; | |
294d1351 | 777 | writel(val, sgpio->chip.regs + offset); |
3370dc91 BS |
778 | } |
779 | } | |
780 | } | |
781 | ||
782 | static int sirfsoc_gpio_probe(struct device_node *np) | |
783 | { | |
784 | int i, err = 0; | |
294d1351 | 785 | static struct sirfsoc_gpio_chip *sgpio; |
3370dc91 | 786 | struct sirfsoc_gpio_bank *bank; |
2c9fdcf1 | 787 | void __iomem *regs; |
3370dc91 | 788 | struct platform_device *pdev; |
3370dc91 BS |
789 | |
790 | u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS]; | |
791 | ||
792 | pdev = of_find_device_by_node(np); | |
793 | if (!pdev) | |
794 | return -ENODEV; | |
795 | ||
294d1351 LW |
796 | sgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL); |
797 | if (!sgpio) | |
798 | return -ENOMEM; | |
1dfe0d15 | 799 | spin_lock_init(&sgpio->lock); |
294d1351 | 800 | |
3370dc91 BS |
801 | regs = of_iomap(np, 0); |
802 | if (!regs) | |
803 | return -ENOMEM; | |
804 | ||
294d1351 LW |
805 | sgpio->chip.gc.request = sirfsoc_gpio_request; |
806 | sgpio->chip.gc.free = sirfsoc_gpio_free; | |
807 | sgpio->chip.gc.direction_input = sirfsoc_gpio_direction_input; | |
808 | sgpio->chip.gc.get = sirfsoc_gpio_get_value; | |
809 | sgpio->chip.gc.direction_output = sirfsoc_gpio_direction_output; | |
810 | sgpio->chip.gc.set = sirfsoc_gpio_set_value; | |
811 | sgpio->chip.gc.base = 0; | |
812 | sgpio->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS; | |
f5292d06 | 813 | sgpio->chip.gc.label = kasprintf(GFP_KERNEL, "%pOF", np); |
294d1351 LW |
814 | sgpio->chip.gc.of_node = np; |
815 | sgpio->chip.gc.of_xlate = sirfsoc_gpio_of_xlate; | |
816 | sgpio->chip.gc.of_gpio_n_cells = 2; | |
58383c78 | 817 | sgpio->chip.gc.parent = &pdev->dev; |
294d1351 | 818 | sgpio->chip.regs = regs; |
294d1351 | 819 | |
192d3507 | 820 | err = gpiochip_add_data(&sgpio->chip.gc, sgpio); |
c5eb757c | 821 | if (err) { |
f5292d06 RH |
822 | dev_err(&pdev->dev, "%pOF: error in probe function with status %d\n", |
823 | np, err); | |
c5eb757c BS |
824 | goto out; |
825 | } | |
826 | ||
294d1351 | 827 | err = gpiochip_irqchip_add(&sgpio->chip.gc, |
7420d2d0 LW |
828 | &sirfsoc_irq_chip, |
829 | 0, handle_level_irq, | |
830 | IRQ_TYPE_NONE); | |
831 | if (err) { | |
832 | dev_err(&pdev->dev, | |
833 | "could not connect irqchip to gpiochip\n"); | |
0a5d6670 | 834 | goto out_banks; |
7420d2d0 LW |
835 | } |
836 | ||
3370dc91 | 837 | for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { |
294d1351 | 838 | bank = &sgpio->sgpio_bank[i]; |
3370dc91 | 839 | spin_lock_init(&bank->lock); |
3370dc91 BS |
840 | bank->parent_irq = platform_get_irq(pdev, i); |
841 | if (bank->parent_irq < 0) { | |
842 | err = bank->parent_irq; | |
294d1351 | 843 | goto out_banks; |
3370dc91 BS |
844 | } |
845 | ||
294d1351 | 846 | gpiochip_set_chained_irqchip(&sgpio->chip.gc, |
7420d2d0 LW |
847 | &sirfsoc_irq_chip, |
848 | bank->parent_irq, | |
849 | sirfsoc_gpio_handle_irq); | |
3370dc91 BS |
850 | } |
851 | ||
294d1351 LW |
852 | err = gpiochip_add_pin_range(&sgpio->chip.gc, dev_name(&pdev->dev), |
853 | 0, 0, SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS); | |
854 | if (err) { | |
855 | dev_err(&pdev->dev, | |
856 | "could not add gpiochip pin range\n"); | |
857 | goto out_no_range; | |
858 | } | |
859 | ||
3370dc91 BS |
860 | if (!of_property_read_u32_array(np, "sirf,pullups", pullups, |
861 | SIRFSOC_GPIO_NO_OF_BANKS)) | |
294d1351 | 862 | sirfsoc_gpio_set_pullup(sgpio, pullups); |
3370dc91 BS |
863 | |
864 | if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns, | |
865 | SIRFSOC_GPIO_NO_OF_BANKS)) | |
294d1351 | 866 | sirfsoc_gpio_set_pulldown(sgpio, pulldowns); |
3370dc91 BS |
867 | |
868 | return 0; | |
869 | ||
294d1351 LW |
870 | out_no_range: |
871 | out_banks: | |
2fcea6ce | 872 | gpiochip_remove(&sgpio->chip.gc); |
3370dc91 BS |
873 | out: |
874 | iounmap(regs); | |
875 | return err; | |
876 | } | |
877 | ||
878 | static int __init sirfsoc_gpio_init(void) | |
879 | { | |
880 | ||
881 | struct device_node *np; | |
882 | ||
883 | np = of_find_matching_node(NULL, pinmux_ids); | |
884 | ||
885 | if (!np) | |
886 | return -ENODEV; | |
887 | ||
888 | return sirfsoc_gpio_probe(np); | |
889 | } | |
890 | subsys_initcall(sirfsoc_gpio_init); |