1/*
2 * extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches
3 *
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute  it and/or modify it
8 * under  the terms of  the GNU General  Public License as published by the
9 * Free Software Foundation;  either version 2 of the  License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/err.h>
14#include <linux/i2c.h>
15#include <linux/interrupt.h>
16#include <linux/irqdomain.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21#include <linux/slab.h>
22#include <linux/extcon.h>
23
24#include "extcon-sm5502.h"
25
26#define	DELAY_MS_DEFAULT		17000	/* unit: millisecond */
27
28struct muic_irq {
29	unsigned int irq;
30	const char *name;
31	unsigned int virq;
32};
33
34struct reg_data {
35	u8 reg;
36	unsigned int val;
37	bool invert;
38};
39
40struct sm5502_muic_info {
41	struct device *dev;
42	struct extcon_dev *edev;
43
44	struct i2c_client *i2c;
45	struct regmap *regmap;
46
47	struct regmap_irq_chip_data *irq_data;
48	struct muic_irq *muic_irqs;
49	unsigned int num_muic_irqs;
50	int irq;
51	bool irq_attach;
52	bool irq_detach;
53	struct work_struct irq_work;
54
55	struct reg_data *reg_data;
56	unsigned int num_reg_data;
57
58	struct mutex mutex;
59
60	/*
61	 * Use delayed workqueue to detect cable state and then
62	 * notify cable state to notifiee/platform through uevent.
63	 * After completing the booting of platform, the extcon provider
64	 * driver should notify cable state to upper layer.
65	 */
66	struct delayed_work wq_detcable;
67};
68
69/* Default value of SM5502 register to bring up MUIC device. */
70static struct reg_data sm5502_reg_data[] = {
71	{
72		.reg = SM5502_REG_CONTROL,
73		.val = SM5502_REG_CONTROL_MASK_INT_MASK,
74		.invert = false,
75	}, {
76		.reg = SM5502_REG_INTMASK1,
77		.val = SM5502_REG_INTM1_KP_MASK
78			| SM5502_REG_INTM1_LKP_MASK
79			| SM5502_REG_INTM1_LKR_MASK,
80		.invert = true,
81	}, {
82		.reg = SM5502_REG_INTMASK2,
83		.val = SM5502_REG_INTM2_VBUS_DET_MASK
84			| SM5502_REG_INTM2_REV_ACCE_MASK
85			| SM5502_REG_INTM2_ADC_CHG_MASK
86			| SM5502_REG_INTM2_STUCK_KEY_MASK
87			| SM5502_REG_INTM2_STUCK_KEY_RCV_MASK
88			| SM5502_REG_INTM2_MHL_MASK,
89		.invert = true,
90	},
91	{ }
92};
93
94/* List of detectable cables */
95enum {
96	EXTCON_CABLE_USB = 0,
97	EXTCON_CABLE_USB_HOST,
98	EXTCON_CABLE_TA,
99
100	EXTCON_CABLE_END,
101};
102
103static const char *sm5502_extcon_cable[] = {
104	[EXTCON_CABLE_USB]	= "USB",
105	[EXTCON_CABLE_USB_HOST]	= "USB-Host",
106	[EXTCON_CABLE_TA]	= "TA",
107	NULL,
108};
109
110/* Define supported accessory type */
111enum sm5502_muic_acc_type {
112	SM5502_MUIC_ADC_GROUND = 0x0,
113	SM5502_MUIC_ADC_SEND_END_BUTTON,
114	SM5502_MUIC_ADC_REMOTE_S1_BUTTON,
115	SM5502_MUIC_ADC_REMOTE_S2_BUTTON,
116	SM5502_MUIC_ADC_REMOTE_S3_BUTTON,
117	SM5502_MUIC_ADC_REMOTE_S4_BUTTON,
118	SM5502_MUIC_ADC_REMOTE_S5_BUTTON,
119	SM5502_MUIC_ADC_REMOTE_S6_BUTTON,
120	SM5502_MUIC_ADC_REMOTE_S7_BUTTON,
121	SM5502_MUIC_ADC_REMOTE_S8_BUTTON,
122	SM5502_MUIC_ADC_REMOTE_S9_BUTTON,
123	SM5502_MUIC_ADC_REMOTE_S10_BUTTON,
124	SM5502_MUIC_ADC_REMOTE_S11_BUTTON,
125	SM5502_MUIC_ADC_REMOTE_S12_BUTTON,
126	SM5502_MUIC_ADC_RESERVED_ACC_1,
127	SM5502_MUIC_ADC_RESERVED_ACC_2,
128	SM5502_MUIC_ADC_RESERVED_ACC_3,
129	SM5502_MUIC_ADC_RESERVED_ACC_4,
130	SM5502_MUIC_ADC_RESERVED_ACC_5,
131	SM5502_MUIC_ADC_AUDIO_TYPE2,
132	SM5502_MUIC_ADC_PHONE_POWERED_DEV,
133	SM5502_MUIC_ADC_TTY_CONVERTER,
134	SM5502_MUIC_ADC_UART_CABLE,
135	SM5502_MUIC_ADC_TYPE1_CHARGER,
136	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB,
137	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB,
138	SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE,
139	SM5502_MUIC_ADC_TYPE2_CHARGER,
140	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART,
141	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART,
142	SM5502_MUIC_ADC_AUDIO_TYPE1,
143	SM5502_MUIC_ADC_OPEN = 0x1f,
144
145	/* The below accessories have same ADC value (0x1f or 0x1e).
146	   So, Device type1 is used to separate specific accessory. */
147							/* |---------|--ADC| */
148							/* |    [7:5]|[4:0]| */
149	SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e,	/* |      001|11110| */
150	SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e,	/* |      010|11110| */
151							/* |Dev Type1|--ADC| */
152	SM5502_MUIC_ADC_OPEN_USB = 0x5f,		/* |      010|11111| */
153	SM5502_MUIC_ADC_OPEN_TA = 0xdf,			/* |      110|11111| */
154	SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff,		/* |      111|11111| */
155};
156
157/* List of supported interrupt for SM5502 */
158static struct muic_irq sm5502_muic_irqs[] = {
159	{ SM5502_IRQ_INT1_ATTACH,	"muic-attach" },
160	{ SM5502_IRQ_INT1_DETACH,	"muic-detach" },
161	{ SM5502_IRQ_INT1_KP,		"muic-kp" },
162	{ SM5502_IRQ_INT1_LKP,		"muic-lkp" },
163	{ SM5502_IRQ_INT1_LKR,		"muic-lkr" },
164	{ SM5502_IRQ_INT1_OVP_EVENT,	"muic-ovp-event" },
165	{ SM5502_IRQ_INT1_OCP_EVENT,	"muic-ocp-event" },
166	{ SM5502_IRQ_INT1_OVP_OCP_DIS,	"muic-ovp-ocp-dis" },
167	{ SM5502_IRQ_INT2_VBUS_DET,	"muic-vbus-det" },
168	{ SM5502_IRQ_INT2_REV_ACCE,	"muic-rev-acce" },
169	{ SM5502_IRQ_INT2_ADC_CHG,	"muic-adc-chg" },
170	{ SM5502_IRQ_INT2_STUCK_KEY,	"muic-stuck-key" },
171	{ SM5502_IRQ_INT2_STUCK_KEY_RCV, "muic-stuck-key-rcv" },
172	{ SM5502_IRQ_INT2_MHL,		"muic-mhl" },
173};
174
175/* Define interrupt list of SM5502 to register regmap_irq */
176static const struct regmap_irq sm5502_irqs[] = {
177	/* INT1 interrupts */
178	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_ATTACH_MASK, },
179	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_DETACH_MASK, },
180	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_KP_MASK, },
181	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKP_MASK, },
182	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKR_MASK, },
183	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_EVENT_MASK, },
184	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OCP_EVENT_MASK, },
185	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_OCP_DIS_MASK, },
186
187	/* INT2 interrupts */
188	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_VBUS_DET_MASK,},
189	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_REV_ACCE_MASK, },
190	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_ADC_CHG_MASK, },
191	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_MASK, },
192	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK, },
193	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_MHL_MASK, },
194};
195
196static const struct regmap_irq_chip sm5502_muic_irq_chip = {
197	.name			= "sm5502",
198	.status_base		= SM5502_REG_INT1,
199	.mask_base		= SM5502_REG_INTMASK1,
200	.mask_invert		= false,
201	.num_regs		= 2,
202	.irqs			= sm5502_irqs,
203	.num_irqs		= ARRAY_SIZE(sm5502_irqs),
204};
205
206/* Define regmap configuration of SM5502 for I2C communication  */
207static bool sm5502_muic_volatile_reg(struct device *dev, unsigned int reg)
208{
209	switch (reg) {
210	case SM5502_REG_INTMASK1:
211	case SM5502_REG_INTMASK2:
212		return true;
213	default:
214		break;
215	}
216	return false;
217}
218
219static const struct regmap_config sm5502_muic_regmap_config = {
220	.reg_bits	= 8,
221	.val_bits	= 8,
222	.volatile_reg	= sm5502_muic_volatile_reg,
223	.max_register	= SM5502_REG_END,
224};
225
226/* Change DM_CON/DP_CON/VBUSIN switch according to cable type */
227static int sm5502_muic_set_path(struct sm5502_muic_info *info,
228				unsigned int con_sw, unsigned int vbus_sw,
229				bool attached)
230{
231	int ret;
232
233	if (!attached) {
234		con_sw	= DM_DP_SWITCH_OPEN;
235		vbus_sw	= VBUSIN_SWITCH_OPEN;
236	}
237
238	switch (con_sw) {
239	case DM_DP_SWITCH_OPEN:
240	case DM_DP_SWITCH_USB:
241	case DM_DP_SWITCH_AUDIO:
242	case DM_DP_SWITCH_UART:
243		ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
244					 SM5502_REG_MANUAL_SW1_DP_MASK |
245					 SM5502_REG_MANUAL_SW1_DM_MASK,
246					 con_sw);
247		if (ret < 0) {
248			dev_err(info->dev,
249				"cannot update DM_CON/DP_CON switch\n");
250			return ret;
251		}
252		break;
253	default:
254		dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
255				con_sw);
256		return -EINVAL;
257	};
258
259	switch (vbus_sw) {
260	case VBUSIN_SWITCH_OPEN:
261	case VBUSIN_SWITCH_VBUSOUT:
262	case VBUSIN_SWITCH_MIC:
263	case VBUSIN_SWITCH_VBUSOUT_WITH_USB:
264		ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
265					 SM5502_REG_MANUAL_SW1_VBUSIN_MASK,
266					 vbus_sw);
267		if (ret < 0) {
268			dev_err(info->dev,
269				"cannot update VBUSIN switch\n");
270			return ret;
271		}
272		break;
273	default:
274		dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
275		return -EINVAL;
276	};
277
278	return 0;
279}
280
281/* Return cable type of attached or detached accessories */
282static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
283{
284	unsigned int cable_type = -1, adc, dev_type1;
285	int ret;
286
287	/* Read ADC value according to external cable or button */
288	ret = regmap_read(info->regmap, SM5502_REG_ADC, &adc);
289	if (ret) {
290		dev_err(info->dev, "failed to read ADC register\n");
291		return ret;
292	}
293
294	/*
295	 * If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't
296	 * connected with to MUIC device.
297	 */
298	cable_type = adc & SM5502_REG_ADC_MASK;
299	if (cable_type == SM5502_MUIC_ADC_GROUND)
300		return SM5502_MUIC_ADC_GROUND;
301
302	switch (cable_type) {
303	case SM5502_MUIC_ADC_GROUND:
304	case SM5502_MUIC_ADC_SEND_END_BUTTON:
305	case SM5502_MUIC_ADC_REMOTE_S1_BUTTON:
306	case SM5502_MUIC_ADC_REMOTE_S2_BUTTON:
307	case SM5502_MUIC_ADC_REMOTE_S3_BUTTON:
308	case SM5502_MUIC_ADC_REMOTE_S4_BUTTON:
309	case SM5502_MUIC_ADC_REMOTE_S5_BUTTON:
310	case SM5502_MUIC_ADC_REMOTE_S6_BUTTON:
311	case SM5502_MUIC_ADC_REMOTE_S7_BUTTON:
312	case SM5502_MUIC_ADC_REMOTE_S8_BUTTON:
313	case SM5502_MUIC_ADC_REMOTE_S9_BUTTON:
314	case SM5502_MUIC_ADC_REMOTE_S10_BUTTON:
315	case SM5502_MUIC_ADC_REMOTE_S11_BUTTON:
316	case SM5502_MUIC_ADC_REMOTE_S12_BUTTON:
317	case SM5502_MUIC_ADC_RESERVED_ACC_1:
318	case SM5502_MUIC_ADC_RESERVED_ACC_2:
319	case SM5502_MUIC_ADC_RESERVED_ACC_3:
320	case SM5502_MUIC_ADC_RESERVED_ACC_4:
321	case SM5502_MUIC_ADC_RESERVED_ACC_5:
322	case SM5502_MUIC_ADC_AUDIO_TYPE2:
323	case SM5502_MUIC_ADC_PHONE_POWERED_DEV:
324	case SM5502_MUIC_ADC_TTY_CONVERTER:
325	case SM5502_MUIC_ADC_UART_CABLE:
326	case SM5502_MUIC_ADC_TYPE1_CHARGER:
327	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
328	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB:
329	case SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE:
330	case SM5502_MUIC_ADC_TYPE2_CHARGER:
331	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART:
332	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART:
333		break;
334	case SM5502_MUIC_ADC_AUDIO_TYPE1:
335		/*
336		 * Check whether cable type is
337		 * SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE
338		 * or SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END
339		 * by using Button event.
340		 */
341		break;
342	case SM5502_MUIC_ADC_OPEN:
343		ret = regmap_read(info->regmap, SM5502_REG_DEV_TYPE1,
344				  &dev_type1);
345		if (ret) {
346			dev_err(info->dev, "failed to read DEV_TYPE1 reg\n");
347			return ret;
348		}
349
350		switch (dev_type1) {
351		case SM5502_REG_DEV_TYPE1_USB_SDP_MASK:
352			cable_type = SM5502_MUIC_ADC_OPEN_USB;
353			break;
354		case SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK:
355			cable_type = SM5502_MUIC_ADC_OPEN_TA;
356			break;
357		case SM5502_REG_DEV_TYPE1_USB_OTG_MASK:
358			cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG;
359			break;
360		default:
361			dev_dbg(info->dev,
362				"cannot identify the cable type: adc(0x%x)\n",
363				adc);
364			return -EINVAL;
365		};
366		break;
367	default:
368		dev_err(info->dev,
369			"failed to identify the cable type: adc(0x%x)\n", adc);
370		return -EINVAL;
371	};
372
373	return cable_type;
374}
375
376static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
377				     bool attached)
378{
379	static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
380	const char **cable_names = info->edev->supported_cable;
381	unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
382	unsigned int con_sw = DM_DP_SWITCH_OPEN;
383	unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
384	unsigned int idx = 0;
385	int ret;
386
387	if (!cable_names)
388		return 0;
389
390	/* Get the type of attached or detached cable */
391	if (attached)
392		cable_type = sm5502_muic_get_cable_type(info);
393	else
394		cable_type = prev_cable_type;
395	prev_cable_type = cable_type;
396
397	switch (cable_type) {
398	case SM5502_MUIC_ADC_OPEN_USB:
399		idx	= EXTCON_CABLE_USB;
400		con_sw	= DM_DP_SWITCH_USB;
401		vbus_sw	= VBUSIN_SWITCH_VBUSOUT_WITH_USB;
402		break;
403	case SM5502_MUIC_ADC_OPEN_TA:
404		idx	= EXTCON_CABLE_TA;
405		con_sw	= DM_DP_SWITCH_OPEN;
406		vbus_sw	= VBUSIN_SWITCH_VBUSOUT;
407		break;
408	case SM5502_MUIC_ADC_OPEN_USB_OTG:
409		idx	= EXTCON_CABLE_USB_HOST;
410		con_sw	= DM_DP_SWITCH_USB;
411		vbus_sw	= VBUSIN_SWITCH_OPEN;
412		break;
413	default:
414		dev_dbg(info->dev,
415			"cannot handle this cable_type (0x%x)\n", cable_type);
416		return 0;
417	};
418
419	/* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
420	ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
421	if (ret < 0)
422		return ret;
423
424	/* Change the state of external accessory */
425	extcon_set_cable_state(info->edev, cable_names[idx], attached);
426
427	return 0;
428}
429
430static void sm5502_muic_irq_work(struct work_struct *work)
431{
432	struct sm5502_muic_info *info = container_of(work,
433			struct sm5502_muic_info, irq_work);
434	int ret = 0;
435
436	if (!info->edev)
437		return;
438
439	mutex_lock(&info->mutex);
440
441	/* Detect attached or detached cables */
442	if (info->irq_attach) {
443		ret = sm5502_muic_cable_handler(info, true);
444		info->irq_attach = false;
445	}
446	if (info->irq_detach) {
447		ret = sm5502_muic_cable_handler(info, false);
448		info->irq_detach = false;
449	}
450
451	if (ret < 0)
452		dev_err(info->dev, "failed to handle MUIC interrupt\n");
453
454	mutex_unlock(&info->mutex);
455}
456
457/*
458 * Sets irq_attach or irq_detach in sm5502_muic_info and returns 0.
459 * Returns -ESRCH if irq_type does not match registered IRQ for this dev type.
460 */
461static int sm5502_parse_irq(struct sm5502_muic_info *info, int irq_type)
462{
463	switch (irq_type) {
464	case SM5502_IRQ_INT1_ATTACH:
465		info->irq_attach = true;
466		break;
467	case SM5502_IRQ_INT1_DETACH:
468		info->irq_detach = true;
469		break;
470	case SM5502_IRQ_INT1_KP:
471	case SM5502_IRQ_INT1_LKP:
472	case SM5502_IRQ_INT1_LKR:
473	case SM5502_IRQ_INT1_OVP_EVENT:
474	case SM5502_IRQ_INT1_OCP_EVENT:
475	case SM5502_IRQ_INT1_OVP_OCP_DIS:
476	case SM5502_IRQ_INT2_VBUS_DET:
477	case SM5502_IRQ_INT2_REV_ACCE:
478	case SM5502_IRQ_INT2_ADC_CHG:
479	case SM5502_IRQ_INT2_STUCK_KEY:
480	case SM5502_IRQ_INT2_STUCK_KEY_RCV:
481	case SM5502_IRQ_INT2_MHL:
482	default:
483		break;
484	}
485
486	return 0;
487}
488
489static irqreturn_t sm5502_muic_irq_handler(int irq, void *data)
490{
491	struct sm5502_muic_info *info = data;
492	int i, irq_type = -1, ret;
493
494	for (i = 0; i < info->num_muic_irqs; i++)
495		if (irq == info->muic_irqs[i].virq)
496			irq_type = info->muic_irqs[i].irq;
497
498	ret = sm5502_parse_irq(info, irq_type);
499	if (ret < 0) {
500		dev_warn(info->dev, "cannot handle is interrupt:%d\n",
501				    irq_type);
502		return IRQ_HANDLED;
503	}
504	schedule_work(&info->irq_work);
505
506	return IRQ_HANDLED;
507}
508
509static void sm5502_muic_detect_cable_wq(struct work_struct *work)
510{
511	struct sm5502_muic_info *info = container_of(to_delayed_work(work),
512				struct sm5502_muic_info, wq_detcable);
513	int ret;
514
515	/* Notify the state of connector cable or not  */
516	ret = sm5502_muic_cable_handler(info, true);
517	if (ret < 0)
518		dev_warn(info->dev, "failed to detect cable state\n");
519}
520
521static void sm5502_init_dev_type(struct sm5502_muic_info *info)
522{
523	unsigned int reg_data, vendor_id, version_id;
524	int i, ret;
525
526	/* To test I2C, Print version_id and vendor_id of SM5502 */
527	ret = regmap_read(info->regmap, SM5502_REG_DEVICE_ID, &reg_data);
528	if (ret) {
529		dev_err(info->dev,
530			"failed to read DEVICE_ID register: %d\n", ret);
531		return;
532	}
533
534	vendor_id = ((reg_data & SM5502_REG_DEVICE_ID_VENDOR_MASK) >>
535				SM5502_REG_DEVICE_ID_VENDOR_SHIFT);
536	version_id = ((reg_data & SM5502_REG_DEVICE_ID_VERSION_MASK) >>
537				SM5502_REG_DEVICE_ID_VERSION_SHIFT);
538
539	dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
540			    version_id, vendor_id);
541
542	/* Initiazle the register of SM5502 device to bring-up */
543	for (i = 0; i < info->num_reg_data; i++) {
544		unsigned int val = 0;
545
546		if (!info->reg_data[i].invert)
547			val |= ~info->reg_data[i].val;
548		else
549			val = info->reg_data[i].val;
550		regmap_write(info->regmap, info->reg_data[i].reg, val);
551	}
552}
553
554static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
555				 const struct i2c_device_id *id)
556{
557	struct device_node *np = i2c->dev.of_node;
558	struct sm5502_muic_info *info;
559	int i, ret, irq_flags;
560
561	if (!np)
562		return -EINVAL;
563
564	info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
565	if (!info)
566		return -ENOMEM;
567	i2c_set_clientdata(i2c, info);
568
569	info->dev = &i2c->dev;
570	info->i2c = i2c;
571	info->irq = i2c->irq;
572	info->muic_irqs = sm5502_muic_irqs;
573	info->num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs);
574	info->reg_data = sm5502_reg_data;
575	info->num_reg_data = ARRAY_SIZE(sm5502_reg_data);
576
577	mutex_init(&info->mutex);
578
579	INIT_WORK(&info->irq_work, sm5502_muic_irq_work);
580
581	info->regmap = devm_regmap_init_i2c(i2c, &sm5502_muic_regmap_config);
582	if (IS_ERR(info->regmap)) {
583		ret = PTR_ERR(info->regmap);
584		dev_err(info->dev, "failed to allocate register map: %d\n",
585				   ret);
586		return ret;
587	}
588
589	/* Support irq domain for SM5502 MUIC device */
590	irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
591	ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0,
592				  &sm5502_muic_irq_chip, &info->irq_data);
593	if (ret != 0) {
594		dev_err(info->dev, "failed to request IRQ %d: %d\n",
595				    info->irq, ret);
596		return ret;
597	}
598
599	for (i = 0; i < info->num_muic_irqs; i++) {
600		struct muic_irq *muic_irq = &info->muic_irqs[i];
601		unsigned int virq = 0;
602
603		virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
604		if (virq <= 0)
605			return -EINVAL;
606		muic_irq->virq = virq;
607
608		ret = devm_request_threaded_irq(info->dev, virq, NULL,
609						sm5502_muic_irq_handler,
610						IRQF_NO_SUSPEND,
611						muic_irq->name, info);
612		if (ret) {
613			dev_err(info->dev,
614				"failed: irq request (IRQ: %d, error :%d)\n",
615				muic_irq->irq, ret);
616			return ret;
617		}
618	}
619
620	/* Allocate extcon device */
621	info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable);
622	if (IS_ERR(info->edev)) {
623		dev_err(info->dev, "failed to allocate memory for extcon\n");
624		return -ENOMEM;
625	}
626	info->edev->name = np->name;
627
628	/* Register extcon device */
629	ret = devm_extcon_dev_register(info->dev, info->edev);
630	if (ret) {
631		dev_err(info->dev, "failed to register extcon device\n");
632		return ret;
633	}
634
635	/*
636	 * Detect accessory after completing the initialization of platform
637	 *
638	 * - Use delayed workqueue to detect cable state and then
639	 * notify cable state to notifiee/platform through uevent.
640	 * After completing the booting of platform, the extcon provider
641	 * driver should notify cable state to upper layer.
642	 */
643	INIT_DELAYED_WORK(&info->wq_detcable, sm5502_muic_detect_cable_wq);
644	queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
645			msecs_to_jiffies(DELAY_MS_DEFAULT));
646
647	/* Initialize SM5502 device and print vendor id and version id */
648	sm5502_init_dev_type(info);
649
650	return 0;
651}
652
653static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
654{
655	struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
656
657	regmap_del_irq_chip(info->irq, info->irq_data);
658
659	return 0;
660}
661
662static const struct of_device_id sm5502_dt_match[] = {
663	{ .compatible = "siliconmitus,sm5502-muic" },
664	{ },
665};
666
667#ifdef CONFIG_PM_SLEEP
668static int sm5502_muic_suspend(struct device *dev)
669{
670	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
671	struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
672
673	enable_irq_wake(info->irq);
674
675	return 0;
676}
677
678static int sm5502_muic_resume(struct device *dev)
679{
680	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
681	struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
682
683	disable_irq_wake(info->irq);
684
685	return 0;
686}
687#endif
688
689static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops,
690			 sm5502_muic_suspend, sm5502_muic_resume);
691
692static const struct i2c_device_id sm5502_i2c_id[] = {
693	{ "sm5502", TYPE_SM5502 },
694	{ }
695};
696MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
697
698static struct i2c_driver sm5502_muic_i2c_driver = {
699	.driver		= {
700		.name	= "sm5502",
701		.owner	= THIS_MODULE,
702		.pm	= &sm5502_muic_pm_ops,
703		.of_match_table = sm5502_dt_match,
704	},
705	.probe	= sm5022_muic_i2c_probe,
706	.remove	= sm5502_muic_i2c_remove,
707	.id_table = sm5502_i2c_id,
708};
709
710static int __init sm5502_muic_i2c_init(void)
711{
712	return i2c_add_driver(&sm5502_muic_i2c_driver);
713}
714subsys_initcall(sm5502_muic_i2c_init);
715
716MODULE_DESCRIPTION("Silicon Mitus SM5502 Extcon driver");
717MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
718MODULE_LICENSE("GPL");
719