aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ricoh583.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/ricoh583.c')
-rw-r--r--drivers/mfd/ricoh583.c1213
1 files changed, 1213 insertions, 0 deletions
diff --git a/drivers/mfd/ricoh583.c b/drivers/mfd/ricoh583.c
new file mode 100644
index 00000000000..a29053ebaf8
--- /dev/null
+++ b/drivers/mfd/ricoh583.c
@@ -0,0 +1,1213 @@
1/*
2 * driver/mfd/ricoh583.c
3 *
4 * Core driver implementation to access RICOH583 power management chip.
5 *
6 * Copyright (C) 2011 NVIDIA Corporation
7 *
8 * Copyright (C) 2011 RICOH COMPANY,LTD
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 *
24 */
25/*#define DEBUG 1*/
26/*#define VERBOSE_DEBUG 1*/
27#include <linux/interrupt.h>
28#include <linux/irq.h>
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/slab.h>
33#include <linux/gpio.h>
34#include <linux/i2c.h>
35#include <linux/mfd/core.h>
36#include <linux/mfd/ricoh583.h>
37
38#define RICOH_ONOFFSEL_REG 0x10
39#define RICOH_SWCTL_REG 0x5E
40
41/* Interrupt enable register */
42#define RICOH583_INT_EN_SYS1 0x19
43#define RICOH583_INT_EN_SYS2 0x1D
44#define RICOH583_INT_EN_DCDC 0x41
45#define RICOH583_INT_EN_RTC 0xED
46#define RICOH583_INT_EN_ADC1 0x90
47#define RICOH583_INT_EN_ADC2 0x91
48#define RICOH583_INT_EN_ADC3 0x92
49#define RICOH583_INT_EN_GPIO 0xA8
50
51/* interrupt status registers (monitor regs in Ricoh)*/
52#define RICOH583_INTC_INTPOL 0xAD
53#define RICOH583_INTC_INTEN 0xAE
54#define RICOH583_INTC_INTMON 0xAF
55
56#define RICOH583_INT_MON_GRP 0xAF
57#define RICOH583_INT_MON_SYS1 0x1B
58#define RICOH583_INT_MON_SYS2 0x1F
59#define RICOH583_INT_MON_DCDC 0x43
60#define RICOH583_INT_MON_RTC 0xEE
61
62/* interrupt clearing registers */
63#define RICOH583_INT_IR_SYS1 0x1A
64#define RICOH583_INT_IR_SYS2 0x1E
65#define RICOH583_INT_IR_DCDC 0x42
66#define RICOH583_INT_IR_RTC 0xEE
67#define RICOH583_INT_IR_ADCL 0x94
68#define RICOH583_INT_IR_ADCH 0x95
69#define RICOH583_INT_IR_ADCEND 0x96
70#define RICOH583_INT_IR_GPIOR 0xA9
71#define RICOH583_INT_IR_GPIOF 0xAA
72
73/* GPIO register base address */
74#define RICOH583_GPIO_IOSEL 0xA0
75#define RICOH583_GPIO_PDEN 0xA1
76#define RICOH583_GPIO_IOOUT 0xA2
77#define RICOH583_GPIO_PGSEL 0xA3
78#define RICOH583_GPIO_GPINV 0xA4
79#define RICOH583_GPIO_GPDEB 0xA5
80#define RICOH583_GPIO_GPEDGE1 0xA6
81#define RICOH583_GPIO_GPEDGE2 0xA7
82#define RICOH583_GPIO_EN_GPIR 0xA8
83#define RICOH583_GPIO_MON_IOIN 0xAB
84#define RICOH583_GPIO_GPOFUNC 0xAC
85#define RICOH583_INTC_INTEN 0xAE
86
87enum int_type {
88 SYS_INT = 0x1,
89 DCDC_INT = 0x2,
90 RTC_INT = 0x4,
91 ADC_INT = 0x8,
92 GPIO_INT = 0x10,
93};
94
95struct ricoh583_irq_data {
96 u8 int_type;
97 u8 master_bit;
98 u8 int_en_bit;
99 u8 mask_reg_index;
100 int grp_index;
101};
102
103struct deepsleep_control_data {
104 u8 reg_add;
105 u8 ds_pos_bit;
106};
107
108#define RICOH583_IRQ(_int_type, _master_bit, _grp_index, _int_bit, _mask_ind) \
109 { \
110 .int_type = _int_type, \
111 .master_bit = _master_bit, \
112 .grp_index = _grp_index, \
113 .int_en_bit = _int_bit, \
114 .mask_reg_index = _mask_ind, \
115 }
116
117static const struct ricoh583_irq_data ricoh583_irqs[] = {
118 [RICOH583_IRQ_ONKEY] = RICOH583_IRQ(SYS_INT, 0, 0, 0, 0),
119 [RICOH583_IRQ_ACOK] = RICOH583_IRQ(SYS_INT, 0, 1, 1, 0),
120 [RICOH583_IRQ_LIDOPEN] = RICOH583_IRQ(SYS_INT, 0, 2, 2, 0),
121 [RICOH583_IRQ_PREOT] = RICOH583_IRQ(SYS_INT, 0, 3, 3, 0),
122 [RICOH583_IRQ_CLKSTP] = RICOH583_IRQ(SYS_INT, 0, 4, 4, 0),
123 [RICOH583_IRQ_ONKEY_OFF] = RICOH583_IRQ(SYS_INT, 0, 5, 5, 0),
124 [RICOH583_IRQ_WD] = RICOH583_IRQ(SYS_INT, 0, 7, 7, 0),
125 [RICOH583_IRQ_EN_PWRREQ1] = RICOH583_IRQ(SYS_INT, 0, 8, 0, 1),
126 [RICOH583_IRQ_EN_PWRREQ2] = RICOH583_IRQ(SYS_INT, 0, 9, 1, 1),
127 [RICOH583_IRQ_PRE_VINDET] = RICOH583_IRQ(SYS_INT, 0, 10, 2, 1),
128
129 [RICOH583_IRQ_DC0LIM] = RICOH583_IRQ(DCDC_INT, 1, 0, 0, 2),
130 [RICOH583_IRQ_DC1LIM] = RICOH583_IRQ(DCDC_INT, 1, 1, 1, 2),
131 [RICOH583_IRQ_DC2LIM] = RICOH583_IRQ(DCDC_INT, 1, 2, 2, 2),
132 [RICOH583_IRQ_DC3LIM] = RICOH583_IRQ(DCDC_INT, 1, 3, 3, 2),
133
134 [RICOH583_IRQ_CTC] = RICOH583_IRQ(RTC_INT, 2, 0, 0, 3),
135 [RICOH583_IRQ_YALE] = RICOH583_IRQ(RTC_INT, 2, 5, 5, 3),
136 [RICOH583_IRQ_DALE] = RICOH583_IRQ(RTC_INT, 2, 6, 6, 3),
137 [RICOH583_IRQ_WALE] = RICOH583_IRQ(RTC_INT, 2, 7, 7, 3),
138
139 [RICOH583_IRQ_AIN1L] = RICOH583_IRQ(ADC_INT, 3, 0, 0, 4),
140 [RICOH583_IRQ_AIN2L] = RICOH583_IRQ(ADC_INT, 3, 1, 1, 4),
141 [RICOH583_IRQ_AIN3L] = RICOH583_IRQ(ADC_INT, 3, 2, 2, 4),
142 [RICOH583_IRQ_VBATL] = RICOH583_IRQ(ADC_INT, 3, 3, 3, 4),
143 [RICOH583_IRQ_VIN3L] = RICOH583_IRQ(ADC_INT, 3, 4, 4, 4),
144 [RICOH583_IRQ_VIN8L] = RICOH583_IRQ(ADC_INT, 3, 5, 5, 4),
145 [RICOH583_IRQ_AIN1H] = RICOH583_IRQ(ADC_INT, 3, 6, 0, 5),
146 [RICOH583_IRQ_AIN2H] = RICOH583_IRQ(ADC_INT, 3, 7, 1, 5),
147 [RICOH583_IRQ_AIN3H] = RICOH583_IRQ(ADC_INT, 3, 8, 2, 5),
148 [RICOH583_IRQ_VBATH] = RICOH583_IRQ(ADC_INT, 3, 9, 3, 5),
149 [RICOH583_IRQ_VIN3H] = RICOH583_IRQ(ADC_INT, 3, 10, 4, 5),
150 [RICOH583_IRQ_VIN8H] = RICOH583_IRQ(ADC_INT, 3, 11, 5, 5),
151 [RICOH583_IRQ_ADCEND] = RICOH583_IRQ(ADC_INT, 3, 12, 0, 6),
152
153 [RICOH583_IRQ_GPIO0] = RICOH583_IRQ(GPIO_INT, 4, 0, 0, 7),
154 [RICOH583_IRQ_GPIO1] = RICOH583_IRQ(GPIO_INT, 4, 1, 1, 7),
155 [RICOH583_IRQ_GPIO2] = RICOH583_IRQ(GPIO_INT, 4, 2, 2, 7),
156 [RICOH583_IRQ_GPIO3] = RICOH583_IRQ(GPIO_INT, 4, 3, 3, 7),
157 [RICOH583_IRQ_GPIO4] = RICOH583_IRQ(GPIO_INT, 4, 4, 4, 7),
158 [RICOH583_IRQ_GPIO5] = RICOH583_IRQ(GPIO_INT, 4, 5, 5, 7),
159 [RICOH583_IRQ_GPIO6] = RICOH583_IRQ(GPIO_INT, 4, 6, 6, 7),
160 [RICOH583_IRQ_GPIO7] = RICOH583_IRQ(GPIO_INT, 4, 7, 7, 7),
161 [RICOH583_NR_IRQS] = RICOH583_IRQ(GPIO_INT, 4, 8, 8, 7),
162};
163
164#define DEEPSLEEP_INIT(_id, _reg, _pos) \
165 [RICOH583_DS_##_id] = {.reg_add = _reg, .ds_pos_bit = _pos}
166
167static struct deepsleep_control_data deepsleep_data[] = {
168 DEEPSLEEP_INIT(DC1, 0x21, 4),
169 DEEPSLEEP_INIT(DC2, 0x22, 0),
170 DEEPSLEEP_INIT(DC3, 0x22, 4),
171 DEEPSLEEP_INIT(LDO0, 0x23, 0),
172 DEEPSLEEP_INIT(LDO1, 0x23, 4),
173 DEEPSLEEP_INIT(LDO2, 0x24, 0),
174 DEEPSLEEP_INIT(LDO3, 0x24, 4),
175 DEEPSLEEP_INIT(LDO4, 0x25, 0),
176 DEEPSLEEP_INIT(LDO5, 0x25, 4),
177 DEEPSLEEP_INIT(LDO6, 0x26, 0),
178 DEEPSLEEP_INIT(LDO7, 0x26, 4),
179 DEEPSLEEP_INIT(LDO8, 0x27, 0),
180 DEEPSLEEP_INIT(LDO9, 0x27, 4),
181 DEEPSLEEP_INIT(PSO0, 0x28, 0),
182 DEEPSLEEP_INIT(PSO1, 0x28, 4),
183 DEEPSLEEP_INIT(PSO2, 0x29, 0),
184 DEEPSLEEP_INIT(PSO3, 0x29, 4),
185 DEEPSLEEP_INIT(PSO4, 0x2A, 0),
186 DEEPSLEEP_INIT(PSO5, 0x2A, 4),
187 DEEPSLEEP_INIT(PSO6, 0x2B, 0),
188 DEEPSLEEP_INIT(PSO7, 0x2B, 4),
189};
190
191#define MAX_INTERRUPT_MASKS 8
192#define MAX_MAIN_INTERRUPT 5
193#define EXT_PWR_REQ \
194 (RICOH583_EXT_PWRREQ1_CONTROL | RICOH583_EXT_PWRREQ2_CONTROL)
195
196struct ricoh583 {
197 struct device *dev;
198 struct i2c_client *client;
199 struct mutex io_lock;
200 int gpio_base;
201 struct gpio_chip gpio;
202 int irq_base;
203 struct irq_chip irq_chip;
204 struct mutex irq_lock;
205 unsigned long group_irq_en[MAX_MAIN_INTERRUPT];
206
207 /* For main interrupt bits in INTC */
208 u8 intc_inten_cache;
209 u8 intc_inten_reg;
210
211 /* For group interrupt bits and address */
212 u8 irq_en_cache[MAX_INTERRUPT_MASKS];
213 u8 irq_en_reg[MAX_INTERRUPT_MASKS];
214 u8 irq_en_add[MAX_INTERRUPT_MASKS];
215
216 /* Interrupt monitor and clear register */
217 u8 irq_mon_add[MAX_INTERRUPT_MASKS + 1];
218 u8 irq_clr_add[MAX_INTERRUPT_MASKS + 1];