Merge tag 'drm-misc-next-fixes-2021-05-06' of git://anongit.freedesktop.org/drm/drm...
[linux-2.6-microblaze.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/module.h>
7 #include <linux/of.h>
8 #include <linux/of_device.h>
9 #include <linux/of_irq.h>
10 #include <linux/platform_device.h>
11 #include <linux/regmap.h>
12 #include <linux/suspend.h>
13 #include <linux/mfd/mt6323/core.h>
14 #include <linux/mfd/mt6323/registers.h>
15 #include <linux/mfd/mt6397/core.h>
16 #include <linux/mfd/mt6397/registers.h>
17
18 static void mt6397_irq_lock(struct irq_data *data)
19 {
20         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
21
22         mutex_lock(&mt6397->irqlock);
23 }
24
25 static void mt6397_irq_sync_unlock(struct irq_data *data)
26 {
27         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
28
29         regmap_write(mt6397->regmap, mt6397->int_con[0],
30                      mt6397->irq_masks_cur[0]);
31         regmap_write(mt6397->regmap, mt6397->int_con[1],
32                      mt6397->irq_masks_cur[1]);
33
34         mutex_unlock(&mt6397->irqlock);
35 }
36
37 static void mt6397_irq_disable(struct irq_data *data)
38 {
39         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
40         int shift = data->hwirq & 0xf;
41         int reg = data->hwirq >> 4;
42
43         mt6397->irq_masks_cur[reg] &= ~BIT(shift);
44 }
45
46 static void mt6397_irq_enable(struct irq_data *data)
47 {
48         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
49         int shift = data->hwirq & 0xf;
50         int reg = data->hwirq >> 4;
51
52         mt6397->irq_masks_cur[reg] |= BIT(shift);
53 }
54
55 #ifdef CONFIG_PM_SLEEP
56 static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
57 {
58         struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
59         int shift = irq_data->hwirq & 0xf;
60         int reg = irq_data->hwirq >> 4;
61
62         if (on)
63                 mt6397->wake_mask[reg] |= BIT(shift);
64         else
65                 mt6397->wake_mask[reg] &= ~BIT(shift);
66
67         return 0;
68 }
69 #else
70 #define mt6397_irq_set_wake NULL
71 #endif
72
73 static struct irq_chip mt6397_irq_chip = {
74         .name = "mt6397-irq",
75         .irq_bus_lock = mt6397_irq_lock,
76         .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
77         .irq_enable = mt6397_irq_enable,
78         .irq_disable = mt6397_irq_disable,
79         .irq_set_wake = mt6397_irq_set_wake,
80 };
81
82 static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
83                                   int irqbase)
84 {
85         unsigned int status = 0;
86         int i, irq, ret;
87
88         ret = regmap_read(mt6397->regmap, reg, &status);
89         if (ret) {
90                 dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
91                 return;
92         }
93
94         for (i = 0; i < 16; i++) {
95                 if (status & BIT(i)) {
96                         irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
97                         if (irq)
98                                 handle_nested_irq(irq);
99                 }
100         }
101
102         regmap_write(mt6397->regmap, reg, status);
103 }
104
105 static irqreturn_t mt6397_irq_thread(int irq, void *data)
106 {
107         struct mt6397_chip *mt6397 = data;
108
109         mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
110         mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
111
112         return IRQ_HANDLED;
113 }
114
115 static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
116                                  irq_hw_number_t hw)
117 {
118         struct mt6397_chip *mt6397 = d->host_data;
119
120         irq_set_chip_data(irq, mt6397);
121         irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
122         irq_set_nested_thread(irq, 1);
123         irq_set_noprobe(irq);
124
125         return 0;
126 }
127
128 static const struct irq_domain_ops mt6397_irq_domain_ops = {
129         .map = mt6397_irq_domain_map,
130 };
131
132 static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
133                                   unsigned long pm_event, void *unused)
134 {
135         struct mt6397_chip *chip =
136                 container_of(notifier, struct mt6397_chip, pm_nb);
137
138         switch (pm_event) {
139         case PM_SUSPEND_PREPARE:
140                 regmap_write(chip->regmap,
141                              chip->int_con[0], chip->wake_mask[0]);
142                 regmap_write(chip->regmap,
143                              chip->int_con[1], chip->wake_mask[1]);
144                 enable_irq_wake(chip->irq);
145                 break;
146
147         case PM_POST_SUSPEND:
148                 regmap_write(chip->regmap,
149                              chip->int_con[0], chip->irq_masks_cur[0]);
150                 regmap_write(chip->regmap,
151                              chip->int_con[1], chip->irq_masks_cur[1]);
152                 disable_irq_wake(chip->irq);
153                 break;
154
155         default:
156                 break;
157         }
158
159         return NOTIFY_DONE;
160 }
161
162 int mt6397_irq_init(struct mt6397_chip *chip)
163 {
164         int ret;
165
166         mutex_init(&chip->irqlock);
167
168         switch (chip->chip_id) {
169         case MT6323_CHIP_ID:
170                 chip->int_con[0] = MT6323_INT_CON0;
171                 chip->int_con[1] = MT6323_INT_CON1;
172                 chip->int_status[0] = MT6323_INT_STATUS0;
173                 chip->int_status[1] = MT6323_INT_STATUS1;
174                 break;
175
176         case MT6391_CHIP_ID:
177         case MT6397_CHIP_ID:
178                 chip->int_con[0] = MT6397_INT_CON0;
179                 chip->int_con[1] = MT6397_INT_CON1;
180                 chip->int_status[0] = MT6397_INT_STATUS0;
181                 chip->int_status[1] = MT6397_INT_STATUS1;
182                 break;
183
184         default:
185                 dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
186                 return -ENODEV;
187         }
188
189         /* Mask all interrupt sources */
190         regmap_write(chip->regmap, chip->int_con[0], 0x0);
191         regmap_write(chip->regmap, chip->int_con[1], 0x0);
192
193         chip->pm_nb.notifier_call = mt6397_irq_pm_notifier;
194         chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
195                                                  MT6397_IRQ_NR,
196                                                  &mt6397_irq_domain_ops,
197                                                  chip);
198         if (!chip->irq_domain) {
199                 dev_err(chip->dev, "could not create irq domain\n");
200                 return -ENOMEM;
201         }
202
203         ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
204                                         mt6397_irq_thread, IRQF_ONESHOT,
205                                         "mt6397-pmic", chip);
206         if (ret) {
207                 dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
208                         chip->irq, ret);
209                 return ret;
210         }
211
212         register_pm_notifier(&chip->pm_nb);
213         return 0;
214 }