summaryrefslogtreecommitdiff
path: root/drivers/mxc/pmic/core/pmic_common.c
blob: 7e53121f12b8f031613835745261d0dac3750fe6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @file pmic_common.c
 * @brief This is the common file for the PMIC Core/Protocol driver.
 *
 * @ingroup PMIC_CORE
 */

/*
 * Includes
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kthread.h>
#include <linux/pmic_external.h>
#include <linux/pmic_status.h>

#include <asm/uaccess.h>

#include "pmic.h"

/*
 * Global variables
 */
pmic_version_t mxc_pmic_version;
unsigned int active_events[MAX_ACTIVE_EVENTS];


static struct completion event_completion;
static struct task_struct *tstask;

static int pmic_event_thread_func(void *v)
{
	unsigned int loop;
	unsigned int count = 0;
	unsigned int irq = (int)v;

	while (1) {
		wait_for_completion_interruptible(
				&event_completion);
		if (kthread_should_stop())
			break;

		count = pmic_get_active_events(
				active_events);
		pr_debug("active events number %d\n", count);

	do {
		for (loop = 0; loop < count; loop++)
			pmic_event_callback(active_events[loop]);

		count = pmic_get_active_events(active_events);

	} while (count != 0);
		enable_irq(irq);
	}

	return 0;
}

int pmic_start_event_thread(int irq_num)
{
	int ret = 0;

	if (tstask)
		return ret;

	init_completion(&event_completion);

	tstask = kthread_run(pmic_event_thread_func,
		(void *)irq_num, "pmic-event-thread");
	ret = IS_ERR(tstask) ? -1 : 0;
	if (IS_ERR(tstask))
		tstask = NULL;
	return ret;
}

void pmic_stop_event_thread(void)
{
	if (tstask) {
		complete(&event_completion);
		kthread_stop(tstask);
	}
}

/*!
 * This function is called when pmic interrupt occurs on the processor.
 * It is the interrupt handler for the pmic module.
 *
 * @param        irq        the irq number
 * @param        dev_id     the pointer on the device
 *
 * @return       The function returns IRQ_HANDLED when handled.
 */
irqreturn_t pmic_irq_handler(int irq, void *dev_id)
{
	disable_irq_nosync(irq);
	complete(&event_completion);

	return IRQ_HANDLED;
}

/*!
 * This function is used to determine the PMIC type and its revision.
 *
 * @return      Returns the PMIC type and its revision.
 */

pmic_version_t pmic_get_version(void)
{
	return mxc_pmic_version;
}
EXPORT_SYMBOL(pmic_get_version);