Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm8994-irq.c
Go to the documentation of this file.
1 /*
2  * wm8994-irq.c -- Interrupt controller support for Wolfson WM8994
3  *
4  * Copyright 2010 Wolfson Microelectronics PLC.
5  *
6  * Author: Mark Brown <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  *
13  */
14 
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/i2c.h>
18 #include <linux/irq.h>
19 #include <linux/mfd/core.h>
20 #include <linux/interrupt.h>
21 #include <linux/regmap.h>
22 
23 #include <linux/mfd/wm8994/core.h>
24 #include <linux/mfd/wm8994/pdata.h>
26 
27 #include <linux/delay.h>
28 
29 static struct regmap_irq wm8994_irqs[] = {
31  .reg_offset = 1,
32  .mask = WM8994_TEMP_SHUT_EINT,
33  },
35  .reg_offset = 1,
36  .mask = WM8994_MIC1_DET_EINT,
37  },
39  .reg_offset = 1,
40  .mask = WM8994_MIC1_SHRT_EINT,
41  },
43  .reg_offset = 1,
44  .mask = WM8994_MIC2_DET_EINT,
45  },
47  .reg_offset = 1,
48  .mask = WM8994_MIC2_SHRT_EINT,
49  },
51  .reg_offset = 1,
52  .mask = WM8994_FLL1_LOCK_EINT,
53  },
55  .reg_offset = 1,
56  .mask = WM8994_FLL2_LOCK_EINT,
57  },
59  .reg_offset = 1,
60  .mask = WM8994_SRC1_LOCK_EINT,
61  },
63  .reg_offset = 1,
64  .mask = WM8994_SRC2_LOCK_EINT,
65  },
67  .reg_offset = 1,
69  },
71  .reg_offset = 1,
73  },
75  .reg_offset = 1,
77  },
79  .reg_offset = 1,
80  .mask = WM8994_FIFOS_ERR_EINT,
81  },
83  .reg_offset = 1,
84  .mask = WM8994_WSEQ_DONE_EINT,
85  },
87  .reg_offset = 1,
88  .mask = WM8994_DCS_DONE_EINT,
89  },
91  .reg_offset = 1,
92  .mask = WM8994_TEMP_WARN_EINT,
93  },
94  [WM8994_IRQ_GPIO(1)] = {
95  .mask = WM8994_GP1_EINT,
96  },
97  [WM8994_IRQ_GPIO(2)] = {
98  .mask = WM8994_GP2_EINT,
99  },
100  [WM8994_IRQ_GPIO(3)] = {
101  .mask = WM8994_GP3_EINT,
102  },
103  [WM8994_IRQ_GPIO(4)] = {
104  .mask = WM8994_GP4_EINT,
105  },
106  [WM8994_IRQ_GPIO(5)] = {
107  .mask = WM8994_GP5_EINT,
108  },
109  [WM8994_IRQ_GPIO(6)] = {
110  .mask = WM8994_GP6_EINT,
111  },
112  [WM8994_IRQ_GPIO(7)] = {
113  .mask = WM8994_GP7_EINT,
114  },
115  [WM8994_IRQ_GPIO(8)] = {
116  .mask = WM8994_GP8_EINT,
117  },
118  [WM8994_IRQ_GPIO(9)] = {
119  .mask = WM8994_GP8_EINT,
120  },
121  [WM8994_IRQ_GPIO(10)] = {
122  .mask = WM8994_GP10_EINT,
123  },
124  [WM8994_IRQ_GPIO(11)] = {
125  .mask = WM8994_GP11_EINT,
126  },
127 };
128 
129 static struct regmap_irq_chip wm8994_irq_chip = {
130  .name = "wm8994",
131  .irqs = wm8994_irqs,
132  .num_irqs = ARRAY_SIZE(wm8994_irqs),
133 
134  .num_regs = 2,
135  .status_base = WM8994_INTERRUPT_STATUS_1,
136  .mask_base = WM8994_INTERRUPT_STATUS_1_MASK,
137  .ack_base = WM8994_INTERRUPT_STATUS_1,
138  .runtime_pm = true,
139 };
140 
142 {
143  int ret;
144  unsigned long irqflags;
145  struct wm8994_pdata *pdata = wm8994->dev->platform_data;
146 
147  if (!wm8994->irq) {
148  dev_warn(wm8994->dev,
149  "No interrupt specified, no interrupts\n");
150  wm8994->irq_base = 0;
151  return 0;
152  }
153 
154  /* select user or default irq flags */
155  irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
156  if (pdata->irq_flags)
157  irqflags = pdata->irq_flags;
158 
159  ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
160  irqflags,
161  wm8994->irq_base, &wm8994_irq_chip,
162  &wm8994->irq_data);
163  if (ret != 0) {
164  dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret);
165  return ret;
166  }
167 
168  /* Enable top level interrupt if it was masked */
170 
171  return 0;
172 }
173 
175 {
176  regmap_del_irq_chip(wm8994->irq, wm8994->irq_data);
177 }