1 /*
2  * max8997-muic.c - MAX8997 muic driver for the Maxim 8997
3  *
4  *  Copyright (C) 2011 Samsung Electrnoics
5  *  Donggeun Kim <dg77.kim@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/i2c.h>
26 #include <linux/slab.h>
27 #include <linux/interrupt.h>
28 #include <linux/err.h>
29 #include <linux/platform_device.h>
30 #include <linux/kobject.h>
31 #include <linux/mfd/max8997.h>
32 #include <linux/mfd/max8997-private.h>
33 
34 /* MAX8997-MUIC STATUS1 register */
35 #define STATUS1_ADC_SHIFT		0
36 #define STATUS1_ADCLOW_SHIFT		5
37 #define STATUS1_ADCERR_SHIFT		6
38 #define STATUS1_ADC_MASK		(0x1f << STATUS1_ADC_SHIFT)
39 #define STATUS1_ADCLOW_MASK		(0x1 << STATUS1_ADCLOW_SHIFT)
40 #define STATUS1_ADCERR_MASK		(0x1 << STATUS1_ADCERR_SHIFT)
41 
42 /* MAX8997-MUIC STATUS2 register */
43 #define STATUS2_CHGTYP_SHIFT		0
44 #define STATUS2_CHGDETRUN_SHIFT		3
45 #define STATUS2_DCDTMR_SHIFT		4
46 #define STATUS2_DBCHG_SHIFT		5
47 #define STATUS2_VBVOLT_SHIFT		6
48 #define STATUS2_CHGTYP_MASK		(0x7 << STATUS2_CHGTYP_SHIFT)
49 #define STATUS2_CHGDETRUN_MASK		(0x1 << STATUS2_CHGDETRUN_SHIFT)
50 #define STATUS2_DCDTMR_MASK		(0x1 << STATUS2_DCDTMR_SHIFT)
51 #define STATUS2_DBCHG_MASK		(0x1 << STATUS2_DBCHG_SHIFT)
52 #define STATUS2_VBVOLT_MASK		(0x1 << STATUS2_VBVOLT_SHIFT)
53 
54 /* MAX8997-MUIC STATUS3 register */
55 #define STATUS3_OVP_SHIFT		2
56 #define STATUS3_OVP_MASK		(0x1 << STATUS3_OVP_SHIFT)
57 
58 /* MAX8997-MUIC CONTROL1 register */
59 #define COMN1SW_SHIFT			0
60 #define COMP2SW_SHIFT			3
61 #define COMN1SW_MASK			(0x7 << COMN1SW_SHIFT)
62 #define COMP2SW_MASK			(0x7 << COMP2SW_SHIFT)
63 #define SW_MASK				(COMP2SW_MASK | COMN1SW_MASK)
64 
65 #define MAX8997_SW_USB		((1 << COMP2SW_SHIFT) | (1 << COMN1SW_SHIFT))
66 #define MAX8997_SW_AUDIO	((2 << COMP2SW_SHIFT) | (2 << COMN1SW_SHIFT))
67 #define MAX8997_SW_UART		((3 << COMP2SW_SHIFT) | (3 << COMN1SW_SHIFT))
68 #define MAX8997_SW_OPEN		((0 << COMP2SW_SHIFT) | (0 << COMN1SW_SHIFT))
69 
70 #define	MAX8997_ADC_GROUND		0x00
71 #define	MAX8997_ADC_MHL			0x01
72 #define	MAX8997_ADC_JIG_USB_1		0x18
73 #define	MAX8997_ADC_JIG_USB_2		0x19
74 #define	MAX8997_ADC_DESKDOCK		0x1a
75 #define	MAX8997_ADC_JIG_UART		0x1c
76 #define	MAX8997_ADC_CARDOCK		0x1d
77 #define	MAX8997_ADC_OPEN		0x1f
78 
79 struct max8997_muic_irq {
80 	unsigned int irq;
81 	const char *name;
82 };
83 
84 static struct max8997_muic_irq muic_irqs[] = {
85 	{ MAX8997_MUICIRQ_ADCError, "muic-ADC_error" },
86 	{ MAX8997_MUICIRQ_ADCLow, "muic-ADC_low" },
87 	{ MAX8997_MUICIRQ_ADC, "muic-ADC" },
88 	{ MAX8997_MUICIRQ_VBVolt, "muic-VB_voltage" },
89 	{ MAX8997_MUICIRQ_DBChg, "muic-DB_charger" },
90 	{ MAX8997_MUICIRQ_DCDTmr, "muic-DCD_timer" },
91 	{ MAX8997_MUICIRQ_ChgDetRun, "muic-CDR_status" },
92 	{ MAX8997_MUICIRQ_ChgTyp, "muic-charger_type" },
93 	{ MAX8997_MUICIRQ_OVP, "muic-over_voltage" },
94 };
95 
96 struct max8997_muic_info {
97 	struct device *dev;
98 	struct max8997_dev *iodev;
99 	struct i2c_client *muic;
100 	struct max8997_muic_platform_data *muic_pdata;
101 
102 	int irq;
103 	struct work_struct irq_work;
104 
105 	enum max8997_muic_charger_type pre_charger_type;
106 	int pre_adc;
107 
108 	struct mutex mutex;
109 };
110 
max8997_muic_handle_usb(struct max8997_muic_info * info,enum max8997_muic_usb_type usb_type,bool attached)111 static int max8997_muic_handle_usb(struct max8997_muic_info *info,
112 			enum max8997_muic_usb_type usb_type, bool attached)
113 {
114 	struct max8997_muic_platform_data *mdata = info->muic_pdata;
115 	int ret = 0;
116 
117 	if (usb_type == MAX8997_USB_HOST) {
118 		/* switch to USB */
119 		ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
120 				attached ? MAX8997_SW_USB : MAX8997_SW_OPEN,
121 				SW_MASK);
122 		if (ret) {
123 			dev_err(info->dev, "failed to update muic register\n");
124 			goto out;
125 		}
126 	}
127 
128 	if (mdata->usb_callback)
129 		mdata->usb_callback(usb_type, attached);
130 out:
131 	return ret;
132 }
133 
max8997_muic_handle_mhl(struct max8997_muic_info * info,bool attached)134 static void max8997_muic_handle_mhl(struct max8997_muic_info *info,
135 			bool attached)
136 {
137 	struct max8997_muic_platform_data *mdata = info->muic_pdata;
138 
139 	if (mdata->mhl_callback)
140 		mdata->mhl_callback(attached);
141 }
142 
max8997_muic_handle_dock(struct max8997_muic_info * info,int adc,bool attached)143 static int max8997_muic_handle_dock(struct max8997_muic_info *info,
144 			int adc, bool attached)
145 {
146 	struct max8997_muic_platform_data *mdata = info->muic_pdata;
147 	int ret = 0;
148 
149 	/* switch to AUDIO */
150 	ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
151 				attached ? MAX8997_SW_AUDIO : MAX8997_SW_OPEN,
152 				SW_MASK);
153 	if (ret) {
154 		dev_err(info->dev, "failed to update muic register\n");
155 		goto out;
156 	}
157 
158 	switch (adc) {
159 	case MAX8997_ADC_DESKDOCK:
160 		if (mdata->deskdock_callback)
161 			mdata->deskdock_callback(attached);
162 		break;
163 	case MAX8997_ADC_CARDOCK:
164 		if (mdata->cardock_callback)
165 			mdata->cardock_callback(attached);
166 		break;
167 	default:
168 		break;
169 	}
170 out:
171 	return ret;
172 }
173 
max8997_muic_handle_jig_uart(struct max8997_muic_info * info,bool attached)174 static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
175 			bool attached)
176 {
177 	struct max8997_muic_platform_data *mdata = info->muic_pdata;
178 	int ret = 0;
179 
180 	/* switch to UART */
181 	ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
182 				attached ? MAX8997_SW_UART : MAX8997_SW_OPEN,
183 				SW_MASK);
184 	if (ret) {
185 		dev_err(info->dev, "failed to update muic register\n");
186 		goto out;
187 	}
188 
189 	if (mdata->uart_callback)
190 		mdata->uart_callback(attached);
191 out:
192 	return ret;
193 }
194 
max8997_muic_handle_adc_detach(struct max8997_muic_info * info)195 static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info)
196 {
197 	int ret = 0;
198 
199 	switch (info->pre_adc) {
200 	case MAX8997_ADC_GROUND:
201 		ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false);
202 		break;
203 	case MAX8997_ADC_MHL:
204 		max8997_muic_handle_mhl(info, false);
205 		break;
206 	case MAX8997_ADC_JIG_USB_1:
207 	case MAX8997_ADC_JIG_USB_2:
208 		ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, false);
209 		break;
210 	case MAX8997_ADC_DESKDOCK:
211 	case MAX8997_ADC_CARDOCK:
212 		ret = max8997_muic_handle_dock(info, info->pre_adc, false);
213 		break;
214 	case MAX8997_ADC_JIG_UART:
215 		ret = max8997_muic_handle_jig_uart(info, false);
216 		break;
217 	default:
218 		break;
219 	}
220 
221 	return ret;
222 }
223 
max8997_muic_handle_adc(struct max8997_muic_info * info,int adc)224 static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc)
225 {
226 	int ret = 0;
227 
228 	switch (adc) {
229 	case MAX8997_ADC_GROUND:
230 		ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true);
231 		break;
232 	case MAX8997_ADC_MHL:
233 		max8997_muic_handle_mhl(info, true);
234 		break;
235 	case MAX8997_ADC_JIG_USB_1:
236 	case MAX8997_ADC_JIG_USB_2:
237 		ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, true);
238 		break;
239 	case MAX8997_ADC_DESKDOCK:
240 	case MAX8997_ADC_CARDOCK:
241 		ret = max8997_muic_handle_dock(info, adc, true);
242 		break;
243 	case MAX8997_ADC_JIG_UART:
244 		ret = max8997_muic_handle_jig_uart(info, true);
245 		break;
246 	case MAX8997_ADC_OPEN:
247 		ret = max8997_muic_handle_adc_detach(info);
248 		break;
249 	default:
250 		break;
251 	}
252 
253 	info->pre_adc = adc;
254 
255 	return ret;
256 }
257 
max8997_muic_handle_charger_type(struct max8997_muic_info * info,enum max8997_muic_charger_type charger_type)258 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
259 				enum max8997_muic_charger_type charger_type)
260 {
261 	struct max8997_muic_platform_data *mdata = info->muic_pdata;
262 	u8 adc;
263 	int ret;
264 
265 	ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_STATUS1, &adc);
266 	if (ret) {
267 		dev_err(info->dev, "failed to read muic register\n");
268 		goto out;
269 	}
270 
271 	switch (charger_type) {
272 	case MAX8997_CHARGER_TYPE_NONE:
273 		if (mdata->charger_callback)
274 			mdata->charger_callback(false, charger_type);
275 		if (info->pre_charger_type == MAX8997_CHARGER_TYPE_USB) {
276 			max8997_muic_handle_usb(info,
277 					MAX8997_USB_DEVICE, false);
278 		}
279 		break;
280 	case MAX8997_CHARGER_TYPE_USB:
281 		if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) {
282 			max8997_muic_handle_usb(info,
283 					MAX8997_USB_DEVICE, true);
284 		}
285 		if (mdata->charger_callback)
286 			mdata->charger_callback(true, charger_type);
287 		break;
288 	case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
289 	case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
290 	case MAX8997_CHARGER_TYPE_500MA:
291 	case MAX8997_CHARGER_TYPE_1A:
292 		if (mdata->charger_callback)
293 			mdata->charger_callback(true, charger_type);
294 		break;
295 	default:
296 		break;
297 	}
298 
299 	info->pre_charger_type = charger_type;
300 out:
301 	return ret;
302 }
303 
max8997_muic_irq_work(struct work_struct * work)304 static void max8997_muic_irq_work(struct work_struct *work)
305 {
306 	struct max8997_muic_info *info = container_of(work,
307 			struct max8997_muic_info, irq_work);
308 	struct max8997_platform_data *pdata =
309 				dev_get_platdata(info->iodev->dev);
310 	u8 status[3];
311 	u8 adc, chg_type;
312 
313 	int irq_type = info->irq - pdata->irq_base;
314 	int ret;
315 
316 	mutex_lock(&info->mutex);
317 
318 	ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
319 				3, status);
320 	if (ret) {
321 		dev_err(info->dev, "failed to read muic register\n");
322 		mutex_unlock(&info->mutex);
323 		return;
324 	}
325 
326 	dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__,
327 			status[0], status[1]);
328 
329 	switch (irq_type) {
330 	case MAX8997_MUICIRQ_ADC:
331 		adc = status[0] & STATUS1_ADC_MASK;
332 		adc >>= STATUS1_ADC_SHIFT;
333 
334 		max8997_muic_handle_adc(info, adc);
335 		break;
336 	case MAX8997_MUICIRQ_ChgTyp:
337 		chg_type = status[1] & STATUS2_CHGTYP_MASK;
338 		chg_type >>= STATUS2_CHGTYP_SHIFT;
339 
340 		max8997_muic_handle_charger_type(info, chg_type);
341 		break;
342 	default:
343 		dev_info(info->dev, "misc interrupt: %s occurred\n",
344 			 muic_irqs[irq_type].name);
345 		break;
346 	}
347 
348 	mutex_unlock(&info->mutex);
349 
350 	return;
351 }
352 
max8997_muic_irq_handler(int irq,void * data)353 static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
354 {
355 	struct max8997_muic_info *info = data;
356 
357 	dev_dbg(info->dev, "irq:%d\n", irq);
358 	info->irq = irq;
359 
360 	schedule_work(&info->irq_work);
361 
362 	return IRQ_HANDLED;
363 }
364 
max8997_muic_detect_dev(struct max8997_muic_info * info)365 static void max8997_muic_detect_dev(struct max8997_muic_info *info)
366 {
367 	int ret;
368 	u8 status[2], adc, chg_type;
369 
370 	ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
371 				2, status);
372 	if (ret) {
373 		dev_err(info->dev, "failed to read muic register\n");
374 		return;
375 	}
376 
377 	dev_info(info->dev, "STATUS1:0x%x, STATUS2:0x%x\n",
378 			status[0], status[1]);
379 
380 	adc = status[0] & STATUS1_ADC_MASK;
381 	adc >>= STATUS1_ADC_SHIFT;
382 
383 	chg_type = status[1] & STATUS2_CHGTYP_MASK;
384 	chg_type >>= STATUS2_CHGTYP_SHIFT;
385 
386 	max8997_muic_handle_adc(info, adc);
387 	max8997_muic_handle_charger_type(info, chg_type);
388 }
389 
max8997_initialize_device(struct max8997_muic_info * info)390 static void max8997_initialize_device(struct max8997_muic_info *info)
391 {
392 	struct max8997_muic_platform_data *mdata = info->muic_pdata;
393 	int i;
394 
395 	for (i = 0; i < mdata->num_init_data; i++) {
396 		max8997_write_reg(info->muic, mdata->init_data[i].addr,
397 				mdata->init_data[i].data);
398 	}
399 }
400 
max8997_muic_probe(struct platform_device * pdev)401 static int __devinit max8997_muic_probe(struct platform_device *pdev)
402 {
403 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
404 	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
405 	struct max8997_muic_info *info;
406 	int ret, i;
407 
408 	info = kzalloc(sizeof(struct max8997_muic_info), GFP_KERNEL);
409 	if (!info) {
410 		dev_err(&pdev->dev, "failed to allocate memory\n");
411 		ret = -ENOMEM;
412 		goto err_kfree;
413 	}
414 
415 	if (!pdata->muic_pdata) {
416 		dev_err(&pdev->dev, "failed to get platform_data\n");
417 		ret = -EINVAL;
418 		goto err_pdata;
419 	}
420 	info->muic_pdata = pdata->muic_pdata;
421 
422 	info->dev = &pdev->dev;
423 	info->iodev = iodev;
424 	info->muic = iodev->muic;
425 
426 	platform_set_drvdata(pdev, info);
427 	mutex_init(&info->mutex);
428 
429 	INIT_WORK(&info->irq_work, max8997_muic_irq_work);
430 
431 	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
432 		struct max8997_muic_irq *muic_irq = &muic_irqs[i];
433 
434 		ret = request_threaded_irq(pdata->irq_base + muic_irq->irq,
435 				NULL, max8997_muic_irq_handler,
436 				0, muic_irq->name,
437 				info);
438 		if (ret) {
439 			dev_err(&pdev->dev,
440 				"failed: irq request (IRQ: %d,"
441 				" error :%d)\n",
442 				muic_irq->irq, ret);
443 
444 			for (i = i - 1; i >= 0; i--)
445 				free_irq(muic_irq->irq, info);
446 
447 			goto err_irq;
448 		}
449 	}
450 
451 	/* Initialize registers according to platform data */
452 	max8997_initialize_device(info);
453 
454 	/* Initial device detection */
455 	max8997_muic_detect_dev(info);
456 
457 	return ret;
458 
459 err_irq:
460 err_pdata:
461 	kfree(info);
462 err_kfree:
463 	return ret;
464 }
465 
max8997_muic_remove(struct platform_device * pdev)466 static int __devexit max8997_muic_remove(struct platform_device *pdev)
467 {
468 	struct max8997_muic_info *info = platform_get_drvdata(pdev);
469 	struct max8997_platform_data *pdata =
470 				dev_get_platdata(info->iodev->dev);
471 	int i;
472 
473 	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
474 		free_irq(pdata->irq_base + muic_irqs[i].irq, info);
475 	cancel_work_sync(&info->irq_work);
476 
477 	kfree(info);
478 
479 	return 0;
480 }
481 
482 static struct platform_driver max8997_muic_driver = {
483 	.driver		= {
484 		.name	= "max8997-muic",
485 		.owner	= THIS_MODULE,
486 	},
487 	.probe		= max8997_muic_probe,
488 	.remove		= __devexit_p(max8997_muic_remove),
489 };
490 
491 module_platform_driver(max8997_muic_driver);
492 
493 MODULE_DESCRIPTION("Maxim MAX8997 MUIC driver");
494 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
495 MODULE_LICENSE("GPL");
496