]> Git Repo - linux.git/blob - drivers/mfd/mt6397-irq.c
Linux 6.14-rc3
[linux.git] / drivers / mfd / mt6397-irq.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright (c) 2019 MediaTek Inc.
4
5 #include <linux/interrupt.h>
6 #include <linux/irq.h>
7 #include <linux/irqdomain.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
11 #include <linux/suspend.h>
12 #include <linux/mfd/mt6323/core.h>
13 #include <linux/mfd/mt6323/registers.h>
14 #include <linux/mfd/mt6328/core.h>
15 #include <linux/mfd/mt6328/registers.h>
16 #include <linux/mfd/mt6331/core.h>
17 #include <linux/mfd/mt6331/registers.h>
18 #include <linux/mfd/mt6397/core.h>
19 #include <linux/mfd/mt6397/registers.h>
20
21 static void mt6397_irq_lock(struct irq_data *data)
22 {
23         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
24
25         mutex_lock(&mt6397->irqlock);
26 }
27
28 static void mt6397_irq_sync_unlock(struct irq_data *data)
29 {
30         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
31
32         regmap_write(mt6397->regmap, mt6397->int_con[0],
33                      mt6397->irq_masks_cur[0]);
34         regmap_write(mt6397->regmap, mt6397->int_con[1],
35                      mt6397->irq_masks_cur[1]);
36         if (mt6397->int_con[2])
37                 regmap_write(mt6397->regmap, mt6397->int_con[2],
38                              mt6397->irq_masks_cur[2]);
39
40         mutex_unlock(&mt6397->irqlock);
41 }
42
43 static void mt6397_irq_disable(struct irq_data *data)
44 {
45         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
46         int shift = data->hwirq & 0xf;
47         int reg = data->hwirq >> 4;
48
49         mt6397->irq_masks_cur[reg] &= ~BIT(shift);
50 }
51
52 static void mt6397_irq_enable(struct irq_data *data)
53 {
54         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
55         int shift = data->hwirq & 0xf;
56         int reg = data->hwirq >> 4;
57
58         mt6397->irq_masks_cur[reg] |= BIT(shift);
59 }
60
61 static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
62 {
63         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
64         int shift = irq_data->hwirq & 0xf;
65         int reg = irq_data->hwirq >> 4;
66
67         if (on)
68                 mt6397->wake_mask[reg] |= BIT(shift);
69         else
70                 mt6397->wake_mask[reg] &= ~BIT(shift);
71
72         return 0;
73 }
74
75 static struct irq_chip mt6397_irq_chip = {
76         .name = "mt6397-irq",
77         .irq_bus_lock = mt6397_irq_lock,
78         .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
79         .irq_enable = mt6397_irq_enable,
80         .irq_disable = mt6397_irq_disable,
81         .irq_set_wake = pm_sleep_ptr(mt6397_irq_set_wake),
82 };
83
84 static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
85                                   int irqbase)
86 {
87         unsigned int status = 0;
88         int i, irq, ret;
89
90         ret = regmap_read(mt6397->regmap, reg, &status);
91         if (ret) {
92                 dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
93                 return;
94         }
95
96         for (i = 0; i < 16; i++) {
97                 if (status & BIT(i)) {
98                         irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
99                         if (irq)
100                                 handle_nested_irq(irq);
101                 }
102         }
103
104         regmap_write(mt6397->regmap, reg, status);
105 }
106
107 static irqreturn_t mt6397_irq_thread(int irq, void *data)
108 {
109         struct mt6397_chip *mt6397 = data;
110
111         mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
112         mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
113         if (mt6397->int_status[2])
114                 mt6397_irq_handle_reg(mt6397, mt6397->int_status[2], 32);
115
116         return IRQ_HANDLED;
117 }
118
119 static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
120                                  irq_hw_number_t hw)
121 {
122         struct mt6397_chip *mt6397 = d->host_data;
123
124         irq_set_chip_data(irq, mt6397);
125         irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
126         irq_set_nested_thread(irq, 1);
127         irq_set_noprobe(irq);
128
129         return 0;
130 }
131
132 static const struct irq_domain_ops mt6397_irq_domain_ops = {
133         .map = mt6397_irq_domain_map,
134 };
135
136 static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
137                                   unsigned long pm_event, void *unused)
138 {
139         struct mt6397_chip *chip =
140                 container_of(notifier, struct mt6397_chip, pm_nb);
141
142         switch (pm_event) {
143         case PM_SUSPEND_PREPARE:
144                 regmap_write(chip->regmap,
145                              chip->int_con[0], chip->wake_mask[0]);
146                 regmap_write(chip->regmap,
147                              chip->int_con[1], chip->wake_mask[1]);
148                 if (chip->int_con[2])
149                         regmap_write(chip->regmap,
150                                      chip->int_con[2], chip->wake_mask[2]);
151                 enable_irq_wake(chip->irq);
152                 break;
153
154         case PM_POST_SUSPEND:
155                 regmap_write(chip->regmap,
156                              chip->int_con[0], chip->irq_masks_cur[0]);
157                 regmap_write(chip->regmap,
158                              chip->int_con[1], chip->irq_masks_cur[1]);
159                 if (chip->int_con[2])
160                         regmap_write(chip->regmap,
161                                      chip->int_con[2], chip->irq_masks_cur[2]);
162                 disable_irq_wake(chip->irq);
163                 break;
164
165         default:
166                 break;
167         }
168
169         return NOTIFY_DONE;
170 }
171
172 int mt6397_irq_init(struct mt6397_chip *chip)
173 {
174         int ret;
175
176         mutex_init(&chip->irqlock);
177
178         switch (chip->chip_id) {
179         case MT6323_CHIP_ID:
180                 chip->int_con[0] = MT6323_INT_CON0;
181                 chip->int_con[1] = MT6323_INT_CON1;
182                 chip->int_status[0] = MT6323_INT_STATUS0;
183                 chip->int_status[1] = MT6323_INT_STATUS1;
184                 break;
185         case MT6328_CHIP_ID:
186                 chip->int_con[0] = MT6328_INT_CON0;
187                 chip->int_con[1] = MT6328_INT_CON1;
188                 chip->int_con[2] = MT6328_INT_CON2;
189                 chip->int_status[0] = MT6328_INT_STATUS0;
190                 chip->int_status[1] = MT6328_INT_STATUS1;
191                 chip->int_status[2] = MT6328_INT_STATUS2;
192                 break;
193         case MT6331_CHIP_ID:
194                 chip->int_con[0] = MT6331_INT_CON0;
195                 chip->int_con[1] = MT6331_INT_CON1;
196                 chip->int_status[0] = MT6331_INT_STATUS_CON0;
197                 chip->int_status[1] = MT6331_INT_STATUS_CON1;
198                 break;
199         case MT6391_CHIP_ID:
200         case MT6397_CHIP_ID:
201                 chip->int_con[0] = MT6397_INT_CON0;
202                 chip->int_con[1] = MT6397_INT_CON1;
203                 chip->int_status[0] = MT6397_INT_STATUS0;
204                 chip->int_status[1] = MT6397_INT_STATUS1;
205                 break;
206
207         default:
208                 dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
209                 return -ENODEV;
210         }
211
212         /* Mask all interrupt sources */
213         regmap_write(chip->regmap, chip->int_con[0], 0x0);
214         regmap_write(chip->regmap, chip->int_con[1], 0x0);
215         if (chip->int_con[2])
216                 regmap_write(chip->regmap, chip->int_con[2], 0x0);
217
218         chip->pm_nb.notifier_call = mt6397_irq_pm_notifier;
219         chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
220                                                  MT6397_IRQ_NR,
221                                                  &mt6397_irq_domain_ops,
222                                                  chip);
223         if (!chip->irq_domain) {
224                 dev_err(chip->dev, "could not create irq domain\n");
225                 return -ENOMEM;
226         }
227
228         ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
229                                         mt6397_irq_thread, IRQF_ONESHOT,
230                                         "mt6397-pmic", chip);
231         if (ret) {
232                 dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
233                         chip->irq, ret);
234                 return ret;
235         }
236
237         register_pm_notifier(&chip->pm_nb);
238         return 0;
239 }
This page took 0.044177 seconds and 4 git commands to generate.