xref: /OK3568_Linux_fs/kernel/drivers/mfd/mc13xxx-core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2009-2010 Pengutronix
4*4882a593Smuzhiyun  * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * loosely based on an earlier driver that has
7*4882a593Smuzhiyun  * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/of_device.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/mfd/core.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "mc13xxx.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define MC13XXX_IRQSTAT0	0
19*4882a593Smuzhiyun #define MC13XXX_IRQMASK0	1
20*4882a593Smuzhiyun #define MC13XXX_IRQSTAT1	3
21*4882a593Smuzhiyun #define MC13XXX_IRQMASK1	4
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define MC13XXX_REVISION	7
24*4882a593Smuzhiyun #define MC13XXX_REVISION_REVMETAL	(0x07 <<  0)
25*4882a593Smuzhiyun #define MC13XXX_REVISION_REVFULL	(0x03 <<  3)
26*4882a593Smuzhiyun #define MC13XXX_REVISION_ICID		(0x07 <<  6)
27*4882a593Smuzhiyun #define MC13XXX_REVISION_FIN		(0x03 <<  9)
28*4882a593Smuzhiyun #define MC13XXX_REVISION_FAB		(0x03 << 11)
29*4882a593Smuzhiyun #define MC13XXX_REVISION_ICIDCODE	(0x3f << 13)
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define MC34708_REVISION_REVMETAL	(0x07 <<  0)
32*4882a593Smuzhiyun #define MC34708_REVISION_REVFULL	(0x07 <<  3)
33*4882a593Smuzhiyun #define MC34708_REVISION_FIN		(0x07 <<  6)
34*4882a593Smuzhiyun #define MC34708_REVISION_FAB		(0x07 <<  9)
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define MC13XXX_PWRCTRL		15
37*4882a593Smuzhiyun #define MC13XXX_PWRCTRL_WDIRESET	(1 << 12)
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define MC13XXX_ADC1		44
40*4882a593Smuzhiyun #define MC13XXX_ADC1_ADEN		(1 << 0)
41*4882a593Smuzhiyun #define MC13XXX_ADC1_RAND		(1 << 1)
42*4882a593Smuzhiyun #define MC13XXX_ADC1_ADSEL		(1 << 3)
43*4882a593Smuzhiyun #define MC13XXX_ADC1_ASC		(1 << 20)
44*4882a593Smuzhiyun #define MC13XXX_ADC1_ADTRIGIGN		(1 << 21)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define MC13XXX_ADC2		45
47*4882a593Smuzhiyun 
mc13xxx_lock(struct mc13xxx * mc13xxx)48*4882a593Smuzhiyun void mc13xxx_lock(struct mc13xxx *mc13xxx)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	if (!mutex_trylock(&mc13xxx->lock)) {
51*4882a593Smuzhiyun 		dev_dbg(mc13xxx->dev, "wait for %s from %ps\n",
52*4882a593Smuzhiyun 				__func__, __builtin_return_address(0));
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 		mutex_lock(&mc13xxx->lock);
55*4882a593Smuzhiyun 	}
56*4882a593Smuzhiyun 	dev_dbg(mc13xxx->dev, "%s from %ps\n",
57*4882a593Smuzhiyun 			__func__, __builtin_return_address(0));
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_lock);
60*4882a593Smuzhiyun 
mc13xxx_unlock(struct mc13xxx * mc13xxx)61*4882a593Smuzhiyun void mc13xxx_unlock(struct mc13xxx *mc13xxx)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	dev_dbg(mc13xxx->dev, "%s from %ps\n",
64*4882a593Smuzhiyun 			__func__, __builtin_return_address(0));
65*4882a593Smuzhiyun 	mutex_unlock(&mc13xxx->lock);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_unlock);
68*4882a593Smuzhiyun 
mc13xxx_reg_read(struct mc13xxx * mc13xxx,unsigned int offset,u32 * val)69*4882a593Smuzhiyun int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	int ret;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	ret = regmap_read(mc13xxx->regmap, offset, val);
74*4882a593Smuzhiyun 	dev_vdbg(mc13xxx->dev, "[0x%02x] -> 0x%06x\n", offset, *val);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return ret;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_reg_read);
79*4882a593Smuzhiyun 
mc13xxx_reg_write(struct mc13xxx * mc13xxx,unsigned int offset,u32 val)80*4882a593Smuzhiyun int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (val >= BIT(24))
85*4882a593Smuzhiyun 		return -EINVAL;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return regmap_write(mc13xxx->regmap, offset, val);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_reg_write);
90*4882a593Smuzhiyun 
mc13xxx_reg_rmw(struct mc13xxx * mc13xxx,unsigned int offset,u32 mask,u32 val)91*4882a593Smuzhiyun int mc13xxx_reg_rmw(struct mc13xxx *mc13xxx, unsigned int offset,
92*4882a593Smuzhiyun 		u32 mask, u32 val)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	BUG_ON(val & ~mask);
95*4882a593Smuzhiyun 	dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x (mask: 0x%06x)\n",
96*4882a593Smuzhiyun 			offset, val, mask);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	return regmap_update_bits(mc13xxx->regmap, offset, mask, val);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_reg_rmw);
101*4882a593Smuzhiyun 
mc13xxx_irq_mask(struct mc13xxx * mc13xxx,int irq)102*4882a593Smuzhiyun int mc13xxx_irq_mask(struct mc13xxx *mc13xxx, int irq)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	disable_irq_nosync(virq);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_irq_mask);
111*4882a593Smuzhiyun 
mc13xxx_irq_unmask(struct mc13xxx * mc13xxx,int irq)112*4882a593Smuzhiyun int mc13xxx_irq_unmask(struct mc13xxx *mc13xxx, int irq)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	enable_irq(virq);
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	return 0;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_irq_unmask);
121*4882a593Smuzhiyun 
mc13xxx_irq_status(struct mc13xxx * mc13xxx,int irq,int * enabled,int * pending)122*4882a593Smuzhiyun int mc13xxx_irq_status(struct mc13xxx *mc13xxx, int irq,
123*4882a593Smuzhiyun 		int *enabled, int *pending)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	int ret;
126*4882a593Smuzhiyun 	unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
127*4882a593Smuzhiyun 	unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
128*4882a593Smuzhiyun 	u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	if (irq < 0 || irq >= ARRAY_SIZE(mc13xxx->irqs))
131*4882a593Smuzhiyun 		return -EINVAL;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	if (enabled) {
134*4882a593Smuzhiyun 		u32 mask;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 		ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
137*4882a593Smuzhiyun 		if (ret)
138*4882a593Smuzhiyun 			return ret;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		*enabled = mask & irqbit;
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	if (pending) {
144*4882a593Smuzhiyun 		u32 stat;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 		ret = mc13xxx_reg_read(mc13xxx, offstat, &stat);
147*4882a593Smuzhiyun 		if (ret)
148*4882a593Smuzhiyun 			return ret;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 		*pending = stat & irqbit;
151*4882a593Smuzhiyun 	}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_irq_status);
156*4882a593Smuzhiyun 
mc13xxx_irq_request(struct mc13xxx * mc13xxx,int irq,irq_handler_t handler,const char * name,void * dev)157*4882a593Smuzhiyun int mc13xxx_irq_request(struct mc13xxx *mc13xxx, int irq,
158*4882a593Smuzhiyun 		irq_handler_t handler, const char *name, void *dev)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	return devm_request_threaded_irq(mc13xxx->dev, virq, NULL, handler,
163*4882a593Smuzhiyun 					 IRQF_ONESHOT, name, dev);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_irq_request);
166*4882a593Smuzhiyun 
mc13xxx_irq_free(struct mc13xxx * mc13xxx,int irq,void * dev)167*4882a593Smuzhiyun int mc13xxx_irq_free(struct mc13xxx *mc13xxx, int irq, void *dev)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	devm_free_irq(mc13xxx->dev, virq, dev);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_irq_free);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun #define maskval(reg, mask)	(((reg) & (mask)) >> __ffs(mask))
mc13xxx_print_revision(struct mc13xxx * mc13xxx,u32 revision)178*4882a593Smuzhiyun static void mc13xxx_print_revision(struct mc13xxx *mc13xxx, u32 revision)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	dev_info(mc13xxx->dev, "%s: rev: %d.%d, "
181*4882a593Smuzhiyun 			"fin: %d, fab: %d, icid: %d/%d\n",
182*4882a593Smuzhiyun 			mc13xxx->variant->name,
183*4882a593Smuzhiyun 			maskval(revision, MC13XXX_REVISION_REVFULL),
184*4882a593Smuzhiyun 			maskval(revision, MC13XXX_REVISION_REVMETAL),
185*4882a593Smuzhiyun 			maskval(revision, MC13XXX_REVISION_FIN),
186*4882a593Smuzhiyun 			maskval(revision, MC13XXX_REVISION_FAB),
187*4882a593Smuzhiyun 			maskval(revision, MC13XXX_REVISION_ICID),
188*4882a593Smuzhiyun 			maskval(revision, MC13XXX_REVISION_ICIDCODE));
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
mc34708_print_revision(struct mc13xxx * mc13xxx,u32 revision)191*4882a593Smuzhiyun static void mc34708_print_revision(struct mc13xxx *mc13xxx, u32 revision)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	dev_info(mc13xxx->dev, "%s: rev %d.%d, fin: %d, fab: %d\n",
194*4882a593Smuzhiyun 			mc13xxx->variant->name,
195*4882a593Smuzhiyun 			maskval(revision, MC34708_REVISION_REVFULL),
196*4882a593Smuzhiyun 			maskval(revision, MC34708_REVISION_REVMETAL),
197*4882a593Smuzhiyun 			maskval(revision, MC34708_REVISION_FIN),
198*4882a593Smuzhiyun 			maskval(revision, MC34708_REVISION_FAB));
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun /* These are only exported for mc13xxx-i2c and mc13xxx-spi */
202*4882a593Smuzhiyun struct mc13xxx_variant mc13xxx_variant_mc13783 = {
203*4882a593Smuzhiyun 	.name = "mc13783",
204*4882a593Smuzhiyun 	.print_revision = mc13xxx_print_revision,
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mc13xxx_variant_mc13783);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun struct mc13xxx_variant mc13xxx_variant_mc13892 = {
209*4882a593Smuzhiyun 	.name = "mc13892",
210*4882a593Smuzhiyun 	.print_revision = mc13xxx_print_revision,
211*4882a593Smuzhiyun };
212*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mc13xxx_variant_mc13892);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun struct mc13xxx_variant mc13xxx_variant_mc34708 = {
215*4882a593Smuzhiyun 	.name = "mc34708",
216*4882a593Smuzhiyun 	.print_revision = mc34708_print_revision,
217*4882a593Smuzhiyun };
218*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mc13xxx_variant_mc34708);
219*4882a593Smuzhiyun 
mc13xxx_get_chipname(struct mc13xxx * mc13xxx)220*4882a593Smuzhiyun static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	return mc13xxx->variant->name;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
mc13xxx_get_flags(struct mc13xxx * mc13xxx)225*4882a593Smuzhiyun int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	return mc13xxx->flags;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun EXPORT_SYMBOL(mc13xxx_get_flags);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun #define MC13XXX_ADC1_CHAN0_SHIFT	5
232*4882a593Smuzhiyun #define MC13XXX_ADC1_CHAN1_SHIFT	8
233*4882a593Smuzhiyun #define MC13783_ADC1_ATO_SHIFT		11
234*4882a593Smuzhiyun #define MC13783_ADC1_ATOX		(1 << 19)
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun struct mc13xxx_adcdone_data {
237*4882a593Smuzhiyun 	struct mc13xxx *mc13xxx;
238*4882a593Smuzhiyun 	struct completion done;
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun 
mc13xxx_handler_adcdone(int irq,void * data)241*4882a593Smuzhiyun static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct mc13xxx_adcdone_data *adcdone_data = data;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	complete_all(&adcdone_data->done);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	return IRQ_HANDLED;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun #define MC13XXX_ADC_WORKING (1 << 0)
251*4882a593Smuzhiyun 
mc13xxx_adc_do_conversion(struct mc13xxx * mc13xxx,unsigned int mode,unsigned int channel,u8 ato,bool atox,unsigned int * sample)252*4882a593Smuzhiyun int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
253*4882a593Smuzhiyun 		unsigned int channel, u8 ato, bool atox,
254*4882a593Smuzhiyun 		unsigned int *sample)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	u32 adc0, adc1, old_adc0;
257*4882a593Smuzhiyun 	int i, ret;
258*4882a593Smuzhiyun 	struct mc13xxx_adcdone_data adcdone_data = {
259*4882a593Smuzhiyun 		.mc13xxx = mc13xxx,
260*4882a593Smuzhiyun 	};
261*4882a593Smuzhiyun 	init_completion(&adcdone_data.done);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	dev_dbg(mc13xxx->dev, "%s\n", __func__);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	mc13xxx_lock(mc13xxx);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	if (mc13xxx->adcflags & MC13XXX_ADC_WORKING) {
268*4882a593Smuzhiyun 		ret = -EBUSY;
269*4882a593Smuzhiyun 		goto out;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
275*4882a593Smuzhiyun 	if (ret)
276*4882a593Smuzhiyun 		goto out;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
279*4882a593Smuzhiyun 	       MC13XXX_ADC0_CHRGRAWDIV;
280*4882a593Smuzhiyun 	adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	/*
283*4882a593Smuzhiyun 	 * Channels mapped through ADIN7:
284*4882a593Smuzhiyun 	 * 7  - General purpose ADIN7
285*4882a593Smuzhiyun 	 * 16 - UID
286*4882a593Smuzhiyun 	 * 17 - Die temperature
287*4882a593Smuzhiyun 	 */
288*4882a593Smuzhiyun 	if (channel > 7 && channel < 16) {
289*4882a593Smuzhiyun 		adc1 |= MC13XXX_ADC1_ADSEL;
290*4882a593Smuzhiyun 	} else if (channel == 16) {
291*4882a593Smuzhiyun 		adc0 |= MC13XXX_ADC0_ADIN7SEL_UID;
292*4882a593Smuzhiyun 		channel = 7;
293*4882a593Smuzhiyun 	} else if (channel == 17) {
294*4882a593Smuzhiyun 		adc0 |= MC13XXX_ADC0_ADIN7SEL_DIE;
295*4882a593Smuzhiyun 		channel = 7;
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	switch (mode) {
299*4882a593Smuzhiyun 	case MC13XXX_ADC_MODE_TS:
300*4882a593Smuzhiyun 		adc0 |= MC13XXX_ADC0_ADREFEN | MC13XXX_ADC0_TSMOD0 |
301*4882a593Smuzhiyun 			MC13XXX_ADC0_TSMOD1;
302*4882a593Smuzhiyun 		adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
303*4882a593Smuzhiyun 		break;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	case MC13XXX_ADC_MODE_SINGLE_CHAN:
306*4882a593Smuzhiyun 		adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
307*4882a593Smuzhiyun 		adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
308*4882a593Smuzhiyun 		adc1 |= MC13XXX_ADC1_RAND;
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	case MC13XXX_ADC_MODE_MULT_CHAN:
312*4882a593Smuzhiyun 		adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
313*4882a593Smuzhiyun 		adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
314*4882a593Smuzhiyun 		break;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	default:
317*4882a593Smuzhiyun 		mc13xxx_unlock(mc13xxx);
318*4882a593Smuzhiyun 		return -EINVAL;
319*4882a593Smuzhiyun 	}
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	adc1 |= ato << MC13783_ADC1_ATO_SHIFT;
322*4882a593Smuzhiyun 	if (atox)
323*4882a593Smuzhiyun 		adc1 |= MC13783_ADC1_ATOX;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__);
326*4882a593Smuzhiyun 	ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
327*4882a593Smuzhiyun 			mc13xxx_handler_adcdone, __func__, &adcdone_data);
328*4882a593Smuzhiyun 	if (ret)
329*4882a593Smuzhiyun 		goto out;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
332*4882a593Smuzhiyun 	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	mc13xxx_unlock(mc13xxx);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ);
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (!ret)
339*4882a593Smuzhiyun 		ret = -ETIMEDOUT;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	mc13xxx_lock(mc13xxx);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_ADCDONE, &adcdone_data);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	if (ret > 0)
346*4882a593Smuzhiyun 		for (i = 0; i < 4; ++i) {
347*4882a593Smuzhiyun 			ret = mc13xxx_reg_read(mc13xxx,
348*4882a593Smuzhiyun 					MC13XXX_ADC2, &sample[i]);
349*4882a593Smuzhiyun 			if (ret)
350*4882a593Smuzhiyun 				break;
351*4882a593Smuzhiyun 		}
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	if (mode == MC13XXX_ADC_MODE_TS)
354*4882a593Smuzhiyun 		/* restore TSMOD */
355*4882a593Smuzhiyun 		mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, old_adc0);
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	mc13xxx->adcflags &= ~MC13XXX_ADC_WORKING;
358*4882a593Smuzhiyun out:
359*4882a593Smuzhiyun 	mc13xxx_unlock(mc13xxx);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	return ret;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mc13xxx_adc_do_conversion);
364*4882a593Smuzhiyun 
mc13xxx_add_subdevice_pdata(struct mc13xxx * mc13xxx,const char * format,void * pdata,size_t pdata_size)365*4882a593Smuzhiyun static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
366*4882a593Smuzhiyun 		const char *format, void *pdata, size_t pdata_size)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	char buf[30];
369*4882a593Smuzhiyun 	const char *name = mc13xxx_get_chipname(mc13xxx);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	struct mfd_cell cell = {
372*4882a593Smuzhiyun 		.platform_data = pdata,
373*4882a593Smuzhiyun 		.pdata_size = pdata_size,
374*4882a593Smuzhiyun 	};
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	/* there is no asnprintf in the kernel :-( */
377*4882a593Smuzhiyun 	if (snprintf(buf, sizeof(buf), format, name) > sizeof(buf))
378*4882a593Smuzhiyun 		return -E2BIG;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	cell.name = kmemdup(buf, strlen(buf) + 1, GFP_KERNEL);
381*4882a593Smuzhiyun 	if (!cell.name)
382*4882a593Smuzhiyun 		return -ENOMEM;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0,
385*4882a593Smuzhiyun 			       regmap_irq_get_domain(mc13xxx->irq_data));
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
mc13xxx_add_subdevice(struct mc13xxx * mc13xxx,const char * format)388*4882a593Smuzhiyun static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun #ifdef CONFIG_OF
mc13xxx_probe_flags_dt(struct mc13xxx * mc13xxx)394*4882a593Smuzhiyun static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	struct device_node *np = mc13xxx->dev->of_node;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	if (!np)
399*4882a593Smuzhiyun 		return -ENODEV;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	if (of_property_read_bool(np, "fsl,mc13xxx-uses-adc"))
402*4882a593Smuzhiyun 		mc13xxx->flags |= MC13XXX_USE_ADC;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (of_property_read_bool(np, "fsl,mc13xxx-uses-codec"))
405*4882a593Smuzhiyun 		mc13xxx->flags |= MC13XXX_USE_CODEC;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	if (of_property_read_bool(np, "fsl,mc13xxx-uses-rtc"))
408*4882a593Smuzhiyun 		mc13xxx->flags |= MC13XXX_USE_RTC;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	if (of_property_read_bool(np, "fsl,mc13xxx-uses-touch"))
411*4882a593Smuzhiyun 		mc13xxx->flags |= MC13XXX_USE_TOUCHSCREEN;
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	return 0;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun #else
mc13xxx_probe_flags_dt(struct mc13xxx * mc13xxx)416*4882a593Smuzhiyun static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	return -ENODEV;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun #endif
421*4882a593Smuzhiyun 
mc13xxx_common_init(struct device * dev)422*4882a593Smuzhiyun int mc13xxx_common_init(struct device *dev)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun 	struct mc13xxx_platform_data *pdata = dev_get_platdata(dev);
425*4882a593Smuzhiyun 	struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
426*4882a593Smuzhiyun 	u32 revision;
427*4882a593Smuzhiyun 	int i, ret;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	mc13xxx->dev = dev;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision);
432*4882a593Smuzhiyun 	if (ret)
433*4882a593Smuzhiyun 		return ret;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	mc13xxx->variant->print_revision(mc13xxx, revision);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	ret = mc13xxx_reg_rmw(mc13xxx, MC13XXX_PWRCTRL,
438*4882a593Smuzhiyun 			MC13XXX_PWRCTRL_WDIRESET, MC13XXX_PWRCTRL_WDIRESET);
439*4882a593Smuzhiyun 	if (ret)
440*4882a593Smuzhiyun 		return ret;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(mc13xxx->irqs); i++) {
443*4882a593Smuzhiyun 		mc13xxx->irqs[i].reg_offset = i / MC13XXX_IRQ_PER_REG;
444*4882a593Smuzhiyun 		mc13xxx->irqs[i].mask = BIT(i % MC13XXX_IRQ_PER_REG);
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	mc13xxx->irq_chip.name = dev_name(dev);
448*4882a593Smuzhiyun 	mc13xxx->irq_chip.status_base = MC13XXX_IRQSTAT0;
449*4882a593Smuzhiyun 	mc13xxx->irq_chip.mask_base = MC13XXX_IRQMASK0;
450*4882a593Smuzhiyun 	mc13xxx->irq_chip.ack_base = MC13XXX_IRQSTAT0;
451*4882a593Smuzhiyun 	mc13xxx->irq_chip.irq_reg_stride = MC13XXX_IRQSTAT1 - MC13XXX_IRQSTAT0;
452*4882a593Smuzhiyun 	mc13xxx->irq_chip.init_ack_masked = true;
453*4882a593Smuzhiyun 	mc13xxx->irq_chip.use_ack = true;
454*4882a593Smuzhiyun 	mc13xxx->irq_chip.num_regs = MC13XXX_IRQ_REG_CNT;
455*4882a593Smuzhiyun 	mc13xxx->irq_chip.irqs = mc13xxx->irqs;
456*4882a593Smuzhiyun 	mc13xxx->irq_chip.num_irqs = ARRAY_SIZE(mc13xxx->irqs);
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq, IRQF_ONESHOT,
459*4882a593Smuzhiyun 				  0, &mc13xxx->irq_chip, &mc13xxx->irq_data);
460*4882a593Smuzhiyun 	if (ret)
461*4882a593Smuzhiyun 		return ret;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	mutex_init(&mc13xxx->lock);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
466*4882a593Smuzhiyun 		mc13xxx->flags = pdata->flags;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	if (pdata) {
469*4882a593Smuzhiyun 		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
470*4882a593Smuzhiyun 			&pdata->regulators, sizeof(pdata->regulators));
471*4882a593Smuzhiyun 		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
472*4882a593Smuzhiyun 				pdata->leds, sizeof(*pdata->leds));
473*4882a593Smuzhiyun 		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
474*4882a593Smuzhiyun 				pdata->buttons, sizeof(*pdata->buttons));
475*4882a593Smuzhiyun 		if (mc13xxx->flags & MC13XXX_USE_CODEC)
476*4882a593Smuzhiyun 			mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
477*4882a593Smuzhiyun 				pdata->codec, sizeof(*pdata->codec));
478*4882a593Smuzhiyun 		if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
479*4882a593Smuzhiyun 			mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts",
480*4882a593Smuzhiyun 				&pdata->touch, sizeof(pdata->touch));
481*4882a593Smuzhiyun 	} else {
482*4882a593Smuzhiyun 		mc13xxx_add_subdevice(mc13xxx, "%s-regulator");
483*4882a593Smuzhiyun 		mc13xxx_add_subdevice(mc13xxx, "%s-led");
484*4882a593Smuzhiyun 		mc13xxx_add_subdevice(mc13xxx, "%s-pwrbutton");
485*4882a593Smuzhiyun 		if (mc13xxx->flags & MC13XXX_USE_CODEC)
486*4882a593Smuzhiyun 			mc13xxx_add_subdevice(mc13xxx, "%s-codec");
487*4882a593Smuzhiyun 		if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
488*4882a593Smuzhiyun 			mc13xxx_add_subdevice(mc13xxx, "%s-ts");
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	if (mc13xxx->flags & MC13XXX_USE_ADC)
492*4882a593Smuzhiyun 		mc13xxx_add_subdevice(mc13xxx, "%s-adc");
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	if (mc13xxx->flags & MC13XXX_USE_RTC)
495*4882a593Smuzhiyun 		mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	return 0;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mc13xxx_common_init);
500*4882a593Smuzhiyun 
mc13xxx_common_exit(struct device * dev)501*4882a593Smuzhiyun int mc13xxx_common_exit(struct device *dev)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	mfd_remove_devices(dev);
506*4882a593Smuzhiyun 	regmap_del_irq_chip(mc13xxx->irq, mc13xxx->irq_data);
507*4882a593Smuzhiyun 	mutex_destroy(&mc13xxx->lock);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	return 0;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mc13xxx_common_exit);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC");
514*4882a593Smuzhiyun MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
515*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
516