blob: ddc045d0cfe1b6ae6d786c6df0809542dd2a1595 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (c) 2019 MediaTek Inc.
4
5#include <linux/interrupt.h>
6#include <linux/mfd/mt6330/core.h>
7#include <linux/mfd/mt6330/registers.h>
8#include <linux/module.h>
9#include <linux/of.h>
10#include <linux/of_device.h>
11#include <linux/of_irq.h>
12#include <linux/platform_device.h>
13#include <linux/regmap.h>
14
15#undef MT6330_SPMIMST_RCSCLR
16#define MT6330_SPMIMST_STARTADDR (0x10029000)
17#define MT6330_SPMIMST_ENDADDR (0x100290FF)
18#define MT6330_REG_SPMIMST_RCSCLR (0x24)
19#define MT6330_MSK_SPMIMST_RCSCLR (0xFF)
20
21struct irq_top_t {
22 int hwirq_base;
23 unsigned int num_int_regs;
24 unsigned int en_reg;
25 unsigned int en_reg_shift;
26 unsigned int sta_reg;
27 unsigned int sta_reg_shift;
28 unsigned int top_offset;
29};
30
31struct pmic_irq_data {
32 unsigned int num_top;
33 unsigned int num_pmic_irqs;
34 unsigned int reg_width;
35 unsigned short top_int_status_reg_l;
36 unsigned short top_int_status_reg_h;
37 bool *enable_hwirq;
38 bool *cache_hwirq;
39 struct irq_top_t *pmic_ints;
40};
41
42static struct irq_top_t mt6330_ints[] = {
43 MT6330_TOP_GEN(MISC),
44 MT6330_TOP_GEN(BUCK),
45 MT6330_TOP_GEN(LDO),
46 MT6330_TOP_GEN(PSC),
47 MT6330_TOP_GEN(SCK),
48};
49
50#ifdef MT6330_SPMIMST_RCSCLR
51static inline void mt6330_clear_spmimst_rcs(struct mt6330_chip *chip)
52{
53 writel(MT6330_MSK_SPMIMST_RCSCLR,
54 (chip->spmimst_base + MT6330_REG_SPMIMST_RCSCLR));
55}
56
57static struct resource spmimst_resource = {
58 .start = MT6330_SPMIMST_STARTADDR,
59 .end = MT6330_SPMIMST_ENDADDR,
60 .flags = IORESOURCE_MEM,
61 .name = "spmimst",
62};
63#endif /* MT6362_SPMIMST_RCSCLR */
64
65static void pmic_irq_enable(struct irq_data *data)
66{
67 unsigned int hwirq = irqd_to_hwirq(data);
68 struct mt6330_chip *chip = irq_data_get_irq_chip_data(data);
69 struct pmic_irq_data *irqd = chip->irq_data;
70
71 irqd->enable_hwirq[hwirq] = true;
72}
73
74static void pmic_irq_disable(struct irq_data *data)
75{
76 unsigned int hwirq = irqd_to_hwirq(data);
77 struct mt6330_chip *chip = irq_data_get_irq_chip_data(data);
78 struct pmic_irq_data *irqd = chip->irq_data;
79
80 irqd->enable_hwirq[hwirq] = false;
81}
82
83static void pmic_irq_lock(struct irq_data *data)
84{
85 struct mt6330_chip *chip = irq_data_get_irq_chip_data(data);
86
87 mutex_lock(&chip->irqlock);
88}
89
90static void pmic_irq_sync_unlock(struct irq_data *data)
91{
92 unsigned int i, top_gp, en_reg, int_regs, shift;
93 struct mt6330_chip *chip = irq_data_get_irq_chip_data(data);
94 struct pmic_irq_data *irqd = chip->irq_data;
95
96 for (i = 0; i < irqd->num_pmic_irqs; i++) {
97 if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i])
98 continue;
99
100 top_gp = 0;
101 while ((top_gp + 1) < irqd->num_top &&
102 i >= irqd->pmic_ints[top_gp + 1].hwirq_base)
103 top_gp++;
104
105 if (top_gp >= irqd->num_top) {
106 mutex_unlock(&chip->irqlock);
107 dev_err(chip->dev,
108 "Failed to get top_group: %d\n", top_gp);
109 return;
110 }
111
112 int_regs = (i - irqd->pmic_ints[top_gp].hwirq_base) /
113 irqd->reg_width;
114 en_reg = irqd->pmic_ints[top_gp].en_reg +
115 irqd->pmic_ints[top_gp].en_reg_shift * int_regs;
116 shift = (i - irqd->pmic_ints[top_gp].hwirq_base) %
117 irqd->reg_width;
118 regmap_update_bits(chip->regmap, en_reg, BIT(shift),
119 irqd->enable_hwirq[i] << shift);
120 irqd->cache_hwirq[i] = irqd->enable_hwirq[i];
121 }
122 mutex_unlock(&chip->irqlock);
123}
124
125static struct irq_chip mt6330_irq_chip = {
126 .name = "mt6330-irq",
127 .flags = IRQCHIP_SKIP_SET_WAKE,
128 .irq_enable = pmic_irq_enable,
129 .irq_disable = pmic_irq_disable,
130 .irq_bus_lock = pmic_irq_lock,
131 .irq_bus_sync_unlock = pmic_irq_sync_unlock,
132};
133
134static void mt6330_irq_sp_handler(struct mt6330_chip *chip,
135 unsigned int top_gp)
136{
137 unsigned int sta_reg, irq_status = 0;
138 unsigned int hwirq, virq;
139 int ret, i, j;
140 struct pmic_irq_data *irqd = chip->irq_data;
141
142 for (i = 0; i < irqd->pmic_ints[top_gp].num_int_regs; i++) {
143 sta_reg = irqd->pmic_ints[top_gp].sta_reg +
144 irqd->pmic_ints[top_gp].sta_reg_shift * i;
145 ret = regmap_read(chip->regmap, sta_reg, &irq_status);
146 if (ret) {
147 dev_err(chip->dev,
148 "Failed to read irq status: %d\n", ret);
149 return;
150 }
151
152 if (!irq_status)
153 continue;
154
155 for (j = 0; j < irqd->reg_width ; j++) {
156 if ((irq_status & BIT(j)) == 0)
157 continue;
158 hwirq = irqd->pmic_ints[top_gp].hwirq_base +
159 irqd->reg_width * i + j;
160 virq = irq_find_mapping(chip->irq_domain, hwirq);
161 dev_info(chip->dev,
162 "Reg[0x%x]=0x%x,hwirq=%d,type=%d\n",
163 sta_reg, irq_status, hwirq,
164 irq_get_trigger_type(virq));
165 if (virq)
166 handle_nested_irq(virq);
167 }
168
169#ifdef MT6330_SPMIMST_RCSCLR
170 mt6330_clear_spmimst_rcs(chip);
171#endif
172 regmap_write(chip->regmap, sta_reg, irq_status);
173 }
174}
175
176extern void spmi_dump_spmimst_all_reg(void);
177static irqreturn_t mt6330_irq_handler(int irq, void *data)
178{
179 struct mt6330_chip *chip = data;
180 struct pmic_irq_data *irqd = chip->irq_data;
181 unsigned int top_irq_status_h = 0, top_irq_status = 0;
182 unsigned int i;
183 int ret;
184
185 ret = regmap_read(chip->regmap,
186 irqd->top_int_status_reg_h,
187 &top_irq_status_h);
188 if (ret) {
189 dev_err(chip->dev, "Can't read TOP_INT_STATUS0 ret=%d\n", ret);
190 return IRQ_NONE;
191 }
192
193 ret = regmap_read(chip->regmap,
194 irqd->top_int_status_reg_l,
195 &top_irq_status);
196 if (ret) {
197 dev_err(chip->dev, "Can't read TOP_INT_STATUS1 ret=%d\n", ret);
198 return IRQ_NONE;
199 }
200 top_irq_status |= (top_irq_status_h << 8);
201
202 dev_info(chip->dev, "%s: top_irq_sts:0x%x\n", __func__, top_irq_status);
203 if (!top_irq_status)
204 spmi_dump_spmimst_all_reg();
205 for (i = 0; i < irqd->num_top; i++) {
206 if (top_irq_status & BIT(irqd->pmic_ints[i].top_offset))
207 mt6330_irq_sp_handler(chip, i);
208 }
209
210 return IRQ_HANDLED;
211}
212
213static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
214 irq_hw_number_t hw)
215{
216 struct mt6330_chip *mt6330 = d->host_data;
217
218 irq_set_chip_data(irq, mt6330);
219 irq_set_chip_and_handler(irq, &mt6330_irq_chip, handle_level_irq);
220 irq_set_nested_thread(irq, 1);
221 irq_set_noprobe(irq);
222
223 return 0;
224}
225
226static const struct irq_domain_ops mt6330_irq_domain_ops = {
227 .map = pmic_irq_domain_map,
228 .xlate = irq_domain_xlate_twocell,
229};
230
231int mt6330_irq_init(struct mt6330_chip *chip)
232{
233 int i, j, ret;
234 struct pmic_irq_data *irqd;
235
236 irqd = devm_kzalloc(chip->dev, sizeof(*irqd), GFP_KERNEL);
237 if (!irqd)
238 return -ENOMEM;
239
240 chip->irq_data = irqd;
241
242 mutex_init(&chip->irqlock);
243 irqd->num_top = ARRAY_SIZE(mt6330_ints);
244 irqd->num_pmic_irqs = MT6330_IRQ_NR;
245 irqd->reg_width = MT6330_REG_WIDTH;
246 irqd->top_int_status_reg_l = MT6330_TOP_INT_STATUS0;
247 irqd->top_int_status_reg_h = MT6330_TOP_INT_STATUS1;
248 irqd->pmic_ints = mt6330_ints;
249
250 dev_info(chip->dev, "mt6330_irq_init +++\n");
251 irqd->enable_hwirq = devm_kcalloc(chip->dev,
252 irqd->num_pmic_irqs,
253 sizeof(bool),
254 GFP_KERNEL);
255 if (!irqd->enable_hwirq)
256 return -ENOMEM;
257
258 irqd->cache_hwirq = devm_kcalloc(chip->dev,
259 irqd->num_pmic_irqs,
260 sizeof(bool),
261 GFP_KERNEL);
262 if (!irqd->cache_hwirq)
263 return -ENOMEM;
264
265#ifdef MT6330_SPMIMST_RCSCLR
266 chip->spmimst_base = devm_ioremap(chip->dev, spmimst_resource.start,
267 resource_size(&spmimst_resource));
268 if (!chip->spmimst_base) {
269 dev_notice(chip->dev,
270 "Failed to ioremap spmi master address\n");
271 return -EINVAL;
272 }
273 mt6330_clear_spmimst_rcs(chip);
274#endif /* MT6330_SPMIMST_RCSCLR */
275
276 /* Disable all interrupt for initializing */
277 for (i = 0; i < irqd->num_top; i++) {
278 for (j = 0; j < irqd->pmic_ints[i].num_int_regs; j++)
279 regmap_write(chip->regmap,
280 irqd->pmic_ints[i].en_reg +
281 irqd->pmic_ints[i].en_reg_shift * j, 0);
282 }
283
284 chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
285 irqd->num_pmic_irqs,
286 &mt6330_irq_domain_ops, chip);
287 if (!chip->irq_domain) {
288 dev_err(chip->dev, "could not create irq domain\n");
289 return -ENODEV;
290 }
291
292 ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
293 mt6330_irq_handler, IRQF_ONESHOT,
294 mt6330_irq_chip.name, chip);
295 if (ret) {
296 dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
297 chip->irq, ret);
298 return ret;
299 }
300
301 enable_irq_wake(chip->irq);
302 dev_info(chip->dev, "mt6330_irq_init ---\n");
303 return ret;
304}