xref: /openbmc/linux/drivers/mfd/mt6358-irq.c (revision a4e1d0b7)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright (c) 2020 MediaTek Inc.
4 
5 #include <linux/interrupt.h>
6 #include <linux/mfd/mt6357/core.h>
7 #include <linux/mfd/mt6357/registers.h>
8 #include <linux/mfd/mt6358/core.h>
9 #include <linux/mfd/mt6358/registers.h>
10 #include <linux/mfd/mt6359/core.h>
11 #include <linux/mfd/mt6359/registers.h>
12 #include <linux/mfd/mt6397/core.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/of_device.h>
16 #include <linux/of_irq.h>
17 #include <linux/platform_device.h>
18 #include <linux/regmap.h>
19 
20 #define MTK_PMIC_REG_WIDTH 16
21 
22 static const struct irq_top_t mt6357_ints[] = {
23 	MT6357_TOP_GEN(BUCK),
24 	MT6357_TOP_GEN(LDO),
25 	MT6357_TOP_GEN(PSC),
26 	MT6357_TOP_GEN(SCK),
27 	MT6357_TOP_GEN(BM),
28 	MT6357_TOP_GEN(HK),
29 	MT6357_TOP_GEN(AUD),
30 	MT6357_TOP_GEN(MISC),
31 };
32 
33 static const struct irq_top_t mt6358_ints[] = {
34 	MT6358_TOP_GEN(BUCK),
35 	MT6358_TOP_GEN(LDO),
36 	MT6358_TOP_GEN(PSC),
37 	MT6358_TOP_GEN(SCK),
38 	MT6358_TOP_GEN(BM),
39 	MT6358_TOP_GEN(HK),
40 	MT6358_TOP_GEN(AUD),
41 	MT6358_TOP_GEN(MISC),
42 };
43 
44 static const struct irq_top_t mt6359_ints[] = {
45 	MT6359_TOP_GEN(BUCK),
46 	MT6359_TOP_GEN(LDO),
47 	MT6359_TOP_GEN(PSC),
48 	MT6359_TOP_GEN(SCK),
49 	MT6359_TOP_GEN(BM),
50 	MT6359_TOP_GEN(HK),
51 	MT6359_TOP_GEN(AUD),
52 	MT6359_TOP_GEN(MISC),
53 };
54 
55 static struct pmic_irq_data mt6357_irqd = {
56 	.num_top = ARRAY_SIZE(mt6357_ints),
57 	.num_pmic_irqs = MT6357_IRQ_NR,
58 	.top_int_status_reg = MT6357_TOP_INT_STATUS0,
59 	.pmic_ints = mt6357_ints,
60 };
61 
62 static struct pmic_irq_data mt6358_irqd = {
63 	.num_top = ARRAY_SIZE(mt6358_ints),
64 	.num_pmic_irqs = MT6358_IRQ_NR,
65 	.top_int_status_reg = MT6358_TOP_INT_STATUS0,
66 	.pmic_ints = mt6358_ints,
67 };
68 
69 static struct pmic_irq_data mt6359_irqd = {
70 	.num_top = ARRAY_SIZE(mt6359_ints),
71 	.num_pmic_irqs = MT6359_IRQ_NR,
72 	.top_int_status_reg = MT6359_TOP_INT_STATUS0,
73 	.pmic_ints = mt6359_ints,
74 };
75 
76 static void pmic_irq_enable(struct irq_data *data)
77 {
78 	unsigned int hwirq = irqd_to_hwirq(data);
79 	struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
80 	struct pmic_irq_data *irqd = chip->irq_data;
81 
82 	irqd->enable_hwirq[hwirq] = true;
83 }
84 
85 static void pmic_irq_disable(struct irq_data *data)
86 {
87 	unsigned int hwirq = irqd_to_hwirq(data);
88 	struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
89 	struct pmic_irq_data *irqd = chip->irq_data;
90 
91 	irqd->enable_hwirq[hwirq] = false;
92 }
93 
94 static void pmic_irq_lock(struct irq_data *data)
95 {
96 	struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
97 
98 	mutex_lock(&chip->irqlock);
99 }
100 
101 static void pmic_irq_sync_unlock(struct irq_data *data)
102 {
103 	unsigned int i, top_gp, gp_offset, en_reg, int_regs, shift;
104 	struct mt6397_chip *chip = irq_data_get_irq_chip_data(data);
105 	struct pmic_irq_data *irqd = chip->irq_data;
106 
107 	for (i = 0; i < irqd->num_pmic_irqs; i++) {
108 		if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i])
109 			continue;
110 
111 		/* Find out the IRQ group */
112 		top_gp = 0;
113 		while ((top_gp + 1) < irqd->num_top &&
114 		       i >= irqd->pmic_ints[top_gp + 1].hwirq_base)
115 			top_gp++;
116 
117 		/* Find the IRQ registers */
118 		gp_offset = i - irqd->pmic_ints[top_gp].hwirq_base;
119 		int_regs = gp_offset / MTK_PMIC_REG_WIDTH;
120 		shift = gp_offset % MTK_PMIC_REG_WIDTH;
121 		en_reg = irqd->pmic_ints[top_gp].en_reg +
122 			 (irqd->pmic_ints[top_gp].en_reg_shift * int_regs);
123 
124 		regmap_update_bits(chip->regmap, en_reg, BIT(shift),
125 				   irqd->enable_hwirq[i] << shift);
126 
127 		irqd->cache_hwirq[i] = irqd->enable_hwirq[i];
128 	}
129 	mutex_unlock(&chip->irqlock);
130 }
131 
132 static struct irq_chip mt6358_irq_chip = {
133 	.name = "mt6358-irq",
134 	.flags = IRQCHIP_SKIP_SET_WAKE,
135 	.irq_enable = pmic_irq_enable,
136 	.irq_disable = pmic_irq_disable,
137 	.irq_bus_lock = pmic_irq_lock,
138 	.irq_bus_sync_unlock = pmic_irq_sync_unlock,
139 };
140 
141 static void mt6358_irq_sp_handler(struct mt6397_chip *chip,
142 				  unsigned int top_gp)
143 {
144 	unsigned int irq_status, sta_reg, status;
145 	unsigned int hwirq, virq;
146 	int i, j, ret;
147 	struct pmic_irq_data *irqd = chip->irq_data;
148 
149 	for (i = 0; i < irqd->pmic_ints[top_gp].num_int_regs; i++) {
150 		sta_reg = irqd->pmic_ints[top_gp].sta_reg +
151 			irqd->pmic_ints[top_gp].sta_reg_shift * i;
152 
153 		ret = regmap_read(chip->regmap, sta_reg, &irq_status);
154 		if (ret) {
155 			dev_err(chip->dev,
156 				"Failed to read IRQ status, ret=%d\n", ret);
157 			return;
158 		}
159 
160 		if (!irq_status)
161 			continue;
162 
163 		status = irq_status;
164 		do {
165 			j = __ffs(status);
166 
167 			hwirq = irqd->pmic_ints[top_gp].hwirq_base +
168 				MTK_PMIC_REG_WIDTH * i + j;
169 
170 			virq = irq_find_mapping(chip->irq_domain, hwirq);
171 			if (virq)
172 				handle_nested_irq(virq);
173 
174 			status &= ~BIT(j);
175 		} while (status);
176 
177 		regmap_write(chip->regmap, sta_reg, irq_status);
178 	}
179 }
180 
181 static irqreturn_t mt6358_irq_handler(int irq, void *data)
182 {
183 	struct mt6397_chip *chip = data;
184 	struct pmic_irq_data *irqd = chip->irq_data;
185 	unsigned int bit, i, top_irq_status = 0;
186 	int ret;
187 
188 	ret = regmap_read(chip->regmap,
189 			  irqd->top_int_status_reg,
190 			  &top_irq_status);
191 	if (ret) {
192 		dev_err(chip->dev,
193 			"Failed to read status from the device, ret=%d\n", ret);
194 		return IRQ_NONE;
195 	}
196 
197 	for (i = 0; i < irqd->num_top; i++) {
198 		bit = BIT(irqd->pmic_ints[i].top_offset);
199 		if (top_irq_status & bit) {
200 			mt6358_irq_sp_handler(chip, i);
201 			top_irq_status &= ~bit;
202 			if (!top_irq_status)
203 				break;
204 		}
205 	}
206 
207 	return IRQ_HANDLED;
208 }
209 
210 static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
211 			       irq_hw_number_t hw)
212 {
213 	struct mt6397_chip *mt6397 = d->host_data;
214 
215 	irq_set_chip_data(irq, mt6397);
216 	irq_set_chip_and_handler(irq, &mt6358_irq_chip, handle_level_irq);
217 	irq_set_nested_thread(irq, 1);
218 	irq_set_noprobe(irq);
219 
220 	return 0;
221 }
222 
223 static const struct irq_domain_ops mt6358_irq_domain_ops = {
224 	.map = pmic_irq_domain_map,
225 	.xlate = irq_domain_xlate_twocell,
226 };
227 
228 int mt6358_irq_init(struct mt6397_chip *chip)
229 {
230 	int i, j, ret;
231 	struct pmic_irq_data *irqd;
232 
233 	switch (chip->chip_id) {
234 	case MT6357_CHIP_ID:
235 		chip->irq_data = &mt6357_irqd;
236 		break;
237 
238 	case MT6358_CHIP_ID:
239 	case MT6366_CHIP_ID:
240 		chip->irq_data = &mt6358_irqd;
241 		break;
242 
243 	case MT6359_CHIP_ID:
244 		chip->irq_data = &mt6359_irqd;
245 		break;
246 
247 	default:
248 		dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
249 		return -ENODEV;
250 	}
251 
252 	mutex_init(&chip->irqlock);
253 	irqd = chip->irq_data;
254 	irqd->enable_hwirq = devm_kcalloc(chip->dev,
255 					  irqd->num_pmic_irqs,
256 					  sizeof(*irqd->enable_hwirq),
257 					  GFP_KERNEL);
258 	if (!irqd->enable_hwirq)
259 		return -ENOMEM;
260 
261 	irqd->cache_hwirq = devm_kcalloc(chip->dev,
262 					 irqd->num_pmic_irqs,
263 					 sizeof(*irqd->cache_hwirq),
264 					 GFP_KERNEL);
265 	if (!irqd->cache_hwirq)
266 		return -ENOMEM;
267 
268 	/* Disable all interrupts for initializing */
269 	for (i = 0; i < irqd->num_top; i++) {
270 		for (j = 0; j < irqd->pmic_ints[i].num_int_regs; j++)
271 			regmap_write(chip->regmap,
272 				     irqd->pmic_ints[i].en_reg +
273 				     irqd->pmic_ints[i].en_reg_shift * j, 0);
274 	}
275 
276 	chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
277 						 irqd->num_pmic_irqs,
278 						 &mt6358_irq_domain_ops, chip);
279 	if (!chip->irq_domain) {
280 		dev_err(chip->dev, "Could not create IRQ domain\n");
281 		return -ENODEV;
282 	}
283 
284 	ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
285 					mt6358_irq_handler, IRQF_ONESHOT,
286 					mt6358_irq_chip.name, chip);
287 	if (ret) {
288 		dev_err(chip->dev, "Failed to register IRQ=%d, ret=%d\n",
289 			chip->irq, ret);
290 		return ret;
291 	}
292 
293 	enable_irq_wake(chip->irq);
294 	return ret;
295 }
296