xref: /OK3568_Linux_fs/kernel/drivers/mfd/qcom-pm8xxx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #define pr_fmt(fmt) "%s: " fmt, __func__
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/interrupt.h>
10*4882a593Smuzhiyun #include <linux/irqchip/chained_irq.h>
11*4882a593Smuzhiyun #include <linux/irq.h>
12*4882a593Smuzhiyun #include <linux/irqdomain.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/err.h>
17*4882a593Smuzhiyun #include <linux/ssbi.h>
18*4882a593Smuzhiyun #include <linux/regmap.h>
19*4882a593Smuzhiyun #include <linux/of_platform.h>
20*4882a593Smuzhiyun #include <linux/mfd/core.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
25*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
26*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
27*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
28*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
29*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
30*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
31*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
32*4882a593Smuzhiyun #define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
35*4882a593Smuzhiyun #define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
36*4882a593Smuzhiyun #define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
37*4882a593Smuzhiyun #define	PM8821_SSBI_REG(m, b, offset) \
38*4882a593Smuzhiyun 			((m == 0) ? \
39*4882a593Smuzhiyun 			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
40*4882a593Smuzhiyun 			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
41*4882a593Smuzhiyun #define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
42*4882a593Smuzhiyun #define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
43*4882a593Smuzhiyun #define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
44*4882a593Smuzhiyun #define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define	PM8821_BLOCKS_PER_MASTER	7
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define	PM_IRQF_LVL_SEL			0x01	/* level select */
49*4882a593Smuzhiyun #define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
50*4882a593Smuzhiyun #define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
51*4882a593Smuzhiyun #define	PM_IRQF_CLR			0x08	/* clear interrupt */
52*4882a593Smuzhiyun #define	PM_IRQF_BITS_MASK		0x70
53*4882a593Smuzhiyun #define	PM_IRQF_BITS_SHIFT		4
54*4882a593Smuzhiyun #define	PM_IRQF_WRITE			0x80
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
57*4882a593Smuzhiyun 					PM_IRQF_MASK_RE)
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define REG_HWREV		0x002  /* PMIC4 revision */
60*4882a593Smuzhiyun #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define PM8XXX_NR_IRQS		256
63*4882a593Smuzhiyun #define PM8821_NR_IRQS		112
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun struct pm_irq_data {
66*4882a593Smuzhiyun 	int num_irqs;
67*4882a593Smuzhiyun 	struct irq_chip *irq_chip;
68*4882a593Smuzhiyun 	void (*irq_handler)(struct irq_desc *desc);
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun struct pm_irq_chip {
72*4882a593Smuzhiyun 	struct regmap		*regmap;
73*4882a593Smuzhiyun 	spinlock_t		pm_irq_lock;
74*4882a593Smuzhiyun 	struct irq_domain	*irqdomain;
75*4882a593Smuzhiyun 	unsigned int		num_blocks;
76*4882a593Smuzhiyun 	unsigned int		num_masters;
77*4882a593Smuzhiyun 	const struct pm_irq_data *pm_irq_data;
78*4882a593Smuzhiyun 	/* MUST BE AT THE END OF THIS STRUCT */
79*4882a593Smuzhiyun 	u8			config[];
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun 
pm8xxx_read_block_irq(struct pm_irq_chip * chip,unsigned int bp,unsigned int * ip)82*4882a593Smuzhiyun static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
83*4882a593Smuzhiyun 				 unsigned int *ip)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	int	rc;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	spin_lock(&chip->pm_irq_lock);
88*4882a593Smuzhiyun 	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
89*4882a593Smuzhiyun 	if (rc) {
90*4882a593Smuzhiyun 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
91*4882a593Smuzhiyun 		goto bail;
92*4882a593Smuzhiyun 	}
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
95*4882a593Smuzhiyun 	if (rc)
96*4882a593Smuzhiyun 		pr_err("Failed Reading Status rc=%d\n", rc);
97*4882a593Smuzhiyun bail:
98*4882a593Smuzhiyun 	spin_unlock(&chip->pm_irq_lock);
99*4882a593Smuzhiyun 	return rc;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static int
pm8xxx_config_irq(struct pm_irq_chip * chip,unsigned int bp,unsigned int cp)103*4882a593Smuzhiyun pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	int	rc;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	spin_lock(&chip->pm_irq_lock);
108*4882a593Smuzhiyun 	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
109*4882a593Smuzhiyun 	if (rc) {
110*4882a593Smuzhiyun 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
111*4882a593Smuzhiyun 		goto bail;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	cp |= PM_IRQF_WRITE;
115*4882a593Smuzhiyun 	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
116*4882a593Smuzhiyun 	if (rc)
117*4882a593Smuzhiyun 		pr_err("Failed Configuring IRQ rc=%d\n", rc);
118*4882a593Smuzhiyun bail:
119*4882a593Smuzhiyun 	spin_unlock(&chip->pm_irq_lock);
120*4882a593Smuzhiyun 	return rc;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
pm8xxx_irq_block_handler(struct pm_irq_chip * chip,int block)123*4882a593Smuzhiyun static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	int pmirq, irq, i, ret = 0;
126*4882a593Smuzhiyun 	unsigned int bits;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	ret = pm8xxx_read_block_irq(chip, block, &bits);
129*4882a593Smuzhiyun 	if (ret) {
130*4882a593Smuzhiyun 		pr_err("Failed reading %d block ret=%d", block, ret);
131*4882a593Smuzhiyun 		return ret;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 	if (!bits) {
134*4882a593Smuzhiyun 		pr_err("block bit set in master but no irqs: %d", block);
135*4882a593Smuzhiyun 		return 0;
136*4882a593Smuzhiyun 	}
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	/* Check IRQ bits */
139*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
140*4882a593Smuzhiyun 		if (bits & (1 << i)) {
141*4882a593Smuzhiyun 			pmirq = block * 8 + i;
142*4882a593Smuzhiyun 			irq = irq_find_mapping(chip->irqdomain, pmirq);
143*4882a593Smuzhiyun 			generic_handle_irq(irq);
144*4882a593Smuzhiyun 		}
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 	return 0;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
pm8xxx_irq_master_handler(struct pm_irq_chip * chip,int master)149*4882a593Smuzhiyun static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	unsigned int blockbits;
152*4882a593Smuzhiyun 	int block_number, i, ret = 0;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
155*4882a593Smuzhiyun 			  &blockbits);
156*4882a593Smuzhiyun 	if (ret) {
157*4882a593Smuzhiyun 		pr_err("Failed to read master %d ret=%d\n", master, ret);
158*4882a593Smuzhiyun 		return ret;
159*4882a593Smuzhiyun 	}
160*4882a593Smuzhiyun 	if (!blockbits) {
161*4882a593Smuzhiyun 		pr_err("master bit set in root but no blocks: %d", master);
162*4882a593Smuzhiyun 		return 0;
163*4882a593Smuzhiyun 	}
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	for (i = 0; i < 8; i++)
166*4882a593Smuzhiyun 		if (blockbits & (1 << i)) {
167*4882a593Smuzhiyun 			block_number = master * 8 + i;	/* block # */
168*4882a593Smuzhiyun 			ret |= pm8xxx_irq_block_handler(chip, block_number);
169*4882a593Smuzhiyun 		}
170*4882a593Smuzhiyun 	return ret;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
pm8xxx_irq_handler(struct irq_desc * desc)173*4882a593Smuzhiyun static void pm8xxx_irq_handler(struct irq_desc *desc)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
176*4882a593Smuzhiyun 	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
177*4882a593Smuzhiyun 	unsigned int root;
178*4882a593Smuzhiyun 	int	i, ret, masters = 0;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	chained_irq_enter(irq_chip, desc);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
183*4882a593Smuzhiyun 	if (ret) {
184*4882a593Smuzhiyun 		pr_err("Can't read root status ret=%d\n", ret);
185*4882a593Smuzhiyun 		return;
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* on pm8xxx series masters start from bit 1 of the root */
189*4882a593Smuzhiyun 	masters = root >> 1;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* Read allowed masters for blocks. */
192*4882a593Smuzhiyun 	for (i = 0; i < chip->num_masters; i++)
193*4882a593Smuzhiyun 		if (masters & (1 << i))
194*4882a593Smuzhiyun 			pm8xxx_irq_master_handler(chip, i);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	chained_irq_exit(irq_chip, desc);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
pm8821_irq_block_handler(struct pm_irq_chip * chip,int master,int block)199*4882a593Smuzhiyun static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
200*4882a593Smuzhiyun 				     int master, int block)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	int pmirq, irq, i, ret;
203*4882a593Smuzhiyun 	unsigned int bits;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	ret = regmap_read(chip->regmap,
206*4882a593Smuzhiyun 			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
207*4882a593Smuzhiyun 	if (ret) {
208*4882a593Smuzhiyun 		pr_err("Reading block %d failed ret=%d", block, ret);
209*4882a593Smuzhiyun 		return;
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	/* Convert block offset to global block number */
213*4882a593Smuzhiyun 	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/* Check IRQ bits */
216*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
217*4882a593Smuzhiyun 		if (bits & BIT(i)) {
218*4882a593Smuzhiyun 			pmirq = block * 8 + i;
219*4882a593Smuzhiyun 			irq = irq_find_mapping(chip->irqdomain, pmirq);
220*4882a593Smuzhiyun 			generic_handle_irq(irq);
221*4882a593Smuzhiyun 		}
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
pm8821_irq_master_handler(struct pm_irq_chip * chip,int master,u8 master_val)225*4882a593Smuzhiyun static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
226*4882a593Smuzhiyun 					     int master, u8 master_val)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	int block;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	for (block = 1; block < 8; block++)
231*4882a593Smuzhiyun 		if (master_val & BIT(block))
232*4882a593Smuzhiyun 			pm8821_irq_block_handler(chip, master, block);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
pm8821_irq_handler(struct irq_desc * desc)235*4882a593Smuzhiyun static void pm8821_irq_handler(struct irq_desc *desc)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
238*4882a593Smuzhiyun 	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
239*4882a593Smuzhiyun 	unsigned int master;
240*4882a593Smuzhiyun 	int ret;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	chained_irq_enter(irq_chip, desc);
243*4882a593Smuzhiyun 	ret = regmap_read(chip->regmap,
244*4882a593Smuzhiyun 			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
245*4882a593Smuzhiyun 	if (ret) {
246*4882a593Smuzhiyun 		pr_err("Failed to read master 0 ret=%d\n", ret);
247*4882a593Smuzhiyun 		goto done;
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	/* bits 1 through 7 marks the first 7 blocks in master 0 */
251*4882a593Smuzhiyun 	if (master & GENMASK(7, 1))
252*4882a593Smuzhiyun 		pm8821_irq_master_handler(chip, 0, master);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	/* bit 0 marks if master 1 contains any bits */
255*4882a593Smuzhiyun 	if (!(master & BIT(0)))
256*4882a593Smuzhiyun 		goto done;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	ret = regmap_read(chip->regmap,
259*4882a593Smuzhiyun 			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
260*4882a593Smuzhiyun 	if (ret) {
261*4882a593Smuzhiyun 		pr_err("Failed to read master 1 ret=%d\n", ret);
262*4882a593Smuzhiyun 		goto done;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	pm8821_irq_master_handler(chip, 1, master);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun done:
268*4882a593Smuzhiyun 	chained_irq_exit(irq_chip, desc);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
pm8xxx_irq_mask_ack(struct irq_data * d)271*4882a593Smuzhiyun static void pm8xxx_irq_mask_ack(struct irq_data *d)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
274*4882a593Smuzhiyun 	unsigned int pmirq = irqd_to_hwirq(d);
275*4882a593Smuzhiyun 	u8	block, config;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	block = pmirq / 8;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
280*4882a593Smuzhiyun 	pm8xxx_config_irq(chip, block, config);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
pm8xxx_irq_unmask(struct irq_data * d)283*4882a593Smuzhiyun static void pm8xxx_irq_unmask(struct irq_data *d)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
286*4882a593Smuzhiyun 	unsigned int pmirq = irqd_to_hwirq(d);
287*4882a593Smuzhiyun 	u8	block, config;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	block = pmirq / 8;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	config = chip->config[pmirq];
292*4882a593Smuzhiyun 	pm8xxx_config_irq(chip, block, config);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun 
pm8xxx_irq_set_type(struct irq_data * d,unsigned int flow_type)295*4882a593Smuzhiyun static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
298*4882a593Smuzhiyun 	unsigned int pmirq = irqd_to_hwirq(d);
299*4882a593Smuzhiyun 	int irq_bit;
300*4882a593Smuzhiyun 	u8 block, config;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	block = pmirq / 8;
303*4882a593Smuzhiyun 	irq_bit  = pmirq % 8;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
306*4882a593Smuzhiyun 							| PM_IRQF_MASK_ALL;
307*4882a593Smuzhiyun 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
308*4882a593Smuzhiyun 		if (flow_type & IRQF_TRIGGER_RISING)
309*4882a593Smuzhiyun 			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
310*4882a593Smuzhiyun 		if (flow_type & IRQF_TRIGGER_FALLING)
311*4882a593Smuzhiyun 			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
312*4882a593Smuzhiyun 	} else {
313*4882a593Smuzhiyun 		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 		if (flow_type & IRQF_TRIGGER_HIGH)
316*4882a593Smuzhiyun 			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
317*4882a593Smuzhiyun 		else
318*4882a593Smuzhiyun 			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
319*4882a593Smuzhiyun 	}
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	config = chip->config[pmirq] | PM_IRQF_CLR;
322*4882a593Smuzhiyun 	return pm8xxx_config_irq(chip, block, config);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
pm8xxx_irq_get_irqchip_state(struct irq_data * d,enum irqchip_irq_state which,bool * state)325*4882a593Smuzhiyun static int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
326*4882a593Smuzhiyun 					enum irqchip_irq_state which,
327*4882a593Smuzhiyun 					bool *state)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
330*4882a593Smuzhiyun 	unsigned int pmirq = irqd_to_hwirq(d);
331*4882a593Smuzhiyun 	unsigned int bits;
332*4882a593Smuzhiyun 	int irq_bit;
333*4882a593Smuzhiyun 	u8 block;
334*4882a593Smuzhiyun 	int rc;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	if (which != IRQCHIP_STATE_LINE_LEVEL)
337*4882a593Smuzhiyun 		return -EINVAL;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	block = pmirq / 8;
340*4882a593Smuzhiyun 	irq_bit = pmirq % 8;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	spin_lock(&chip->pm_irq_lock);
343*4882a593Smuzhiyun 	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
344*4882a593Smuzhiyun 	if (rc) {
345*4882a593Smuzhiyun 		pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
346*4882a593Smuzhiyun 		goto bail;
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
350*4882a593Smuzhiyun 	if (rc) {
351*4882a593Smuzhiyun 		pr_err("Failed Reading Status rc=%d\n", rc);
352*4882a593Smuzhiyun 		goto bail;
353*4882a593Smuzhiyun 	}
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	*state = !!(bits & BIT(irq_bit));
356*4882a593Smuzhiyun bail:
357*4882a593Smuzhiyun 	spin_unlock(&chip->pm_irq_lock);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	return rc;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun static struct irq_chip pm8xxx_irq_chip = {
363*4882a593Smuzhiyun 	.name		= "pm8xxx",
364*4882a593Smuzhiyun 	.irq_mask_ack	= pm8xxx_irq_mask_ack,
365*4882a593Smuzhiyun 	.irq_unmask	= pm8xxx_irq_unmask,
366*4882a593Smuzhiyun 	.irq_set_type	= pm8xxx_irq_set_type,
367*4882a593Smuzhiyun 	.irq_get_irqchip_state = pm8xxx_irq_get_irqchip_state,
368*4882a593Smuzhiyun 	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun 
pm8xxx_irq_domain_map(struct pm_irq_chip * chip,struct irq_domain * domain,unsigned int irq,irq_hw_number_t hwirq,unsigned int type)371*4882a593Smuzhiyun static void pm8xxx_irq_domain_map(struct pm_irq_chip *chip,
372*4882a593Smuzhiyun 				  struct irq_domain *domain, unsigned int irq,
373*4882a593Smuzhiyun 				  irq_hw_number_t hwirq, unsigned int type)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	irq_domain_set_info(domain, irq, hwirq, chip->pm_irq_data->irq_chip,
376*4882a593Smuzhiyun 			    chip, handle_level_irq, NULL, NULL);
377*4882a593Smuzhiyun 	irq_set_noprobe(irq);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
pm8xxx_irq_domain_alloc(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs,void * data)380*4882a593Smuzhiyun static int pm8xxx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
381*4882a593Smuzhiyun 				   unsigned int nr_irqs, void *data)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	struct pm_irq_chip *chip = domain->host_data;
384*4882a593Smuzhiyun 	struct irq_fwspec *fwspec = data;
385*4882a593Smuzhiyun 	irq_hw_number_t hwirq;
386*4882a593Smuzhiyun 	unsigned int type;
387*4882a593Smuzhiyun 	int ret, i;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type);
390*4882a593Smuzhiyun 	if (ret)
391*4882a593Smuzhiyun 		return ret;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	for (i = 0; i < nr_irqs; i++)
394*4882a593Smuzhiyun 		pm8xxx_irq_domain_map(chip, domain, virq + i, hwirq + i, type);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	return 0;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
400*4882a593Smuzhiyun 	.alloc = pm8xxx_irq_domain_alloc,
401*4882a593Smuzhiyun 	.free = irq_domain_free_irqs_common,
402*4882a593Smuzhiyun 	.translate = irq_domain_translate_twocell,
403*4882a593Smuzhiyun };
404*4882a593Smuzhiyun 
pm8821_irq_mask_ack(struct irq_data * d)405*4882a593Smuzhiyun static void pm8821_irq_mask_ack(struct irq_data *d)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
408*4882a593Smuzhiyun 	unsigned int pmirq = irqd_to_hwirq(d);
409*4882a593Smuzhiyun 	u8 block, master;
410*4882a593Smuzhiyun 	int irq_bit, rc;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	block = pmirq / 8;
413*4882a593Smuzhiyun 	master = block / PM8821_BLOCKS_PER_MASTER;
414*4882a593Smuzhiyun 	irq_bit = pmirq % 8;
415*4882a593Smuzhiyun 	block %= PM8821_BLOCKS_PER_MASTER;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	rc = regmap_update_bits(chip->regmap,
418*4882a593Smuzhiyun 				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
419*4882a593Smuzhiyun 				BIT(irq_bit), BIT(irq_bit));
420*4882a593Smuzhiyun 	if (rc) {
421*4882a593Smuzhiyun 		pr_err("Failed to mask IRQ:%d rc=%d\n", pmirq, rc);
422*4882a593Smuzhiyun 		return;
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	rc = regmap_update_bits(chip->regmap,
426*4882a593Smuzhiyun 				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
427*4882a593Smuzhiyun 				BIT(irq_bit), BIT(irq_bit));
428*4882a593Smuzhiyun 	if (rc)
429*4882a593Smuzhiyun 		pr_err("Failed to CLEAR IRQ:%d rc=%d\n", pmirq, rc);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
pm8821_irq_unmask(struct irq_data * d)432*4882a593Smuzhiyun static void pm8821_irq_unmask(struct irq_data *d)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
435*4882a593Smuzhiyun 	unsigned int pmirq = irqd_to_hwirq(d);
436*4882a593Smuzhiyun 	int irq_bit, rc;
437*4882a593Smuzhiyun 	u8 block, master;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	block = pmirq / 8;
440*4882a593Smuzhiyun 	master = block / PM8821_BLOCKS_PER_MASTER;
441*4882a593Smuzhiyun 	irq_bit = pmirq % 8;
442*4882a593Smuzhiyun 	block %= PM8821_BLOCKS_PER_MASTER;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	rc = regmap_update_bits(chip->regmap,
445*4882a593Smuzhiyun 				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
446*4882a593Smuzhiyun 				BIT(irq_bit), ~BIT(irq_bit));
447*4882a593Smuzhiyun 	if (rc)
448*4882a593Smuzhiyun 		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
pm8821_irq_get_irqchip_state(struct irq_data * d,enum irqchip_irq_state which,bool * state)452*4882a593Smuzhiyun static int pm8821_irq_get_irqchip_state(struct irq_data *d,
453*4882a593Smuzhiyun 					enum irqchip_irq_state which,
454*4882a593Smuzhiyun 					bool *state)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
457*4882a593Smuzhiyun 	int rc, pmirq = irqd_to_hwirq(d);
458*4882a593Smuzhiyun 	u8 block, irq_bit, master;
459*4882a593Smuzhiyun 	unsigned int bits;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	block = pmirq / 8;
462*4882a593Smuzhiyun 	master = block / PM8821_BLOCKS_PER_MASTER;
463*4882a593Smuzhiyun 	irq_bit = pmirq % 8;
464*4882a593Smuzhiyun 	block %= PM8821_BLOCKS_PER_MASTER;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	rc = regmap_read(chip->regmap,
467*4882a593Smuzhiyun 		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
468*4882a593Smuzhiyun 	if (rc) {
469*4882a593Smuzhiyun 		pr_err("Reading Status of IRQ %d failed rc=%d\n", pmirq, rc);
470*4882a593Smuzhiyun 		return rc;
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	*state = !!(bits & BIT(irq_bit));
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	return rc;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun static struct irq_chip pm8821_irq_chip = {
479*4882a593Smuzhiyun 	.name		= "pm8821",
480*4882a593Smuzhiyun 	.irq_mask_ack	= pm8821_irq_mask_ack,
481*4882a593Smuzhiyun 	.irq_unmask	= pm8821_irq_unmask,
482*4882a593Smuzhiyun 	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
483*4882a593Smuzhiyun 	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
484*4882a593Smuzhiyun };
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun static const struct regmap_config ssbi_regmap_config = {
487*4882a593Smuzhiyun 	.reg_bits = 16,
488*4882a593Smuzhiyun 	.val_bits = 8,
489*4882a593Smuzhiyun 	.max_register = 0x3ff,
490*4882a593Smuzhiyun 	.fast_io = true,
491*4882a593Smuzhiyun 	.reg_read = ssbi_reg_read,
492*4882a593Smuzhiyun 	.reg_write = ssbi_reg_write
493*4882a593Smuzhiyun };
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun static const struct pm_irq_data pm8xxx_data = {
496*4882a593Smuzhiyun 	.num_irqs = PM8XXX_NR_IRQS,
497*4882a593Smuzhiyun 	.irq_chip = &pm8xxx_irq_chip,
498*4882a593Smuzhiyun 	.irq_handler = pm8xxx_irq_handler,
499*4882a593Smuzhiyun };
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun static const struct pm_irq_data pm8821_data = {
502*4882a593Smuzhiyun 	.num_irqs = PM8821_NR_IRQS,
503*4882a593Smuzhiyun 	.irq_chip = &pm8821_irq_chip,
504*4882a593Smuzhiyun 	.irq_handler = pm8821_irq_handler,
505*4882a593Smuzhiyun };
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun static const struct of_device_id pm8xxx_id_table[] = {
508*4882a593Smuzhiyun 	{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
509*4882a593Smuzhiyun 	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
510*4882a593Smuzhiyun 	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
511*4882a593Smuzhiyun 	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
512*4882a593Smuzhiyun 	{ }
513*4882a593Smuzhiyun };
514*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
515*4882a593Smuzhiyun 
pm8xxx_probe(struct platform_device * pdev)516*4882a593Smuzhiyun static int pm8xxx_probe(struct platform_device *pdev)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun 	const struct pm_irq_data *data;
519*4882a593Smuzhiyun 	struct regmap *regmap;
520*4882a593Smuzhiyun 	int irq, rc;
521*4882a593Smuzhiyun 	unsigned int val;
522*4882a593Smuzhiyun 	u32 rev;
523*4882a593Smuzhiyun 	struct pm_irq_chip *chip;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	data = of_device_get_match_data(&pdev->dev);
526*4882a593Smuzhiyun 	if (!data) {
527*4882a593Smuzhiyun 		dev_err(&pdev->dev, "No matching driver data found\n");
528*4882a593Smuzhiyun 		return -EINVAL;
529*4882a593Smuzhiyun 	}
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	irq = platform_get_irq(pdev, 0);
532*4882a593Smuzhiyun 	if (irq < 0)
533*4882a593Smuzhiyun 		return irq;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
536*4882a593Smuzhiyun 				  &ssbi_regmap_config);
537*4882a593Smuzhiyun 	if (IS_ERR(regmap))
538*4882a593Smuzhiyun 		return PTR_ERR(regmap);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	/* Read PMIC chip revision */
541*4882a593Smuzhiyun 	rc = regmap_read(regmap, REG_HWREV, &val);
542*4882a593Smuzhiyun 	if (rc) {
543*4882a593Smuzhiyun 		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
544*4882a593Smuzhiyun 		return rc;
545*4882a593Smuzhiyun 	}
546*4882a593Smuzhiyun 	pr_info("PMIC revision 1: %02X\n", val);
547*4882a593Smuzhiyun 	rev = val;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	/* Read PMIC chip revision 2 */
550*4882a593Smuzhiyun 	rc = regmap_read(regmap, REG_HWREV_2, &val);
551*4882a593Smuzhiyun 	if (rc) {
552*4882a593Smuzhiyun 		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
553*4882a593Smuzhiyun 			REG_HWREV_2, rc);
554*4882a593Smuzhiyun 		return rc;
555*4882a593Smuzhiyun 	}
556*4882a593Smuzhiyun 	pr_info("PMIC revision 2: %02X\n", val);
557*4882a593Smuzhiyun 	rev |= val << BITS_PER_BYTE;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	chip = devm_kzalloc(&pdev->dev,
560*4882a593Smuzhiyun 			    struct_size(chip, config, data->num_irqs),
561*4882a593Smuzhiyun 			    GFP_KERNEL);
562*4882a593Smuzhiyun 	if (!chip)
563*4882a593Smuzhiyun 		return -ENOMEM;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	platform_set_drvdata(pdev, chip);
566*4882a593Smuzhiyun 	chip->regmap = regmap;
567*4882a593Smuzhiyun 	chip->num_blocks = DIV_ROUND_UP(data->num_irqs, 8);
568*4882a593Smuzhiyun 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
569*4882a593Smuzhiyun 	chip->pm_irq_data = data;
570*4882a593Smuzhiyun 	spin_lock_init(&chip->pm_irq_lock);
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
573*4882a593Smuzhiyun 						data->num_irqs,
574*4882a593Smuzhiyun 						&pm8xxx_irq_domain_ops,
575*4882a593Smuzhiyun 						chip);
576*4882a593Smuzhiyun 	if (!chip->irqdomain)
577*4882a593Smuzhiyun 		return -ENODEV;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
580*4882a593Smuzhiyun 	irq_set_irq_wake(irq, 1);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
583*4882a593Smuzhiyun 	if (rc) {
584*4882a593Smuzhiyun 		irq_set_chained_handler_and_data(irq, NULL, NULL);
585*4882a593Smuzhiyun 		irq_domain_remove(chip->irqdomain);
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	return rc;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
pm8xxx_remove_child(struct device * dev,void * unused)591*4882a593Smuzhiyun static int pm8xxx_remove_child(struct device *dev, void *unused)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	platform_device_unregister(to_platform_device(dev));
594*4882a593Smuzhiyun 	return 0;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
pm8xxx_remove(struct platform_device * pdev)597*4882a593Smuzhiyun static int pm8xxx_remove(struct platform_device *pdev)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	int irq = platform_get_irq(pdev, 0);
600*4882a593Smuzhiyun 	struct pm_irq_chip *chip = platform_get_drvdata(pdev);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child);
603*4882a593Smuzhiyun 	irq_set_chained_handler_and_data(irq, NULL, NULL);
604*4882a593Smuzhiyun 	irq_domain_remove(chip->irqdomain);
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	return 0;
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun static struct platform_driver pm8xxx_driver = {
610*4882a593Smuzhiyun 	.probe		= pm8xxx_probe,
611*4882a593Smuzhiyun 	.remove		= pm8xxx_remove,
612*4882a593Smuzhiyun 	.driver		= {
613*4882a593Smuzhiyun 		.name	= "pm8xxx-core",
614*4882a593Smuzhiyun 		.of_match_table = pm8xxx_id_table,
615*4882a593Smuzhiyun 	},
616*4882a593Smuzhiyun };
617*4882a593Smuzhiyun 
pm8xxx_init(void)618*4882a593Smuzhiyun static int __init pm8xxx_init(void)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun 	return platform_driver_register(&pm8xxx_driver);
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun subsys_initcall(pm8xxx_init);
623*4882a593Smuzhiyun 
pm8xxx_exit(void)624*4882a593Smuzhiyun static void __exit pm8xxx_exit(void)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun 	platform_driver_unregister(&pm8xxx_driver);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun module_exit(pm8xxx_exit);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
631*4882a593Smuzhiyun MODULE_DESCRIPTION("PMIC 8xxx core driver");
632*4882a593Smuzhiyun MODULE_VERSION("1.0");
633*4882a593Smuzhiyun MODULE_ALIAS("platform:pm8xxx-core");
634