blob: 8f132fd689b5d3abe6f4f7ca403595493d258e16 [file] [log] [blame]
Karthikeyan Ramasubramanian97a10282016-09-16 12:01:18 -06001/* drivers/gpio/gpio-msm-smp2p.c
2 *
3 * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/bitmap.h>
17#include <linux/of.h>
18#include <linux/gpio.h>
19#include <linux/interrupt.h>
20#include <linux/irq.h>
21#include <linux/irqdomain.h>
22#include <linux/slab.h>
23#include <linux/list.h>
24#include <linux/ipc_logging.h>
25#include "../soc/qcom/smp2p_private_api.h"
26#include "../soc/qcom/smp2p_private.h"
27
28/* GPIO device - one per SMP2P entry. */
29struct smp2p_chip_dev {
30 struct list_head entry_list;
31 char name[SMP2P_MAX_ENTRY_NAME];
32 int remote_pid;
33 bool is_inbound;
34 bool is_open;
35 bool in_shadow;
36 uint32_t shadow_value;
37 struct work_struct shadow_work;
38 spinlock_t shadow_lock;
39 struct notifier_block out_notifier;
40 struct notifier_block in_notifier;
41 struct msm_smp2p_out *out_handle;
42
43 struct gpio_chip gpio;
44 struct irq_domain *irq_domain;
45 int irq_base;
46
47 spinlock_t irq_lock;
48 DECLARE_BITMAP(irq_enabled, SMP2P_BITS_PER_ENTRY);
49 DECLARE_BITMAP(irq_rising_edge, SMP2P_BITS_PER_ENTRY);
50 DECLARE_BITMAP(irq_falling_edge, SMP2P_BITS_PER_ENTRY);
51};
52
53static struct platform_driver smp2p_gpio_driver;
54static struct lock_class_key smp2p_gpio_lock_class;
55static struct irq_chip smp2p_gpio_irq_chip;
56static DEFINE_SPINLOCK(smp2p_entry_lock_lha1);
57static LIST_HEAD(smp2p_entry_list);
58
59/* Used for mapping edge to name for logging. */
60static const char * const edge_names[] = {
61 "-",
62 "0->1",
63 "1->0",
64 "-",
65};
66
67/* Used for mapping edge to value for logging. */
68static const char * const edge_name_rising[] = {
69 "-",
70 "0->1",
71};
72
73/* Used for mapping edge to value for logging. */
74static const char * const edge_name_falling[] = {
75 "-",
76 "1->0",
77};
78
79static int smp2p_gpio_to_irq(struct gpio_chip *cp,
80 unsigned int offset);
81
82/**
83 * smp2p_get_value - Retrieves GPIO value.
84 *
85 * @cp: GPIO chip pointer
86 * @offset: Pin offset
87 * @returns: >=0: value of GPIO Pin; < 0 for error
88 *
89 * Error codes:
90 * -ENODEV - chip/entry invalid
91 * -ENETDOWN - valid entry, but entry not yet created
92 */
93static int smp2p_get_value(struct gpio_chip *cp,
94 unsigned int offset)
95{
96 struct smp2p_chip_dev *chip;
97 int ret = 0;
98 uint32_t data;
99
100 if (!cp)
101 return -ENODEV;
102
103 chip = container_of(cp, struct smp2p_chip_dev, gpio);
104 if (!chip->is_open)
105 return -ENETDOWN;
106
107 if (chip->is_inbound)
108 ret = msm_smp2p_in_read(chip->remote_pid, chip->name, &data);
109 else
110 ret = msm_smp2p_out_read(chip->out_handle, &data);
111
112 if (!ret)
113 ret = (data & (1 << offset)) ? 1 : 0;
114
115 return ret;
116}
117
118/**
119 * smp2p_set_value - Sets GPIO value.
120 *
121 * @cp: GPIO chip pointer
122 * @offset: Pin offset
123 * @value: New value
124 */
125static void smp2p_set_value(struct gpio_chip *cp, unsigned int offset,
126 int value)
127{
128 struct smp2p_chip_dev *chip;
129 uint32_t data_set;
130 uint32_t data_clear;
131 bool send_irq;
132 int ret;
133 unsigned long flags;
134
135 if (!cp)
136 return;
137
138 chip = container_of(cp, struct smp2p_chip_dev, gpio);
139
140 if (chip->is_inbound) {
141 SMP2P_INFO("%s: '%s':%d virq %d invalid operation\n",
142 __func__, chip->name, chip->remote_pid,
143 chip->irq_base + offset);
144 return;
145 }
146
147 if (value & SMP2P_GPIO_NO_INT) {
148 value &= ~SMP2P_GPIO_NO_INT;
149 send_irq = false;
150 } else {
151 send_irq = true;
152 }
153
154 if (value) {
155 data_set = 1 << offset;
156 data_clear = 0;
157 } else {
158 data_set = 0;
159 data_clear = 1 << offset;
160 }
161
162 spin_lock_irqsave(&chip->shadow_lock, flags);
163 if (!chip->is_open) {
164 chip->in_shadow = true;
165 chip->shadow_value &= ~data_clear;
166 chip->shadow_value |= data_set;
167 spin_unlock_irqrestore(&chip->shadow_lock, flags);
168 return;
169 }
170
171 if (chip->in_shadow) {
172 chip->in_shadow = false;
173 chip->shadow_value &= ~data_clear;
174 chip->shadow_value |= data_set;
175 ret = msm_smp2p_out_modify(chip->out_handle,
176 chip->shadow_value, 0x0, send_irq);
177 chip->shadow_value = 0x0;
178 } else {
179 ret = msm_smp2p_out_modify(chip->out_handle,
180 data_set, data_clear, send_irq);
181 }
182 spin_unlock_irqrestore(&chip->shadow_lock, flags);
183
184 if (ret)
185 SMP2P_GPIO("'%s':%d gpio %d set to %d failed (%d)\n",
186 chip->name, chip->remote_pid,
187 chip->gpio.base + offset, value, ret);
188 else
189 SMP2P_GPIO("'%s':%d gpio %d set to %d\n",
190 chip->name, chip->remote_pid,
191 chip->gpio.base + offset, value);
192}
193
194/**
195 * smp2p_direction_input - Sets GPIO direction to input.
196 *
197 * @cp: GPIO chip pointer
198 * @offset: Pin offset
199 * @returns: 0 for success; < 0 for failure
200 */
201static int smp2p_direction_input(struct gpio_chip *cp, unsigned int offset)
202{
203 struct smp2p_chip_dev *chip;
204
205 if (!cp)
206 return -ENODEV;
207
208 chip = container_of(cp, struct smp2p_chip_dev, gpio);
209 if (!chip->is_inbound)
210 return -EPERM;
211
212 return 0;
213}
214
215/**
216 * smp2p_direction_output - Sets GPIO direction to output.
217 *
218 * @cp: GPIO chip pointer
219 * @offset: Pin offset
220 * @value: Direction
221 * @returns: 0 for success; < 0 for failure
222 */
223static int smp2p_direction_output(struct gpio_chip *cp,
224 unsigned int offset, int value)
225{
226 struct smp2p_chip_dev *chip;
227
228 if (!cp)
229 return -ENODEV;
230
231 chip = container_of(cp, struct smp2p_chip_dev, gpio);
232 if (chip->is_inbound)
233 return -EPERM;
234
235 return 0;
236}
237
238/**
239 * smp2p_gpio_to_irq - Convert GPIO pin to virtual IRQ pin.
240 *
241 * @cp: GPIO chip pointer
242 * @offset: Pin offset
243 * @returns: >0 for virtual irq value; < 0 for failure
244 */
245static int smp2p_gpio_to_irq(struct gpio_chip *cp, unsigned int offset)
246{
247 struct smp2p_chip_dev *chip;
248
249 chip = container_of(cp, struct smp2p_chip_dev, gpio);
250 if (!cp || chip->irq_base <= 0)
251 return -ENODEV;
252
253 return chip->irq_base + offset;
254}
255
256/**
257 * smp2p_gpio_irq_mask_helper - Mask/Unmask interrupt.
258 *
259 * @d: IRQ data
260 * @mask: true to mask (disable), false to unmask (enable)
261 */
262static void smp2p_gpio_irq_mask_helper(struct irq_data *d, bool mask)
263{
264 struct smp2p_chip_dev *chip;
265 int offset;
266 unsigned long flags;
267
268 chip = (struct smp2p_chip_dev *)irq_get_chip_data(d->irq);
269 if (!chip || chip->irq_base <= 0)
270 return;
271
272 offset = d->irq - chip->irq_base;
273 spin_lock_irqsave(&chip->irq_lock, flags);
274 if (mask)
275 clear_bit(offset, chip->irq_enabled);
276 else
277 set_bit(offset, chip->irq_enabled);
278 spin_unlock_irqrestore(&chip->irq_lock, flags);
279}
280
281/**
282 * smp2p_gpio_irq_mask - Mask interrupt.
283 *
284 * @d: IRQ data
285 */
286static void smp2p_gpio_irq_mask(struct irq_data *d)
287{
288 smp2p_gpio_irq_mask_helper(d, true);
289}
290
291/**
292 * smp2p_gpio_irq_unmask - Unmask interrupt.
293 *
294 * @d: IRQ data
295 */
296static void smp2p_gpio_irq_unmask(struct irq_data *d)
297{
298 smp2p_gpio_irq_mask_helper(d, false);
299}
300
301/**
302 * smp2p_gpio_irq_set_type - Set interrupt edge type.
303 *
304 * @d: IRQ data
305 * @type: Edge type for interrupt
306 * @returns 0 for success; < 0 for failure
307 */
308static int smp2p_gpio_irq_set_type(struct irq_data *d, unsigned int type)
309{
310 struct smp2p_chip_dev *chip;
311 int offset;
312 unsigned long flags;
313 int ret = 0;
314
315 chip = (struct smp2p_chip_dev *)irq_get_chip_data(d->irq);
316 if (!chip)
317 return -ENODEV;
318
319 if (chip->irq_base <= 0) {
320 SMP2P_ERR("%s: '%s':%d virqbase %d invalid\n",
321 __func__, chip->name, chip->remote_pid,
322 chip->irq_base);
323 return -ENODEV;
324 }
325
326 offset = d->irq - chip->irq_base;
327
328 spin_lock_irqsave(&chip->irq_lock, flags);
329 clear_bit(offset, chip->irq_rising_edge);
330 clear_bit(offset, chip->irq_falling_edge);
331 switch (type) {
332 case IRQ_TYPE_EDGE_RISING:
333 set_bit(offset, chip->irq_rising_edge);
334 break;
335
336 case IRQ_TYPE_EDGE_FALLING:
337 set_bit(offset, chip->irq_falling_edge);
338 break;
339
340 case IRQ_TYPE_NONE:
341 case IRQ_TYPE_DEFAULT:
342 case IRQ_TYPE_EDGE_BOTH:
343 set_bit(offset, chip->irq_rising_edge);
344 set_bit(offset, chip->irq_falling_edge);
345 break;
346
347 default:
348 SMP2P_ERR("%s: unsupported interrupt type 0x%x\n",
349 __func__, type);
350 ret = -EINVAL;
351 break;
352 }
353 spin_unlock_irqrestore(&chip->irq_lock, flags);
354 return ret;
355}
356
357/**
358 * smp2p_irq_map - Creates or updates binding of virtual IRQ
359 *
360 * @domain_ptr: Interrupt domain pointer
361 * @virq: Virtual IRQ
362 * @hw: Hardware IRQ (same as virq for nomap)
363 * @returns: 0 for success
364 */
365static int smp2p_irq_map(struct irq_domain *domain_ptr, unsigned int virq,
366 irq_hw_number_t hw)
367{
368 struct smp2p_chip_dev *chip;
369
370 chip = domain_ptr->host_data;
371 if (!chip) {
372 SMP2P_ERR("%s: invalid domain ptr\n", __func__);
373 return -ENODEV;
374 }
375
376 /* map chip structures to device */
377 irq_set_lockdep_class(virq, &smp2p_gpio_lock_class);
378 irq_set_chip_and_handler(virq, &smp2p_gpio_irq_chip,
379 handle_level_irq);
380 irq_set_chip_data(virq, chip);
381
382 return 0;
383}
384
385static struct irq_chip smp2p_gpio_irq_chip = {
386 .name = "smp2p_gpio",
387 .irq_mask = smp2p_gpio_irq_mask,
388 .irq_unmask = smp2p_gpio_irq_unmask,
389 .irq_set_type = smp2p_gpio_irq_set_type,
390};
391
392/* No-map interrupt Domain */
393static const struct irq_domain_ops smp2p_irq_domain_ops = {
394 .map = smp2p_irq_map,
395};
396
397/**
398 * msm_summary_irq_handler - Handles inbound entry change notification.
399 *
400 * @chip: GPIO chip pointer
401 * @entry: Change notification data
402 *
403 * Whenever an entry changes, this callback is triggered to determine
404 * which bits changed and if the corresponding interrupts need to be
405 * triggered.
406 */
407static void msm_summary_irq_handler(struct smp2p_chip_dev *chip,
408 struct msm_smp2p_update_notif *entry)
409{
410 int i;
411 uint32_t cur_val;
412 uint32_t prev_val;
413 uint32_t edge;
414 unsigned long flags;
415 bool trigger_interrupt;
416 bool irq_rising;
417 bool irq_falling;
418
419 cur_val = entry->current_value;
420 prev_val = entry->previous_value;
421
422 if (chip->irq_base <= 0)
423 return;
424
425 SMP2P_GPIO("'%s':%d GPIO Summary IRQ Change %08x->%08x\n",
426 chip->name, chip->remote_pid, prev_val, cur_val);
427
428 for (i = 0; i < SMP2P_BITS_PER_ENTRY; ++i) {
429 spin_lock_irqsave(&chip->irq_lock, flags);
430 trigger_interrupt = false;
431 edge = (prev_val & 0x1) << 1 | (cur_val & 0x1);
432 irq_rising = test_bit(i, chip->irq_rising_edge);
433 irq_falling = test_bit(i, chip->irq_falling_edge);
434
435 if (test_bit(i, chip->irq_enabled)) {
436 if (edge == 0x1 && irq_rising)
437 /* 0->1 transition */
438 trigger_interrupt = true;
439 else if (edge == 0x2 && irq_falling)
440 /* 1->0 transition */
441 trigger_interrupt = true;
442 } else {
443 SMP2P_GPIO(
444 "'%s':%d GPIO bit %d virq %d (%s,%s) - edge %s disabled\n",
445 chip->name, chip->remote_pid, i,
446 chip->irq_base + i,
447 edge_name_rising[irq_rising],
448 edge_name_falling[irq_falling],
449 edge_names[edge]);
450 }
451 spin_unlock_irqrestore(&chip->irq_lock, flags);
452
453 if (trigger_interrupt) {
454 SMP2P_INFO(
455 "'%s':%d GPIO bit %d virq %d (%s,%s) - edge %s triggering\n",
456 chip->name, chip->remote_pid, i,
457 chip->irq_base + i,
458 edge_name_rising[irq_rising],
459 edge_name_falling[irq_falling],
460 edge_names[edge]);
461 (void)generic_handle_irq(chip->irq_base + i);
462 }
463
464 cur_val >>= 1;
465 prev_val >>= 1;
466 }
467}
468
469/**
470 * Adds an interrupt domain based upon the DT node.
471 *
472 * @chip: pointer to GPIO chip
473 * @node: pointer to Device Tree node
474 */
475static void smp2p_add_irq_domain(struct smp2p_chip_dev *chip,
476 struct device_node *node)
477{
478 int irq_base;
479
480 /* map GPIO pins to interrupts */
481 chip->irq_domain = irq_domain_add_linear(node, SMP2P_BITS_PER_ENTRY,
482 &smp2p_irq_domain_ops, chip);
483 if (!chip->irq_domain) {
484 SMP2P_ERR("%s: unable to create interrupt domain '%s':%d\n",
485 __func__, chip->name, chip->remote_pid);
486 goto domain_fail;
487 }
488
489 /* alloc a contiguous set of virt irqs from anywhere in the irq space */
490 irq_base = irq_alloc_descs_from(0, SMP2P_BITS_PER_ENTRY, of_node_to_nid(
491 irq_domain_get_of_node(chip->irq_domain)));
492 if (irq_base < 0) {
493 SMP2P_ERR("alloc virt irqs failed:%d name:%s pid%d\n", irq_base,
494 chip->name, chip->remote_pid);
495 goto irq_alloc_fail;
496 }
497
498 /* map the allocated irqs to gpios */
499 irq_domain_associate_many(chip->irq_domain, irq_base, 0,
500 SMP2P_BITS_PER_ENTRY);
501
502 chip->irq_base = irq_base;
503 SMP2P_DBG("create mapping:%d naem:%s pid:%d\n", chip->irq_base,
504 chip->name, chip->remote_pid);
505 return;
506
507irq_alloc_fail:
508 irq_domain_remove(chip->irq_domain);
509domain_fail:
510 return;
511}
512
513/**
514 * Notifier function passed into smp2p API for out bound entries.
515 *
516 * @self: Pointer to calling notifier block
517 * @event: Event
518 * @data: Event-specific data
519 * @returns: 0
520 */
521static int smp2p_gpio_out_notify(struct notifier_block *self,
522 unsigned long event, void *data)
523{
524 struct smp2p_chip_dev *chip;
525
526 chip = container_of(self, struct smp2p_chip_dev, out_notifier);
527
528 switch (event) {
529 case SMP2P_OPEN:
530 chip->is_open = 1;
531 SMP2P_GPIO("%s: Opened out '%s':%d in_shadow[%d]\n", __func__,
532 chip->name, chip->remote_pid, chip->in_shadow);
533 if (chip->in_shadow)
534 schedule_work(&chip->shadow_work);
535 break;
536 case SMP2P_ENTRY_UPDATE:
537 break;
538 default:
539 SMP2P_ERR("%s: Unknown event\n", __func__);
540 break;
541 }
542 return 0;
543}
544
545/**
546 * Notifier function passed into smp2p API for in bound entries.
547 *
548 * @self: Pointer to calling notifier block
549 * @event: Event
550 * @data: Event-specific data
551 * @returns: 0
552 */
553static int smp2p_gpio_in_notify(struct notifier_block *self,
554 unsigned long event, void *data)
555{
556 struct smp2p_chip_dev *chip;
557
558 chip = container_of(self, struct smp2p_chip_dev, in_notifier);
559
560 switch (event) {
561 case SMP2P_OPEN:
562 chip->is_open = 1;
563 SMP2P_GPIO("%s: Opened in '%s':%d\n", __func__,
564 chip->name, chip->remote_pid);
565 break;
566 case SMP2P_ENTRY_UPDATE:
567 msm_summary_irq_handler(chip, data);
568 break;
569 default:
570 SMP2P_ERR("%s: Unknown event\n", __func__);
571 break;
572 }
573 return 0;
574}
575
576/**
577 * smp2p_gpio_shadow_worker - Handles shadow updates of an entry.
578 *
579 * @work: Work Item scheduled to handle the shadow updates.
580 */
581static void smp2p_gpio_shadow_worker(struct work_struct *work)
582{
583 struct smp2p_chip_dev *chip;
584 int ret;
585 unsigned long flags;
586
587 chip = container_of(work, struct smp2p_chip_dev, shadow_work);
588 spin_lock_irqsave(&chip->shadow_lock, flags);
589 if (chip->in_shadow) {
590 ret = msm_smp2p_out_modify(chip->out_handle,
591 chip->shadow_value, 0x0, true);
592
593 if (ret)
594 SMP2P_GPIO("'%s':%d shadow val[0x%x] failed(%d)\n",
595 chip->name, chip->remote_pid,
596 chip->shadow_value, ret);
597 else
598 SMP2P_GPIO("'%s':%d shadow val[0x%x]\n",
599 chip->name, chip->remote_pid,
600 chip->shadow_value);
601 chip->shadow_value = 0;
602 chip->in_shadow = false;
603 }
604 spin_unlock_irqrestore(&chip->shadow_lock, flags);
605}
606
607/**
608 * Device tree probe function.
609 *
610 * @pdev: Pointer to device tree data.
611 * @returns: 0 on success; -ENODEV otherwise
612 *
613 * Called for each smp2pgpio entry in the device tree.
614 */
615static int smp2p_gpio_probe(struct platform_device *pdev)
616{
617 struct device_node *node;
618 char *key;
619 struct smp2p_chip_dev *chip;
620 const char *name_tmp;
621 unsigned long flags;
622 bool is_test_entry = false;
623 int ret;
624
625 chip = kzalloc(sizeof(struct smp2p_chip_dev), GFP_KERNEL);
626 if (!chip) {
627 SMP2P_ERR("%s: out of memory\n", __func__);
628 ret = -ENOMEM;
629 goto fail;
630 }
631 spin_lock_init(&chip->irq_lock);
632 spin_lock_init(&chip->shadow_lock);
633 INIT_WORK(&chip->shadow_work, smp2p_gpio_shadow_worker);
634
635 /* parse device tree */
636 node = pdev->dev.of_node;
637 key = "qcom,entry-name";
638 ret = of_property_read_string(node, key, &name_tmp);
639 if (ret) {
640 SMP2P_ERR("%s: missing DT key '%s'\n", __func__, key);
641 goto fail;
642 }
643 strlcpy(chip->name, name_tmp, sizeof(chip->name));
644
645 key = "qcom,remote-pid";
646 ret = of_property_read_u32(node, key, &chip->remote_pid);
647 if (ret) {
648 SMP2P_ERR("%s: missing DT key '%s'\n", __func__, key);
649 goto fail;
650 }
651
652 key = "qcom,is-inbound";
653 chip->is_inbound = of_property_read_bool(node, key);
654
655 /* create virtual GPIO controller */
656 chip->gpio.label = chip->name;
657 chip->gpio.parent = &pdev->dev;
658 chip->gpio.owner = THIS_MODULE;
659 chip->gpio.direction_input = smp2p_direction_input,
660 chip->gpio.get = smp2p_get_value;
661 chip->gpio.direction_output = smp2p_direction_output,
662 chip->gpio.set = smp2p_set_value;
663 chip->gpio.to_irq = smp2p_gpio_to_irq,
664 chip->gpio.base = -1; /* use dynamic GPIO pin allocation */
665 chip->gpio.ngpio = SMP2P_BITS_PER_ENTRY;
666 ret = gpiochip_add(&chip->gpio);
667 if (ret) {
668 SMP2P_ERR("%s: unable to register GPIO '%s' ret %d\n",
669 __func__, chip->name, ret);
670 goto fail;
671 }
672
673 /*
674 * Test entries opened by GPIO Test conflict with loopback
675 * support, so the test entries must be explicitly opened
676 * in the unit test framework.
677 */
678 if (strcmp("smp2p", chip->name) == 0)
679 is_test_entry = true;
680
681 if (!chip->is_inbound) {
682 chip->out_notifier.notifier_call = smp2p_gpio_out_notify;
683 if (!is_test_entry) {
684 ret = msm_smp2p_out_open(chip->remote_pid, chip->name,
685 &chip->out_notifier,
686 &chip->out_handle);
687 if (ret < 0)
688 goto error;
689 }
690 } else {
691 chip->in_notifier.notifier_call = smp2p_gpio_in_notify;
692 if (!is_test_entry) {
693 ret = msm_smp2p_in_register(chip->remote_pid,
694 chip->name,
695 &chip->in_notifier);
696 if (ret < 0)
697 goto error;
698 }
699 }
700
701 spin_lock_irqsave(&smp2p_entry_lock_lha1, flags);
702 list_add(&chip->entry_list, &smp2p_entry_list);
703 spin_unlock_irqrestore(&smp2p_entry_lock_lha1, flags);
704
705 /*
706 * Create interrupt domain - note that chip can't be removed from the
707 * interrupt domain, so chip cannot be deleted after this point.
708 */
709 if (chip->is_inbound)
710 smp2p_add_irq_domain(chip, node);
711 else
712 chip->irq_base = -1;
713
714 SMP2P_GPIO("%s: added %s%s entry '%s':%d gpio %d irq %d",
715 __func__,
716 is_test_entry ? "test " : "",
717 chip->is_inbound ? "in" : "out",
718 chip->name, chip->remote_pid,
719 chip->gpio.base, chip->irq_base);
720
721 return 0;
722error:
723 gpiochip_remove(&chip->gpio);
724
725fail:
726 kfree(chip);
727 return ret;
728}
729
730/**
731 * smp2p_gpio_open_close - Opens or closes entry.
732 *
733 * @entry: Entry to open or close
734 * @do_open: true = open port; false = close
735 */
736static void smp2p_gpio_open_close(struct smp2p_chip_dev *entry,
737 bool do_open)
738{
739 int ret;
740
741 if (do_open) {
742 /* open entry */
743 if (entry->is_inbound)
744 ret = msm_smp2p_in_register(entry->remote_pid,
745 entry->name, &entry->in_notifier);
746 else
747 ret = msm_smp2p_out_open(entry->remote_pid,
748 entry->name, &entry->out_notifier,
749 &entry->out_handle);
750 SMP2P_GPIO("%s: opened %s '%s':%d ret %d\n",
751 __func__,
752 entry->is_inbound ? "in" : "out",
753 entry->name, entry->remote_pid,
754 ret);
755 } else {
756 /* close entry */
757 if (entry->is_inbound)
758 ret = msm_smp2p_in_unregister(entry->remote_pid,
759 entry->name, &entry->in_notifier);
760 else
761 ret = msm_smp2p_out_close(&entry->out_handle);
762 entry->is_open = false;
763 SMP2P_GPIO("%s: closed %s '%s':%d ret %d\n",
764 __func__,
765 entry->is_inbound ? "in" : "out",
766 entry->name, entry->remote_pid, ret);
767 }
768}
769
770/**
771 * smp2p_gpio_open_test_entry - Opens or closes test entries for unit testing.
772 *
773 * @name: Name of the entry
774 * @remote_pid: Remote processor ID
775 * @do_open: true = open port; false = close
776 */
777void smp2p_gpio_open_test_entry(const char *name, int remote_pid, bool do_open)
778{
779 struct smp2p_chip_dev *entry;
780 struct smp2p_chip_dev *start_entry;
781 unsigned long flags;
782
783 spin_lock_irqsave(&smp2p_entry_lock_lha1, flags);
784 if (list_empty(&smp2p_entry_list)) {
785 spin_unlock_irqrestore(&smp2p_entry_lock_lha1, flags);
786 return;
787 }
788 start_entry = list_first_entry(&smp2p_entry_list,
789 struct smp2p_chip_dev,
790 entry_list);
791 entry = start_entry;
792 do {
793 if (!strcmp(entry->name, name)
794 && entry->remote_pid == remote_pid) {
795 /* found entry to change */
796 spin_unlock_irqrestore(&smp2p_entry_lock_lha1, flags);
797 smp2p_gpio_open_close(entry, do_open);
798 spin_lock_irqsave(&smp2p_entry_lock_lha1, flags);
799 }
800 list_rotate_left(&smp2p_entry_list);
801 entry = list_first_entry(&smp2p_entry_list,
802 struct smp2p_chip_dev,
803 entry_list);
804 } while (entry != start_entry);
805 spin_unlock_irqrestore(&smp2p_entry_lock_lha1, flags);
806}
807
808static const struct of_device_id msm_smp2p_match_table[] = {
809 {.compatible = "qcom,smp2pgpio", },
810 {},
811};
812
813static struct platform_driver smp2p_gpio_driver = {
814 .probe = smp2p_gpio_probe,
815 .driver = {
816 .name = "smp2pgpio",
817 .owner = THIS_MODULE,
818 .of_match_table = msm_smp2p_match_table,
819 },
820};
821
822static int smp2p_init(void)
823{
824 INIT_LIST_HEAD(&smp2p_entry_list);
825 return platform_driver_register(&smp2p_gpio_driver);
826}
827module_init(smp2p_init);
828
829static void __exit smp2p_exit(void)
830{
831 platform_driver_unregister(&smp2p_gpio_driver);
832}
833module_exit(smp2p_exit);
834
835MODULE_DESCRIPTION("SMP2P GPIO");
836MODULE_LICENSE("GPL v2");