blob: 201fab79d7f39ce49c1e01c210dc607112fec5e0 [file] [log] [blame]
Jay Chokshi9e3cbf72012-05-25 13:00:28 -07001/*
Duy Truong790f06d2013-02-13 16:38:12 -08002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jay Chokshi9e3cbf72012-05-25 13:00:28 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
Steve Muckle75c34ca2012-06-12 14:27:40 -070016#include <linux/export.h>
Jay Chokshi9e3cbf72012-05-25 13:00:28 -070017#include <linux/err.h>
18#include <linux/interrupt.h>
19#include <linux/irq.h>
20#include <linux/kernel.h>
21#include <linux/mfd/pm8xxx/core.h>
22#include <linux/mfd/pm8xxx/pm8821-irq.h>
23#include <linux/platform_device.h>
24#include <linux/slab.h>
Chandra Ramachandran931d70f2012-07-20 15:01:03 -070025#include <mach/mpm.h>
Jay Chokshi9e3cbf72012-05-25 13:00:28 -070026
27#define PM8821_TOTAL_IRQ_MASTERS 2
28#define PM8821_BLOCKS_PER_MASTER 7
29#define PM8821_IRQ_MASTER1_SET 0x01
30#define PM8821_IRQ_CLEAR_OFFSET 0x01
31#define PM8821_IRQ_RT_STATUS_OFFSET 0x0F
32#define PM8821_IRQ_MASK_REG_OFFSET 0x08
33#define SSBI_REG_ADDR_IRQ_MASTER0 0x30
34#define SSBI_REG_ADDR_IRQ_MASTER1 0xB0
Chandra Ramachandran931d70f2012-07-20 15:01:03 -070035#define MPM_PIN_FOR_8821_IRQ 7
Jay Chokshi9e3cbf72012-05-25 13:00:28 -070036#define SSBI_REG_ADDR_IRQ_IT_STATUS(master_base, block) (master_base + block)
37
38/*
39 * Block 0 does not exist in PM8821 IRQ SSBI address space,
40 * IRQ0 is assigned to bit0 of block1.
41 */
42#define SSBI_REG_ADDR_IRQ_IT_CLEAR(master_base, block) \
43 (master_base + PM8821_IRQ_CLEAR_OFFSET + block)
44
45#define SSBI_REG_ADDR_IRQ_RT_STATUS(master_base, block) \
46 (master_base + PM8821_IRQ_RT_STATUS_OFFSET + block)
47
48#define SSBI_REG_ADDR_IRQ_MASK(master_base, block) \
49 (master_base + PM8821_IRQ_MASK_REG_OFFSET + block)
50
51struct pm_irq_chip {
52 struct device *dev;
53 spinlock_t pm_irq_lock;
54 unsigned int base_addr;
55 unsigned int devirq;
56 unsigned int irq_base;
57 unsigned int num_irqs;
58 int masters[PM8821_TOTAL_IRQ_MASTERS];
59};
60
61static int pm8821_irq_masked_write(struct pm_irq_chip *chip, u16 addr,
62 u8 mask, u8 val)
63{
64 int rc;
65 u8 reg;
66
67 rc = pm8xxx_readb(chip->dev, addr, &reg);
68 if (rc) {
69 pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
70 return rc;
71 }
72
73 reg &= ~mask;
74 reg |= val & mask;
75
76 rc = pm8xxx_writeb(chip->dev, addr, reg);
77 if (rc) {
78 pr_err("write failed addr = %03X, rc = %d\n", addr, rc);
79 return rc;
80 }
81
82 return 0;
83}
84
85static int pm8821_read_master_irq(const struct pm_irq_chip *chip,
86 int m, u8 *master)
87{
88 return pm8xxx_readb(chip->dev, chip->masters[m], master);
89}
90
91static int pm8821_read_block_irq(struct pm_irq_chip *chip, int master,
92 u8 block, u8 *bits)
93{
94 int rc;
95
96 spin_lock(&chip->pm_irq_lock);
97
98 rc = pm8xxx_readb(chip->dev,
99 SSBI_REG_ADDR_IRQ_IT_STATUS(chip->masters[master], block), bits);
100 if (rc)
101 pr_err("Failed Reading Status rc=%d\n", rc);
102
103 spin_unlock(&chip->pm_irq_lock);
104 return rc;
105}
106
107
108static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
109 int master_number, int block)
110{
111 int pmirq, irq, i, ret;
112 u8 bits;
113
114 ret = pm8821_read_block_irq(chip, master_number, block, &bits);
115 if (ret) {
116 pr_err("Failed reading %d block ret=%d", block, ret);
117 return ret;
118 }
119 if (!bits) {
120 pr_err("block bit set in master but no irqs: %d", block);
121 return 0;
122 }
123
124 /* Convert block offset to global block number */
125 block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
126
127 /* Check IRQ bits */
128 for (i = 0; i < 8; i++) {
129 if (bits & BIT(i)) {
130 pmirq = (block << 3) + i;
131 irq = pmirq + chip->irq_base;
132 generic_handle_irq(irq);
133 }
134 }
135 return 0;
136}
137
138static int pm8821_irq_read_master(struct pm_irq_chip *chip,
139 int master_number, u8 master_val)
140{
141 int ret = 0;
142 int block;
143
144 for (block = 1; block < 8; block++) {
145 if (master_val & BIT(block)) {
146 ret |= pm8821_irq_block_handler(chip,
147 master_number, block);
148 }
149 }
150
151 return ret;
152}
153
154static irqreturn_t pm8821_irq_handler(int irq, void *data)
155{
156 struct pm_irq_chip *chip = data;
157 int ret;
158 u8 master;
159
160 ret = pm8821_read_master_irq(chip, 0, &master);
161 if (ret) {
162 pr_err("Failed to read master 0 ret=%d\n", ret);
163 return ret;
164 }
165
166 if (master & ~PM8821_IRQ_MASTER1_SET)
167 pm8821_irq_read_master(chip, 0, master);
168
169 if (!(master & PM8821_IRQ_MASTER1_SET))
170 goto done;
171
172 ret = pm8821_read_master_irq(chip, 1, &master);
173 if (ret) {
174 pr_err("Failed to read master 1 ret=%d\n", ret);
175 return ret;
176 }
177
178 pm8821_irq_read_master(chip, 1, master);
179
180done:
181 return IRQ_HANDLED;
182}
183
184static void pm8821_irq_mask(struct irq_data *d)
185{
186 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
187 unsigned int pmirq = d->irq - chip->irq_base;
188 int irq_bit, rc;
189 u8 block, master;
190
191 block = pmirq >> 3;
192 master = block / PM8821_BLOCKS_PER_MASTER;
193 irq_bit = pmirq % 8;
194 block %= PM8821_BLOCKS_PER_MASTER;
195
196 spin_lock(&chip->pm_irq_lock);
197
198 rc = pm8821_irq_masked_write(chip,
199 SSBI_REG_ADDR_IRQ_MASK(chip->masters[master], block),
200 BIT(irq_bit), BIT(irq_bit));
201
202 if (rc)
203 pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
204
205 spin_unlock(&chip->pm_irq_lock);
206}
207
208static void pm8821_irq_mask_ack(struct irq_data *d)
209{
210 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
211 unsigned int pmirq = d->irq - chip->irq_base;
212 int irq_bit, rc;
213 u8 block, master;
214
215 block = pmirq >> 3;
216 master = block / PM8821_BLOCKS_PER_MASTER;
217 irq_bit = pmirq % 8;
218 block %= PM8821_BLOCKS_PER_MASTER;
219
220 spin_lock(&chip->pm_irq_lock);
221
222 rc = pm8821_irq_masked_write(chip,
223 SSBI_REG_ADDR_IRQ_MASK(chip->masters[master], block),
224 BIT(irq_bit), BIT(irq_bit));
225
226 if (rc) {
227 pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
228 goto fail;
229 }
230
231 rc = pm8821_irq_masked_write(chip,
232 SSBI_REG_ADDR_IRQ_IT_CLEAR(chip->masters[master], block),
233 BIT(irq_bit), BIT(irq_bit));
234
235 if (rc) {
236 pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
237 pmirq, rc);
238 }
239
240fail:
241 spin_unlock(&chip->pm_irq_lock);
242}
243
244static void pm8821_irq_unmask(struct irq_data *d)
245{
246 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
247 unsigned int pmirq = d->irq - chip->irq_base;
248 int irq_bit, rc;
249 u8 block, master;
250
251 block = pmirq >> 3;
252 master = block / PM8821_BLOCKS_PER_MASTER;
253 irq_bit = pmirq % 8;
254 block %= PM8821_BLOCKS_PER_MASTER;
255
256 spin_lock(&chip->pm_irq_lock);
257
258 rc = pm8821_irq_masked_write(chip,
259 SSBI_REG_ADDR_IRQ_MASK(chip->masters[master], block),
260 BIT(irq_bit), ~BIT(irq_bit));
261
262 if (rc)
263 pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
264
265 spin_unlock(&chip->pm_irq_lock);
266}
267
268static int pm8821_irq_set_type(struct irq_data *d, unsigned int flow_type)
269{
270 /*
271 * PM8821 IRQ controller does not have explicit software support for
272 * IRQ flow type.
273 */
274 return 0;
275}
276
277static int pm8821_irq_set_wake(struct irq_data *d, unsigned int on)
278{
279 return 0;
280}
281
282static int pm8821_irq_read_line(struct irq_data *d)
283{
284 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
285
286 return pm8821_get_irq_stat(chip, d->irq);
287}
288
289static struct irq_chip pm_irq_chip = {
290 .name = "pm8821-irq",
291 .irq_mask = pm8821_irq_mask,
292 .irq_mask_ack = pm8821_irq_mask_ack,
293 .irq_unmask = pm8821_irq_unmask,
294 .irq_set_type = pm8821_irq_set_type,
295 .irq_set_wake = pm8821_irq_set_wake,
296 .irq_read_line = pm8821_irq_read_line,
297 .flags = IRQCHIP_MASK_ON_SUSPEND,
298};
299
300/**
301 * pm8821_get_irq_stat - get the status of the irq line
302 * @chip: pointer to identify a pmic irq controller
303 * @irq: the irq number
304 *
305 * The pm8821 gpio and mpp rely on the interrupt block to read
306 * the values on their pins. This function is to facilitate reading
307 * the status of a gpio or an mpp line. The caller has to convert the
308 * gpio number to irq number.
309 *
310 * RETURNS:
311 * an int indicating the value read on that line
312 */
313int pm8821_get_irq_stat(struct pm_irq_chip *chip, int irq)
314{
315 int pmirq, rc;
316 u8 block, bits, bit, master;
317 unsigned long flags;
318
319 if (chip == NULL || irq < chip->irq_base
320 || irq >= chip->irq_base + chip->num_irqs)
321 return -EINVAL;
322
323 pmirq = irq - chip->irq_base;
324
325 block = pmirq >> 3;
326 master = block / PM8821_BLOCKS_PER_MASTER;
327 bit = pmirq % 8;
328 block %= PM8821_BLOCKS_PER_MASTER;
329
330 spin_lock_irqsave(&chip->pm_irq_lock, flags);
331
332 rc = pm8xxx_readb(chip->dev,
333 SSBI_REG_ADDR_IRQ_RT_STATUS(chip->masters[master], block),
334 &bits);
335 if (rc) {
336 pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
337 irq, pmirq, block, rc);
338 goto bail_out;
339 }
340
341 rc = (bits & BIT(bit)) ? 1 : 0;
342
343bail_out:
344 spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
345
346 return rc;
347}
348EXPORT_SYMBOL_GPL(pm8821_get_irq_stat);
349
350struct pm_irq_chip * __devinit pm8821_irq_init(struct device *dev,
351 const struct pm8xxx_irq_platform_data *pdata)
352{
353 struct pm_irq_chip *chip;
354 int devirq, rc, blocks, masters;
355 unsigned int pmirq;
356
357 if (!pdata) {
358 pr_err("No platform data\n");
359 return ERR_PTR(-EINVAL);
360 }
361
362 devirq = pdata->devirq;
363 if (devirq < 0) {
364 pr_err("missing devirq\n");
365 rc = devirq;
366 return ERR_PTR(-EINVAL);
367 }
368
369 chip = kzalloc(sizeof(struct pm_irq_chip)
370 + sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
371 if (!chip) {
372 pr_err("Cannot alloc pm_irq_chip struct\n");
373 return ERR_PTR(-EINVAL);
374 }
375
376 chip->dev = dev;
377 chip->devirq = devirq;
378 chip->irq_base = pdata->irq_base;
379 chip->num_irqs = pdata->irq_cdata.nirqs;
380 chip->base_addr = pdata->irq_cdata.base_addr;
381 blocks = DIV_ROUND_UP(pdata->irq_cdata.nirqs, 8);
382 masters = DIV_ROUND_UP(blocks, PM8821_BLOCKS_PER_MASTER);
383 chip->masters[0] = chip->base_addr + SSBI_REG_ADDR_IRQ_MASTER0;
384 chip->masters[1] = chip->base_addr + SSBI_REG_ADDR_IRQ_MASTER1;
385
386 if (masters != PM8821_TOTAL_IRQ_MASTERS) {
387 pr_err("Unequal number of masters, passed: %d, "
388 "should have been: %d\n", masters, PM8821_TOTAL_IRQ_MASTERS);
389 kfree(chip);
390 return ERR_PTR(-EINVAL);
391 }
392
393 spin_lock_init(&chip->pm_irq_lock);
394
395 for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
396 irq_set_chip_and_handler(chip->irq_base + pmirq,
397 &pm_irq_chip, handle_level_irq);
398 irq_set_chip_data(chip->irq_base + pmirq, chip);
399#ifdef CONFIG_ARM
400 set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
401#else
402 irq_set_noprobe(chip->irq_base + pmirq);
403#endif
404 }
405
406 if (devirq != 0) {
407 rc = request_irq(devirq, pm8821_irq_handler,
408 pdata->irq_trigger_flag, "pm8821_sec_irq", chip);
409 if (rc) {
410 pr_err("failed to request_irq for %d rc=%d\n",
411 devirq, rc);
412 kfree(chip);
413 return ERR_PTR(rc);
Chandra Ramachandran931d70f2012-07-20 15:01:03 -0700414 } else{
Jay Chokshi9e3cbf72012-05-25 13:00:28 -0700415 irq_set_irq_wake(devirq, 1);
Chandra Ramachandran931d70f2012-07-20 15:01:03 -0700416 msm_mpm_set_pin_wake(MPM_PIN_FOR_8821_IRQ, 1);
417 msm_mpm_set_pin_type(MPM_PIN_FOR_8821_IRQ,
418 pdata->irq_trigger_flag);
419 }
Jay Chokshi9e3cbf72012-05-25 13:00:28 -0700420 }
421
422 return chip;
423}
424
425int pm8821_irq_exit(struct pm_irq_chip *chip)
426{
427 irq_set_chained_handler(chip->devirq, NULL);
428 kfree(chip);
429 return 0;
430}