summaryrefslogtreecommitdiff
path: root/drivers/mxc/mcu_pmic/mcu_pmic_core.c
blob: 47c16d1659ca1e633d729400e619224cec559b26 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * Copyright 2008-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 mc9s08dz60/mcu_pmic_core.c
 * @brief This is the main file of mc9s08dz60 Power Control driver.
 *
 * @ingroup PMIC_POWER
 */

/*
 * 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/mfd/mc9s08dz60/pmic.h>
#include <asm/ioctl.h>
#include <asm/uaccess.h>
#include <mach/gpio.h>

#include "mcu_pmic_core.h"
#include "mc9s08dz60.h"
#include "max8660.h"

/* bitfield macros for mcu pmic*/
#define SET_BIT_IN_BYTE(byte, pos) (byte |= (0x01 << pos))
#define CLEAR_BIT_IN_BYTE(byte, pos) (byte &= ~(0x01 << pos))


/* map reg names (enum pmic_reg in pmic_external.h) to real addr*/
const static u8 mcu_pmic_reg_addr_table[] = {
	MCU_VERSION,
	MCU_SECS,
	MCU_MINS,
	MCU_HRS,
	MCU_DAY,
	MCU_DATE,
	MCU_MONTH,
	MCU_YEAR,
	MCU_ALARM_SECS,
	MCU_ALARM_MINS,
	MCU_ALARM_HRS,
	MCU_TS_CONTROL,
	MCU_X_LOW,
	MCU_Y_LOW,
	MCU_XY_HIGH,
	MCU_X_LEFT_LOW,
	MCU_X_LEFT_HIGH,
	MCU_X_RIGHT,
	MCU_Y_TOP_LOW,
	MCU_Y_TOP_HIGH,
	MCU_Y_BOTTOM,
	MCU_RESET_1,
	MCU_RESET_2,
	MCU_POWER_CTL,
	MCU_DELAY_CONFIG,
	MCU_GPIO_1,
	MCU_GPIO_2,
	MCU_KPD_1,
	MCU_KPD_2,
	MCU_KPD_CONTROL,
	MCU_INT_ENABLE_1,
	MCU_INT_ENABLE_2,
	MCU_INT_FLAG_1,
	MCU_INT_FLAG_2,
	MCU_DES_FLAG,
	MAX8660_OUTPUT_ENABLE_1,
	MAX8660_OUTPUT_ENABLE_2,
	MAX8660_VOLT_CHANGE_CONTROL,
	MAX8660_V3_TARGET_VOLT_1,
	MAX8660_V3_TARGET_VOLT_2,
	MAX8660_V4_TARGET_VOLT_1,
	MAX8660_V4_TARGET_VOLT_2,
	MAX8660_V5_TARGET_VOLT_1,
	MAX8660_V5_TARGET_VOLT_2,
	MAX8660_V6V7_TARGET_VOLT,
	MAX8660_FORCE_PWM
};

static int mcu_pmic_read(int reg_num, unsigned int *reg_val)
{
	int ret;
	u8 value = 0;
	/* mcu ops */
	if (reg_num >= REG_MCU_VERSION && reg_num <= REG_MCU_DES_FLAG)
		ret = mc9s08dz60_read_reg(mcu_pmic_reg_addr_table[reg_num],
					&value);
	else if (reg_num >= REG_MAX8660_OUTPUT_ENABLE_1
		   && reg_num <= REG_MAX8660_FORCE_PWM)
		ret = max8660_get_buffered_reg_val(reg_num, &value);
	else
		return -1;

	if (ret < 0)
		return -1;
	*reg_val = value;

	return 0;
}

static int mcu_pmic_write(int reg_num, const unsigned int reg_val)
{
	int ret;
	u8 value = reg_val;
	/* mcu ops */
	if (reg_num >= REG_MCU_VERSION && reg_num <= REG_MCU_DES_FLAG) {

		ret =
		    mc9s08dz60_write_reg(
			mcu_pmic_reg_addr_table[reg_num], value);
		if (ret < 0)
			return -1;
	} else if (reg_num >= REG_MAX8660_OUTPUT_ENABLE_1
		   && reg_num <= REG_MAX8660_FORCE_PWM) {
		ret =
		    max8660_write_reg(mcu_pmic_reg_addr_table[reg_num], value);

		if (ret < 0)
			return -1;

		ret = max8660_save_buffered_reg_val(reg_num, value);
	} else
		return -1;

	return 0;
}

int mcu_pmic_read_reg(int reg, unsigned int *reg_value,
			  unsigned int reg_mask)
{
	int ret = 0;
	unsigned int temp = 0;

	ret = mcu_pmic_read(reg, &temp);
	if (ret != 0)
		return -1;
	*reg_value = (temp & reg_mask);

	pr_debug("Read REG[ %d ] = 0x%x\n", reg, *reg_value);

	return ret;
}


int mcu_pmic_write_reg(int reg, unsigned int reg_value,
			   unsigned int reg_mask)
{
	int ret = 0;
	unsigned int temp = 0;

	ret = mcu_pmic_read(reg, &temp);
	if (ret != 0)
		return -1;
	temp = (temp & (~reg_mask)) | reg_value;

	ret = mcu_pmic_write(reg, temp);
	if (ret != 0)
		return -1;

	pr_debug("Write REG[ %d ] = 0x%x\n", reg, reg_value);

	return ret;
}

/*!
 * make max8660 - mc9s08dz60 enter low-power mode
 */
static void pmic_power_off(void)
{
	mcu_pmic_write_reg(REG_MCU_POWER_CTL, 0x10, 0x10);
}

static int __init mcu_pmic_init(void)
{
	int err;

	/* init chips */
	err = max8660_init();
	if (err)
		goto fail1;

	err = mc9s08dz60_init();
	if (err)
		goto fail1;

	if (is_max8660_present()) {
		pr_info("max8660 is present \n");
		pm_power_off = pmic_power_off;
	} else
		pr_debug("max8660 is not present\n");
	pr_info("mcu_pmic_init completed!\n");
	return 0;

fail1:
	pr_err("mcu_pmic_init failed!\n");
	return err;
}

static void __exit mcu_pmic_exit(void)
{
	reg_max8660_remove();
	mc9s08dz60_exit();
	max8660_exit();
}

subsys_initcall_sync(mcu_pmic_init);
module_exit(mcu_pmic_exit);

MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("mcu pmic driver");
MODULE_LICENSE("GPL");