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