1 | /* |
2 | * SPEAr platform PLGPIO driver |
3 | * |
4 | * Copyright (C) 2012 ST Microelectronics |
5 | * Viresh Kumar <viresh.kumar@linaro.org> |
6 | * |
7 | * This file is licensed under the terms of the GNU General Public |
8 | * License version 2. This program is licensed "as is" without any |
9 | * warranty of any kind, whether express or implied. |
10 | */ |
11 | |
12 | #include <linux/clk.h> |
13 | #include <linux/err.h> |
14 | #include <linux/gpio/driver.h> |
15 | #include <linux/io.h> |
16 | #include <linux/init.h> |
17 | #include <linux/mfd/syscon.h> |
18 | #include <linux/of.h> |
19 | #include <linux/of_platform.h> |
20 | #include <linux/pinctrl/consumer.h> |
21 | #include <linux/platform_device.h> |
22 | #include <linux/pm.h> |
23 | #include <linux/regmap.h> |
24 | #include <linux/spinlock.h> |
25 | |
26 | #define MAX_GPIO_PER_REG 32 |
27 | #define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG) |
28 | #define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \ |
29 | * sizeof(int *)) |
30 | |
31 | /* |
32 | * plgpio pins in all machines are not one to one mapped, bitwise with registers |
33 | * bits. These set of macros define register masks for which below functions |
34 | * (pin_to_offset and offset_to_pin) are required to be called. |
35 | */ |
36 | #define PTO_ENB_REG 0x001 |
37 | #define PTO_WDATA_REG 0x002 |
38 | #define PTO_DIR_REG 0x004 |
39 | #define PTO_IE_REG 0x008 |
40 | #define PTO_RDATA_REG 0x010 |
41 | #define PTO_MIS_REG 0x020 |
42 | |
43 | struct plgpio_regs { |
44 | u32 enb; /* enable register */ |
45 | u32 wdata; /* write data register */ |
46 | u32 dir; /* direction set register */ |
47 | u32 rdata; /* read data register */ |
48 | u32 ie; /* interrupt enable register */ |
49 | u32 mis; /* mask interrupt status register */ |
50 | u32 eit; /* edge interrupt type */ |
51 | }; |
52 | |
53 | /* |
54 | * struct plgpio: plgpio driver specific structure |
55 | * |
56 | * lock: lock for guarding gpio registers |
57 | * base: base address of plgpio block |
58 | * chip: gpio framework specific chip information structure |
59 | * p2o: function ptr for pin to offset conversion. This is required only for |
60 | * machines where mapping b/w pin and offset is not 1-to-1. |
61 | * o2p: function ptr for offset to pin conversion. This is required only for |
62 | * machines where mapping b/w pin and offset is not 1-to-1. |
63 | * p2o_regs: mask of registers for which p2o and o2p are applicable |
64 | * regs: register offsets |
65 | * csave_regs: context save registers for standby/sleep/hibernate cases |
66 | */ |
67 | struct plgpio { |
68 | spinlock_t lock; |
69 | struct regmap *regmap; |
70 | struct clk *clk; |
71 | struct gpio_chip chip; |
72 | int (*p2o)(int pin); /* pin_to_offset */ |
73 | int (*o2p)(int offset); /* offset_to_pin */ |
74 | u32 p2o_regs; |
75 | struct plgpio_regs regs; |
76 | #ifdef CONFIG_PM_SLEEP |
77 | struct plgpio_regs *csave_regs; |
78 | #endif |
79 | }; |
80 | |
81 | /* register manipulation inline functions */ |
82 | static inline u32 is_plgpio_set(struct regmap *regmap, u32 pin, u32 reg) |
83 | { |
84 | u32 offset = PIN_OFFSET(pin); |
85 | u32 reg_off = REG_OFFSET(0, reg, pin); |
86 | u32 val; |
87 | |
88 | regmap_read(map: regmap, reg: reg_off, val: &val); |
89 | |
90 | return !!(val & (1 << offset)); |
91 | } |
92 | |
93 | static inline void plgpio_reg_set(struct regmap *regmap, u32 pin, u32 reg) |
94 | { |
95 | u32 offset = PIN_OFFSET(pin); |
96 | u32 reg_off = REG_OFFSET(0, reg, pin); |
97 | u32 mask; |
98 | |
99 | mask = 1 << offset; |
100 | regmap_update_bits(map: regmap, reg: reg_off, mask, val: mask); |
101 | } |
102 | |
103 | static inline void plgpio_reg_reset(struct regmap *regmap, u32 pin, u32 reg) |
104 | { |
105 | u32 offset = PIN_OFFSET(pin); |
106 | u32 reg_off = REG_OFFSET(0, reg, pin); |
107 | u32 mask; |
108 | |
109 | mask = 1 << offset; |
110 | regmap_update_bits(map: regmap, reg: reg_off, mask, val: 0); |
111 | } |
112 | |
113 | |
114 | /* gpio framework specific routines */ |
115 | static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset) |
116 | { |
117 | struct plgpio *plgpio = gpiochip_get_data(gc: chip); |
118 | unsigned long flags; |
119 | |
120 | /* get correct offset for "offset" pin */ |
121 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) { |
122 | offset = plgpio->p2o(offset); |
123 | if (offset == -1) |
124 | return -EINVAL; |
125 | } |
126 | |
127 | spin_lock_irqsave(&plgpio->lock, flags); |
128 | plgpio_reg_set(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.dir); |
129 | spin_unlock_irqrestore(lock: &plgpio->lock, flags); |
130 | |
131 | return 0; |
132 | } |
133 | |
134 | static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset, |
135 | int value) |
136 | { |
137 | struct plgpio *plgpio = gpiochip_get_data(gc: chip); |
138 | unsigned long flags; |
139 | unsigned dir_offset = offset, wdata_offset = offset, tmp; |
140 | |
141 | /* get correct offset for "offset" pin */ |
142 | if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) { |
143 | tmp = plgpio->p2o(offset); |
144 | if (tmp == -1) |
145 | return -EINVAL; |
146 | |
147 | if (plgpio->p2o_regs & PTO_DIR_REG) |
148 | dir_offset = tmp; |
149 | if (plgpio->p2o_regs & PTO_WDATA_REG) |
150 | wdata_offset = tmp; |
151 | } |
152 | |
153 | spin_lock_irqsave(&plgpio->lock, flags); |
154 | if (value) |
155 | plgpio_reg_set(regmap: plgpio->regmap, pin: wdata_offset, |
156 | reg: plgpio->regs.wdata); |
157 | else |
158 | plgpio_reg_reset(regmap: plgpio->regmap, pin: wdata_offset, |
159 | reg: plgpio->regs.wdata); |
160 | |
161 | plgpio_reg_reset(regmap: plgpio->regmap, pin: dir_offset, reg: plgpio->regs.dir); |
162 | spin_unlock_irqrestore(lock: &plgpio->lock, flags); |
163 | |
164 | return 0; |
165 | } |
166 | |
167 | static int plgpio_get_value(struct gpio_chip *chip, unsigned offset) |
168 | { |
169 | struct plgpio *plgpio = gpiochip_get_data(gc: chip); |
170 | |
171 | if (offset >= chip->ngpio) |
172 | return -EINVAL; |
173 | |
174 | /* get correct offset for "offset" pin */ |
175 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) { |
176 | offset = plgpio->p2o(offset); |
177 | if (offset == -1) |
178 | return -EINVAL; |
179 | } |
180 | |
181 | return is_plgpio_set(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.rdata); |
182 | } |
183 | |
184 | static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value) |
185 | { |
186 | struct plgpio *plgpio = gpiochip_get_data(gc: chip); |
187 | |
188 | if (offset >= chip->ngpio) |
189 | return; |
190 | |
191 | /* get correct offset for "offset" pin */ |
192 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) { |
193 | offset = plgpio->p2o(offset); |
194 | if (offset == -1) |
195 | return; |
196 | } |
197 | |
198 | if (value) |
199 | plgpio_reg_set(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.wdata); |
200 | else |
201 | plgpio_reg_reset(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.wdata); |
202 | } |
203 | |
204 | static int plgpio_request(struct gpio_chip *chip, unsigned offset) |
205 | { |
206 | struct plgpio *plgpio = gpiochip_get_data(gc: chip); |
207 | unsigned long flags; |
208 | int ret = 0; |
209 | |
210 | if (offset >= chip->ngpio) |
211 | return -EINVAL; |
212 | |
213 | ret = pinctrl_gpio_request(gc: chip, offset); |
214 | if (ret) |
215 | return ret; |
216 | |
217 | if (!IS_ERR(ptr: plgpio->clk)) { |
218 | ret = clk_enable(clk: plgpio->clk); |
219 | if (ret) |
220 | goto err0; |
221 | } |
222 | |
223 | if (plgpio->regs.enb == -1) |
224 | return 0; |
225 | |
226 | /* |
227 | * put gpio in IN mode before enabling it. This make enabling gpio safe |
228 | */ |
229 | ret = plgpio_direction_input(chip, offset); |
230 | if (ret) |
231 | goto err1; |
232 | |
233 | /* get correct offset for "offset" pin */ |
234 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) { |
235 | offset = plgpio->p2o(offset); |
236 | if (offset == -1) { |
237 | ret = -EINVAL; |
238 | goto err1; |
239 | } |
240 | } |
241 | |
242 | spin_lock_irqsave(&plgpio->lock, flags); |
243 | plgpio_reg_set(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.enb); |
244 | spin_unlock_irqrestore(lock: &plgpio->lock, flags); |
245 | return 0; |
246 | |
247 | err1: |
248 | if (!IS_ERR(ptr: plgpio->clk)) |
249 | clk_disable(clk: plgpio->clk); |
250 | err0: |
251 | pinctrl_gpio_free(gc: chip, offset); |
252 | return ret; |
253 | } |
254 | |
255 | static void plgpio_free(struct gpio_chip *chip, unsigned offset) |
256 | { |
257 | struct plgpio *plgpio = gpiochip_get_data(gc: chip); |
258 | unsigned long flags; |
259 | |
260 | if (offset >= chip->ngpio) |
261 | return; |
262 | |
263 | if (plgpio->regs.enb == -1) |
264 | goto disable_clk; |
265 | |
266 | /* get correct offset for "offset" pin */ |
267 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) { |
268 | offset = plgpio->p2o(offset); |
269 | if (offset == -1) |
270 | return; |
271 | } |
272 | |
273 | spin_lock_irqsave(&plgpio->lock, flags); |
274 | plgpio_reg_reset(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.enb); |
275 | spin_unlock_irqrestore(lock: &plgpio->lock, flags); |
276 | |
277 | disable_clk: |
278 | if (!IS_ERR(ptr: plgpio->clk)) |
279 | clk_disable(clk: plgpio->clk); |
280 | |
281 | pinctrl_gpio_free(gc: chip, offset); |
282 | } |
283 | |
284 | /* PLGPIO IRQ */ |
285 | static void plgpio_irq_disable(struct irq_data *d) |
286 | { |
287 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
288 | struct plgpio *plgpio = gpiochip_get_data(gc); |
289 | int offset = d->hwirq; |
290 | unsigned long flags; |
291 | |
292 | /* get correct offset for "offset" pin */ |
293 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) { |
294 | offset = plgpio->p2o(offset); |
295 | if (offset == -1) |
296 | return; |
297 | } |
298 | |
299 | spin_lock_irqsave(&plgpio->lock, flags); |
300 | plgpio_reg_set(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.ie); |
301 | spin_unlock_irqrestore(lock: &plgpio->lock, flags); |
302 | gpiochip_disable_irq(gc, offset: irqd_to_hwirq(d)); |
303 | } |
304 | |
305 | static void plgpio_irq_enable(struct irq_data *d) |
306 | { |
307 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
308 | struct plgpio *plgpio = gpiochip_get_data(gc); |
309 | int offset = d->hwirq; |
310 | unsigned long flags; |
311 | |
312 | /* get correct offset for "offset" pin */ |
313 | if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) { |
314 | offset = plgpio->p2o(offset); |
315 | if (offset == -1) |
316 | return; |
317 | } |
318 | |
319 | gpiochip_enable_irq(gc, offset: irqd_to_hwirq(d)); |
320 | spin_lock_irqsave(&plgpio->lock, flags); |
321 | plgpio_reg_reset(regmap: plgpio->regmap, pin: offset, reg: plgpio->regs.ie); |
322 | spin_unlock_irqrestore(lock: &plgpio->lock, flags); |
323 | } |
324 | |
325 | static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger) |
326 | { |
327 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
328 | struct plgpio *plgpio = gpiochip_get_data(gc); |
329 | int offset = d->hwirq; |
330 | u32 reg_off; |
331 | unsigned int supported_type = 0, val; |
332 | |
333 | if (offset >= plgpio->chip.ngpio) |
334 | return -EINVAL; |
335 | |
336 | if (plgpio->regs.eit == -1) |
337 | supported_type = IRQ_TYPE_LEVEL_HIGH; |
338 | else |
339 | supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; |
340 | |
341 | if (!(trigger & supported_type)) |
342 | return -EINVAL; |
343 | |
344 | if (plgpio->regs.eit == -1) |
345 | return 0; |
346 | |
347 | reg_off = REG_OFFSET(0, plgpio->regs.eit, offset); |
348 | regmap_read(map: plgpio->regmap, reg: reg_off, val: &val); |
349 | |
350 | offset = PIN_OFFSET(offset); |
351 | if (trigger & IRQ_TYPE_EDGE_RISING) |
352 | regmap_write(map: plgpio->regmap, reg: reg_off, val: val | (1 << offset)); |
353 | else |
354 | regmap_write(map: plgpio->regmap, reg: reg_off, val: val & ~(1 << offset)); |
355 | |
356 | return 0; |
357 | } |
358 | |
359 | static const struct irq_chip plgpio_irqchip = { |
360 | .name = "PLGPIO" , |
361 | .irq_enable = plgpio_irq_enable, |
362 | .irq_disable = plgpio_irq_disable, |
363 | .irq_set_type = plgpio_irq_set_type, |
364 | .flags = IRQCHIP_IMMUTABLE, |
365 | GPIOCHIP_IRQ_RESOURCE_HELPERS, |
366 | }; |
367 | |
368 | static void plgpio_irq_handler(struct irq_desc *desc) |
369 | { |
370 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
371 | struct plgpio *plgpio = gpiochip_get_data(gc); |
372 | struct irq_chip *irqchip = irq_desc_get_chip(desc); |
373 | int regs_count, count, pin, offset, i = 0; |
374 | u32 pending; |
375 | unsigned long pendingl; |
376 | |
377 | count = plgpio->chip.ngpio; |
378 | regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG); |
379 | |
380 | chained_irq_enter(chip: irqchip, desc); |
381 | /* check all plgpio MIS registers for a possible interrupt */ |
382 | for (; i < regs_count; i++) { |
383 | regmap_read(map: plgpio->regmap, reg: plgpio->regs.mis + |
384 | i * sizeof(int *), val: &pending); |
385 | if (!pending) |
386 | continue; |
387 | |
388 | /* clear interrupts */ |
389 | regmap_write(map: plgpio->regmap, reg: plgpio->regs.mis + |
390 | i * sizeof(int *), val: ~pending); |
391 | /* |
392 | * clear extra bits in last register having gpios < MAX/REG |
393 | * ex: Suppose there are max 102 plgpios. then last register |
394 | * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits |
395 | * so, we must not take other 28 bits into consideration for |
396 | * checking interrupt. so clear those bits. |
397 | */ |
398 | count = count - i * MAX_GPIO_PER_REG; |
399 | if (count < MAX_GPIO_PER_REG) |
400 | pending &= (1 << count) - 1; |
401 | |
402 | pendingl = pending; |
403 | for_each_set_bit(offset, &pendingl, MAX_GPIO_PER_REG) { |
404 | /* get correct pin for "offset" */ |
405 | if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) { |
406 | pin = plgpio->o2p(offset); |
407 | if (pin == -1) |
408 | continue; |
409 | } else |
410 | pin = offset; |
411 | |
412 | /* get correct irq line number */ |
413 | pin = i * MAX_GPIO_PER_REG + pin; |
414 | generic_handle_domain_irq(domain: gc->irq.domain, hwirq: pin); |
415 | } |
416 | } |
417 | chained_irq_exit(chip: irqchip, desc); |
418 | } |
419 | |
420 | /* |
421 | * pin to offset and offset to pin converter functions |
422 | * |
423 | * In spear310 there is inconsistency among bit positions in plgpio regiseters, |
424 | * for different plgpio pins. For example: for pin 27, bit offset is 23, pin |
425 | * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1 |
426 | */ |
427 | static int spear310_p2o(int pin) |
428 | { |
429 | int offset = pin; |
430 | |
431 | if (pin <= 27) |
432 | offset += 4; |
433 | else if (pin <= 33) |
434 | offset = -1; |
435 | else if (pin <= 97) |
436 | offset -= 2; |
437 | else if (pin <= 101) |
438 | offset = 101 - pin; |
439 | else |
440 | offset = -1; |
441 | |
442 | return offset; |
443 | } |
444 | |
445 | static int spear310_o2p(int offset) |
446 | { |
447 | if (offset <= 3) |
448 | return 101 - offset; |
449 | else if (offset <= 31) |
450 | return offset - 4; |
451 | else |
452 | return offset + 2; |
453 | } |
454 | |
455 | static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio) |
456 | { |
457 | struct device_node *np = pdev->dev.of_node; |
458 | int ret = -EINVAL; |
459 | u32 val; |
460 | |
461 | if (of_machine_is_compatible(compat: "st,spear310" )) { |
462 | plgpio->p2o = spear310_p2o; |
463 | plgpio->o2p = spear310_o2p; |
464 | plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG | |
465 | PTO_RDATA_REG | PTO_MIS_REG; |
466 | } |
467 | |
468 | if (!of_property_read_u32(np, propname: "st-plgpio,ngpio" , out_value: &val)) { |
469 | plgpio->chip.ngpio = val; |
470 | } else { |
471 | dev_err(&pdev->dev, "DT: Invalid ngpio field\n" ); |
472 | goto end; |
473 | } |
474 | |
475 | if (!of_property_read_u32(np, propname: "st-plgpio,enb-reg" , out_value: &val)) |
476 | plgpio->regs.enb = val; |
477 | else |
478 | plgpio->regs.enb = -1; |
479 | |
480 | if (!of_property_read_u32(np, propname: "st-plgpio,wdata-reg" , out_value: &val)) { |
481 | plgpio->regs.wdata = val; |
482 | } else { |
483 | dev_err(&pdev->dev, "DT: Invalid wdata reg\n" ); |
484 | goto end; |
485 | } |
486 | |
487 | if (!of_property_read_u32(np, propname: "st-plgpio,dir-reg" , out_value: &val)) { |
488 | plgpio->regs.dir = val; |
489 | } else { |
490 | dev_err(&pdev->dev, "DT: Invalid dir reg\n" ); |
491 | goto end; |
492 | } |
493 | |
494 | if (!of_property_read_u32(np, propname: "st-plgpio,ie-reg" , out_value: &val)) { |
495 | plgpio->regs.ie = val; |
496 | } else { |
497 | dev_err(&pdev->dev, "DT: Invalid ie reg\n" ); |
498 | goto end; |
499 | } |
500 | |
501 | if (!of_property_read_u32(np, propname: "st-plgpio,rdata-reg" , out_value: &val)) { |
502 | plgpio->regs.rdata = val; |
503 | } else { |
504 | dev_err(&pdev->dev, "DT: Invalid rdata reg\n" ); |
505 | goto end; |
506 | } |
507 | |
508 | if (!of_property_read_u32(np, propname: "st-plgpio,mis-reg" , out_value: &val)) { |
509 | plgpio->regs.mis = val; |
510 | } else { |
511 | dev_err(&pdev->dev, "DT: Invalid mis reg\n" ); |
512 | goto end; |
513 | } |
514 | |
515 | if (!of_property_read_u32(np, propname: "st-plgpio,eit-reg" , out_value: &val)) |
516 | plgpio->regs.eit = val; |
517 | else |
518 | plgpio->regs.eit = -1; |
519 | |
520 | return 0; |
521 | |
522 | end: |
523 | return ret; |
524 | } |
525 | |
526 | static int plgpio_probe(struct platform_device *pdev) |
527 | { |
528 | struct device_node *regmap_np; |
529 | struct plgpio *plgpio; |
530 | int ret, irq; |
531 | |
532 | plgpio = devm_kzalloc(dev: &pdev->dev, size: sizeof(*plgpio), GFP_KERNEL); |
533 | if (!plgpio) |
534 | return -ENOMEM; |
535 | |
536 | regmap_np = of_parse_phandle(np: pdev->dev.of_node, phandle_name: "regmap" , index: 0); |
537 | if (regmap_np) { |
538 | plgpio->regmap = device_node_to_regmap(np: regmap_np); |
539 | of_node_put(node: regmap_np); |
540 | if (IS_ERR(ptr: plgpio->regmap)) { |
541 | dev_err(&pdev->dev, "Retrieve regmap failed (%pe)\n" , |
542 | plgpio->regmap); |
543 | return PTR_ERR(ptr: plgpio->regmap); |
544 | } |
545 | } else { |
546 | plgpio->regmap = device_node_to_regmap(np: pdev->dev.of_node); |
547 | if (IS_ERR(ptr: plgpio->regmap)) { |
548 | dev_err(&pdev->dev, "Init regmap failed (%pe)\n" , |
549 | plgpio->regmap); |
550 | return PTR_ERR(ptr: plgpio->regmap); |
551 | } |
552 | } |
553 | |
554 | ret = plgpio_probe_dt(pdev, plgpio); |
555 | if (ret) { |
556 | dev_err(&pdev->dev, "DT probe failed\n" ); |
557 | return ret; |
558 | } |
559 | |
560 | plgpio->clk = devm_clk_get(dev: &pdev->dev, NULL); |
561 | if (IS_ERR(ptr: plgpio->clk)) |
562 | dev_warn(&pdev->dev, "clk_get() failed, work without it\n" ); |
563 | |
564 | #ifdef CONFIG_PM_SLEEP |
565 | plgpio->csave_regs = devm_kcalloc(dev: &pdev->dev, |
566 | DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG), |
567 | size: sizeof(*plgpio->csave_regs), |
568 | GFP_KERNEL); |
569 | if (!plgpio->csave_regs) |
570 | return -ENOMEM; |
571 | #endif |
572 | |
573 | platform_set_drvdata(pdev, data: plgpio); |
574 | spin_lock_init(&plgpio->lock); |
575 | |
576 | plgpio->chip.base = -1; |
577 | plgpio->chip.request = plgpio_request; |
578 | plgpio->chip.free = plgpio_free; |
579 | plgpio->chip.direction_input = plgpio_direction_input; |
580 | plgpio->chip.direction_output = plgpio_direction_output; |
581 | plgpio->chip.get = plgpio_get_value; |
582 | plgpio->chip.set = plgpio_set_value; |
583 | plgpio->chip.label = dev_name(dev: &pdev->dev); |
584 | plgpio->chip.parent = &pdev->dev; |
585 | plgpio->chip.owner = THIS_MODULE; |
586 | |
587 | if (!IS_ERR(ptr: plgpio->clk)) { |
588 | ret = clk_prepare(clk: plgpio->clk); |
589 | if (ret) { |
590 | dev_err(&pdev->dev, "clk prepare failed\n" ); |
591 | return ret; |
592 | } |
593 | } |
594 | |
595 | irq = platform_get_irq(pdev, 0); |
596 | if (irq > 0) { |
597 | struct gpio_irq_chip *girq; |
598 | |
599 | girq = &plgpio->chip.irq; |
600 | gpio_irq_chip_set_chip(girq, chip: &plgpio_irqchip); |
601 | girq->parent_handler = plgpio_irq_handler; |
602 | girq->num_parents = 1; |
603 | girq->parents = devm_kcalloc(dev: &pdev->dev, n: 1, |
604 | size: sizeof(*girq->parents), |
605 | GFP_KERNEL); |
606 | if (!girq->parents) |
607 | return -ENOMEM; |
608 | girq->parents[0] = irq; |
609 | girq->default_type = IRQ_TYPE_NONE; |
610 | girq->handler = handle_simple_irq; |
611 | dev_info(&pdev->dev, "PLGPIO registering with IRQs\n" ); |
612 | } else { |
613 | dev_info(&pdev->dev, "PLGPIO registering without IRQs\n" ); |
614 | } |
615 | |
616 | ret = gpiochip_add_data(&plgpio->chip, plgpio); |
617 | if (ret) { |
618 | dev_err(&pdev->dev, "unable to add gpio chip\n" ); |
619 | goto unprepare_clk; |
620 | } |
621 | |
622 | return 0; |
623 | |
624 | unprepare_clk: |
625 | if (!IS_ERR(ptr: plgpio->clk)) |
626 | clk_unprepare(clk: plgpio->clk); |
627 | |
628 | return ret; |
629 | } |
630 | |
631 | #ifdef CONFIG_PM_SLEEP |
632 | static int plgpio_suspend(struct device *dev) |
633 | { |
634 | struct plgpio *plgpio = dev_get_drvdata(dev); |
635 | int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG); |
636 | u32 off; |
637 | |
638 | for (i = 0; i < reg_count; i++) { |
639 | off = i * sizeof(int *); |
640 | |
641 | if (plgpio->regs.enb != -1) |
642 | regmap_read(map: plgpio->regmap, reg: plgpio->regs.enb + off, |
643 | val: &plgpio->csave_regs[i].enb); |
644 | if (plgpio->regs.eit != -1) |
645 | regmap_read(map: plgpio->regmap, reg: plgpio->regs.eit + off, |
646 | val: &plgpio->csave_regs[i].eit); |
647 | regmap_read(map: plgpio->regmap, reg: plgpio->regs.wdata + off, |
648 | val: &plgpio->csave_regs[i].wdata); |
649 | regmap_read(map: plgpio->regmap, reg: plgpio->regs.dir + off, |
650 | val: &plgpio->csave_regs[i].dir); |
651 | regmap_read(map: plgpio->regmap, reg: plgpio->regs.ie + off, |
652 | val: &plgpio->csave_regs[i].ie); |
653 | } |
654 | |
655 | return 0; |
656 | } |
657 | |
658 | /* |
659 | * This is used to correct the values in end registers. End registers contain |
660 | * extra bits that might be used for other purpose in platform. So, we shouldn't |
661 | * overwrite these bits. This macro, reads given register again, preserves other |
662 | * bit values (non-plgpio bits), and retain captured value (plgpio bits). |
663 | */ |
664 | #define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \ |
665 | { \ |
666 | regmap_read(plgpio->regmap, plgpio->regs.__reg + _off, &_tmp); \ |
667 | _tmp &= ~_mask; \ |
668 | plgpio->csave_regs[i].__reg = \ |
669 | _tmp | (plgpio->csave_regs[i].__reg & _mask); \ |
670 | } |
671 | |
672 | static int plgpio_resume(struct device *dev) |
673 | { |
674 | struct plgpio *plgpio = dev_get_drvdata(dev); |
675 | int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG); |
676 | u32 off; |
677 | u32 mask, tmp; |
678 | |
679 | for (i = 0; i < reg_count; i++) { |
680 | off = i * sizeof(int *); |
681 | |
682 | if (i == reg_count - 1) { |
683 | mask = (1 << (plgpio->chip.ngpio - i * |
684 | MAX_GPIO_PER_REG)) - 1; |
685 | |
686 | if (plgpio->regs.enb != -1) |
687 | plgpio_prepare_reg(enb, off, mask, tmp); |
688 | |
689 | if (plgpio->regs.eit != -1) |
690 | plgpio_prepare_reg(eit, off, mask, tmp); |
691 | |
692 | plgpio_prepare_reg(wdata, off, mask, tmp); |
693 | plgpio_prepare_reg(dir, off, mask, tmp); |
694 | plgpio_prepare_reg(ie, off, mask, tmp); |
695 | } |
696 | |
697 | regmap_write(map: plgpio->regmap, reg: plgpio->regs.wdata + off, |
698 | val: plgpio->csave_regs[i].wdata); |
699 | |
700 | regmap_write(map: plgpio->regmap, reg: plgpio->regs.dir + off, |
701 | val: plgpio->csave_regs[i].dir); |
702 | |
703 | if (plgpio->regs.eit != -1) |
704 | regmap_write(map: plgpio->regmap, reg: plgpio->regs.eit + off, |
705 | val: plgpio->csave_regs[i].eit); |
706 | |
707 | regmap_write(map: plgpio->regmap, reg: plgpio->regs.ie + off, |
708 | val: plgpio->csave_regs[i].ie); |
709 | |
710 | if (plgpio->regs.enb != -1) |
711 | regmap_write(map: plgpio->regmap, reg: plgpio->regs.enb + off, |
712 | val: plgpio->csave_regs[i].enb); |
713 | } |
714 | |
715 | return 0; |
716 | } |
717 | #endif |
718 | |
719 | static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume); |
720 | |
721 | static const struct of_device_id plgpio_of_match[] = { |
722 | { .compatible = "st,spear-plgpio" }, |
723 | {} |
724 | }; |
725 | |
726 | static struct platform_driver plgpio_driver = { |
727 | .probe = plgpio_probe, |
728 | .driver = { |
729 | .name = "spear-plgpio" , |
730 | .pm = &plgpio_dev_pm_ops, |
731 | .of_match_table = plgpio_of_match, |
732 | }, |
733 | }; |
734 | |
735 | static int __init plgpio_init(void) |
736 | { |
737 | return platform_driver_register(&plgpio_driver); |
738 | } |
739 | subsys_initcall(plgpio_init); |
740 | |