aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-11-19 22:14:49 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-11-21 10:07:53 -0500
commit759f2598ef3876637e40d99a4ceb7a3d83a4d8d3 (patch)
tree62fa9fd103c1c305214b7aea168f6352aa1a61bb /drivers/mfd
parentb9c79323166530a14c1fa8c10337eeaa54e3f98d (diff)
mfd: tps65090: Use regmap irq framework for interrupt support
Use the regmap irq framework for implementing TPS65090 interrupt support in place of implementing it locally. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/tps65090.c263
1 files changed, 98 insertions, 165 deletions
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index 355a07749454..2eaae52cb5b8 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -38,35 +38,21 @@
38#define TPS65090_INT_MSK 0x2 38#define TPS65090_INT_MSK 0x2
39#define TPS65090_INT_MSK2 0x3 39#define TPS65090_INT_MSK2 0x3
40 40
41struct tps65090_irq_data { 41#define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1
42 u8 mask_reg; 42#define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2
43 u8 mask_pos; 43#define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3
44}; 44#define TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE 4
45 45#define TPS65090_INT1_MASK_CHARGING_COMPLETE 5
46#define TPS65090_IRQ(_reg, _mask_pos) \ 46#define TPS65090_INT1_MASK_OVERLOAD_DCDC1 6
47 { \ 47#define TPS65090_INT1_MASK_OVERLOAD_DCDC2 7
48 .mask_reg = (_reg), \ 48#define TPS65090_INT2_MASK_OVERLOAD_DCDC3 0
49 .mask_pos = (_mask_pos), \ 49#define TPS65090_INT2_MASK_OVERLOAD_FET1 1
50 } 50#define TPS65090_INT2_MASK_OVERLOAD_FET2 2
51 51#define TPS65090_INT2_MASK_OVERLOAD_FET3 3
52static const struct tps65090_irq_data tps65090_irqs[] = { 52#define TPS65090_INT2_MASK_OVERLOAD_FET4 4
53 [0] = TPS65090_IRQ(0, 0), 53#define TPS65090_INT2_MASK_OVERLOAD_FET5 5
54 [1] = TPS65090_IRQ(0, 1), 54#define TPS65090_INT2_MASK_OVERLOAD_FET6 6
55 [2] = TPS65090_IRQ(0, 2), 55#define TPS65090_INT2_MASK_OVERLOAD_FET7 7
56 [3] = TPS65090_IRQ(0, 3),
57 [4] = TPS65090_IRQ(0, 4),
58 [5] = TPS65090_IRQ(0, 5),
59 [6] = TPS65090_IRQ(0, 6),
60 [7] = TPS65090_IRQ(0, 7),
61 [8] = TPS65090_IRQ(1, 0),
62 [9] = TPS65090_IRQ(1, 1),
63 [10] = TPS65090_IRQ(1, 2),
64 [11] = TPS65090_IRQ(1, 3),
65 [12] = TPS65090_IRQ(1, 4),
66 [13] = TPS65090_IRQ(1, 5),
67 [14] = TPS65090_IRQ(1, 6),
68 [15] = TPS65090_IRQ(1, 7),
69};
70 56
71static struct mfd_cell tps65090s[] = { 57static struct mfd_cell tps65090s[] = {
72 { 58 {
@@ -77,132 +63,77 @@ static struct mfd_cell tps65090s[] = {
77 }, 63 },
78}; 64};
79 65
80static void tps65090_irq_lock(struct irq_data *data) 66static const struct regmap_irq tps65090_irqs[] = {
81{ 67 /* INT1 IRQs*/
82 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data); 68 [TPS65090_IRQ_VAC_STATUS_CHANGE] = {
83 69 .mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE,
84 mutex_lock(&tps65090->irq_lock); 70 },
85} 71 [TPS65090_IRQ_VSYS_STATUS_CHANGE] = {
86 72 .mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE,
87static void tps65090_irq_mask(struct irq_data *irq_data) 73 },
88{ 74 [TPS65090_IRQ_BAT_STATUS_CHANGE] = {
89 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); 75 .mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE,
90 unsigned int __irq = irq_data->hwirq; 76 },
91 const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; 77 [TPS65090_IRQ_CHARGING_STATUS_CHANGE] = {
92 78 .mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE,
93 tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg), 79 },
94 data->mask_pos); 80 [TPS65090_IRQ_CHARGING_COMPLETE] = {
95} 81 .mask = TPS65090_INT1_MASK_CHARGING_COMPLETE,
96 82 },
97static void tps65090_irq_unmask(struct irq_data *irq_data) 83 [TPS65090_IRQ_OVERLOAD_DCDC1] = {
98{ 84 .mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1,
99 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); 85 },
100 unsigned int __irq = irq_data->irq - tps65090->irq_base; 86 [TPS65090_IRQ_OVERLOAD_DCDC2] = {
101 const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; 87 .mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2,
102 88 },
103 tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg), 89 /* INT2 IRQs*/
104 data->mask_pos); 90 [TPS65090_IRQ_OVERLOAD_DCDC3] = {
105} 91 .reg_offset = 1,
106 92 .mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3,
107static void tps65090_irq_sync_unlock(struct irq_data *data) 93 },
108{ 94 [TPS65090_IRQ_OVERLOAD_FET1] = {
109 struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data); 95 .reg_offset = 1,
110 96 .mask = TPS65090_INT2_MASK_OVERLOAD_FET1,
111 mutex_unlock(&tps65090->irq_lock); 97 },
112} 98 [TPS65090_IRQ_OVERLOAD_FET2] = {
113 99 .reg_offset = 1,
114static irqreturn_t tps65090_irq(int irq, void *data) 100 .mask = TPS65090_INT2_MASK_OVERLOAD_FET2,
115{ 101 },
116 struct tps65090 *tps65090 = data; 102 [TPS65090_IRQ_OVERLOAD_FET3] = {
117 int ret = 0; 103 .reg_offset = 1,
118 u8 status, mask; 104 .mask = TPS65090_INT2_MASK_OVERLOAD_FET3,
119 unsigned long int acks = 0; 105 },
120 int i; 106 [TPS65090_IRQ_OVERLOAD_FET4] = {
121 107 .reg_offset = 1,
122 for (i = 0; i < NUM_INT_REG; i++) { 108 .mask = TPS65090_INT2_MASK_OVERLOAD_FET4,
123 ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask); 109 },
124 if (ret < 0) { 110 [TPS65090_IRQ_OVERLOAD_FET5] = {
125 dev_err(tps65090->dev, 111 .reg_offset = 1,
126 "failed to read mask reg [addr:%d]\n", 112 .mask = TPS65090_INT2_MASK_OVERLOAD_FET5,
127 TPS65090_INT_MSK + i); 113 },
128 return IRQ_NONE; 114 [TPS65090_IRQ_OVERLOAD_FET6] = {
129 } 115 .reg_offset = 1,
130 ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i, 116 .mask = TPS65090_INT2_MASK_OVERLOAD_FET6,
131 &status); 117 },
132 if (ret < 0) { 118 [TPS65090_IRQ_OVERLOAD_FET7] = {
133 dev_err(tps65090->dev, 119 .reg_offset = 1,
134 "failed to read status reg [addr:%d]\n", 120 .mask = TPS65090_INT2_MASK_OVERLOAD_FET7,
135 TPS65090_INT_STS + i); 121 },
136 return IRQ_NONE; 122};
137 }
138 if (status) {
139 /* Ack only those interrupts which are not masked */
140 status &= (~mask);
141 ret = tps65090_write(tps65090->dev,
142 TPS65090_INT_STS + i, status);
143 if (ret < 0) {
144 dev_err(tps65090->dev,
145 "failed to write interrupt status\n");
146 return IRQ_NONE;
147 }
148 acks |= (status << (i * 8));
149 }
150 }
151
152 for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs))
153 handle_nested_irq(tps65090->irq_base + i);
154 return acks ? IRQ_HANDLED : IRQ_NONE;
155}
156
157static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
158 int irq_base)
159{
160 int i, ret;
161
162 if (!irq_base) {
163 dev_err(tps65090->dev, "IRQ base not set\n");
164 return -EINVAL;
165 }
166
167 mutex_init(&tps65090->irq_lock);
168
169 for (i = 0; i < NUM_INT_REG; i++)
170 tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF);
171
172 for (i = 0; i < NUM_INT_REG; i++)
173 tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff);
174
175 tps65090->irq_base = irq_base;
176 tps65090->irq_chip.name = "tps65090";
177 tps65090->irq_chip.irq_mask = tps65090_irq_mask;
178 tps65090->irq_chip.irq_unmask = tps65090_irq_unmask;
179 tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock;
180 tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock;
181
182 for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
183 int __irq = i + tps65090->irq_base;
184 irq_set_chip_data(__irq, tps65090);
185 irq_set_chip_and_handler(__irq, &tps65090->irq_chip,
186 handle_simple_irq);
187 irq_set_nested_thread(__irq, 1);
188#ifdef CONFIG_ARM
189 set_irq_flags(__irq, IRQF_VALID);
190#endif
191 }
192
193 ret = request_threaded_irq(irq, NULL, tps65090_irq, IRQF_ONESHOT,
194 "tps65090", tps65090);
195 if (!ret) {
196 device_init_wakeup(tps65090->dev, 1);
197 enable_irq_wake(irq);
198 }
199 123
200 return ret; 124static struct regmap_irq_chip tps65090_irq_chip = {
201} 125 .name = "tps65090",
126 .irqs = tps65090_irqs,
127 .num_irqs = ARRAY_SIZE(tps65090_irqs),
128 .num_regs = NUM_INT_REG,
129 .status_base = TPS65090_INT_STS,
130 .mask_base = TPS65090_INT_MSK,
131 .mask_invert = true,
132};
202 133
203static bool is_volatile_reg(struct device *dev, unsigned int reg) 134static bool is_volatile_reg(struct device *dev, unsigned int reg)
204{ 135{
205 if (reg == TPS65090_INT_STS) 136 if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS2))
206 return true; 137 return true;
207 else 138 else
208 return false; 139 return false;
@@ -238,24 +169,27 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
238 tps65090->dev = &client->dev; 169 tps65090->dev = &client->dev;
239 i2c_set_clientdata(client, tps65090); 170 i2c_set_clientdata(client, tps65090);
240 171
241 if (client->irq) {
242 ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base);
243 if (ret) {
244 dev_err(&client->dev, "IRQ init failed with err: %d\n",
245 ret);
246 goto err_exit;
247 }
248 }
249
250 tps65090->rmap = devm_regmap_init_i2c(client, &tps65090_regmap_config); 172 tps65090->rmap = devm_regmap_init_i2c(client, &tps65090_regmap_config);
251 if (IS_ERR(tps65090->rmap)) { 173 if (IS_ERR(tps65090->rmap)) {
252 ret = PTR_ERR(tps65090->rmap); 174 ret = PTR_ERR(tps65090->rmap);
253 dev_err(&client->dev, "regmap_init failed with err: %d\n", ret); 175 dev_err(&client->dev, "regmap_init failed with err: %d\n", ret);
254 goto err_irq_exit; 176 return ret;
177 }
178
179 if (client->irq) {
180 ret = regmap_add_irq_chip(tps65090->rmap, client->irq,
181 IRQF_ONESHOT | IRQF_TRIGGER_LOW, pdata->irq_base,
182 &tps65090_irq_chip, &tps65090->irq_data);
183 if (ret) {
184 dev_err(&client->dev,
185 "IRQ init failed with err: %d\n", ret);
186 return ret;
187 }
255 } 188 }
256 189
257 ret = mfd_add_devices(tps65090->dev, -1, tps65090s, 190 ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
258 ARRAY_SIZE(tps65090s), NULL, 0, NULL); 191 ARRAY_SIZE(tps65090s), NULL,
192 regmap_irq_chip_get_base(tps65090->irq_data), NULL);
259 if (ret) { 193 if (ret) {
260 dev_err(&client->dev, "add mfd devices failed with err: %d\n", 194 dev_err(&client->dev, "add mfd devices failed with err: %d\n",
261 ret); 195 ret);
@@ -266,8 +200,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
266 200
267err_irq_exit: 201err_irq_exit:
268 if (client->irq) 202 if (client->irq)
269 free_irq(client->irq, tps65090); 203 regmap_del_irq_chip(client->irq, tps65090->irq_data);
270err_exit:
271 return ret; 204 return ret;
272} 205}
273 206
@@ -277,7 +210,7 @@ static int __devexit tps65090_i2c_remove(struct i2c_client *client)
277 210
278 mfd_remove_devices(tps65090->dev); 211 mfd_remove_devices(tps65090->dev);
279 if (client->irq) 212 if (client->irq)
280 free_irq(client->irq, tps65090); 213 regmap_del_irq_chip(client->irq, tps65090->irq_data);
281 214
282 return 0; 215 return 0;
283} 216}