regulator: Troika :Set BUCK8 output voltage to 1.35V
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / drivers / muic_mu004 / muic_manager.c
CommitLineData
581d0897
KT
1/*
2 * muic_ccic.c
3 *
4 * Copyright (C) 2014 Samsung Electronics
5 * Thomas Ryu <smilesr.ryu@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#define pr_fmt(fmt) "[MUIC] " fmt
23
24#include <linux/gpio.h>
25#include <linux/i2c.h>
26#include <linux/interrupt.h>
27#include <linux/slab.h>
28#include <linux/platform_device.h>
29#include <linux/module.h>
30#include <linux/delay.h>
31#if defined(CONFIG_USB_HOST_NOTIFY)
32#include <linux/host_notify.h>
33#endif
34#include <linux/string.h>
35#if defined(CONFIG_OF)
36#include <linux/of_device.h>
37#include <linux/of_gpio.h>
38#endif
39
40#include <linux/muic_mu004/muic_core.h>
41#if defined(CONFIG_IFCONN_NOTIFIER)
42#include <linux/ifconn/ifconn_notifier.h>
43#endif
44#if defined(CONFIG_MUIC_NOTIFIER)
45#include <linux/muic_mu004/s2mu004-muic-notifier.h>
46#endif
47#include <linux/muic_mu004/muic_interface.h>
48
49#if defined(CONFIG_CCIC_NOTIFIER)
50#include <linux/ccic/ccic_notifier.h>
51#endif
52
53#if defined(CONFIG_USB_TYPEC_MANAGER_NOTIFIER)
54#include <linux/usb/manager/usb_typec_manager_notifier.h>
55#endif
56
57#if defined(CONFIG_MUIC_HV)
58#include "muic_hv.h"
59#endif
60
61#define MUIC_CCIC_NOTI_ATTACH (1)
62#define MUIC_CCIC_NOTI_DETACH (-1)
63#define MUIC_CCIC_NOTI_UNDEFINED (0)
64
65static int __ccic_info;
66static struct ccic_rid_desc_t ccic_rid_tbl[] = {
67 [CCIC_RID_UNDEFINED] = {"UNDEFINED", ATTACHED_DEV_NONE_MUIC},
68 [CCIC_RID_000K] = {"000K", ATTACHED_DEV_OTG_MUIC},
69 [CCIC_RID_001K] = {"001K", ATTACHED_DEV_MHL_MUIC},
70 [CCIC_RID_255K] = {"255K", ATTACHED_DEV_JIG_USB_OFF_MUIC},
71 [CCIC_RID_301K] = {"301K", ATTACHED_DEV_JIG_USB_ON_MUIC},
72 [CCIC_RID_523K] = {"523K", ATTACHED_DEV_JIG_UART_OFF_MUIC},
73 [CCIC_RID_619K] = {"619K", ATTACHED_DEV_JIG_UART_ON_MUIC},
74 [CCIC_RID_OPEN] = {"OPEN", ATTACHED_DEV_NONE_MUIC},
75};
76
77/*
78 * __ccic_info :
79 * b'0: 1 if an active ccic is present,
80 * 0 when muic works without ccic chip or
81 * no ccic Noti. registration is needed
82 * even though a ccic chip is present.
83 */
84static int set_ccic_info(char *str)
85{
86 get_option(&str, &__ccic_info);
87
88 pr_info("%s: ccic_info: 0x%04x\n", __func__, __ccic_info);
89
90 return __ccic_info;
91}
92
93__setup("ccic_info=", set_ccic_info);
94
95int get_ccic_info(void)
96{
97 return __ccic_info;
98}
99
100static void _muic_manager_switch_uart_path(struct muic_interface_t *muic_if, int path)
101{
102 if (muic_if->pdata->gpio_uart_sel)
103 muic_if->set_gpio_uart_sel(muic_if->muic_data, path);
104
105 if (muic_if->set_switch_to_uart)
106 muic_if->set_switch_to_uart(muic_if->muic_data);
107 else
108 pr_err("%s:function not set!\n", __func__);
109}
110
111static void _muic_manager_switch_usb_path(struct muic_interface_t *muic_if, int path)
112{
113 if (muic_if->pdata->gpio_usb_sel)
114 muic_if->set_gpio_usb_sel(muic_if->muic_data, path);
115
116 if (muic_if->set_switch_to_usb)
117 muic_if->set_switch_to_usb(muic_if->muic_data);
118 else
119 pr_err("%s:function not set!\n", __func__);
120}
121
122static int muic_manager_switch_path(struct muic_interface_t *muic_if, int path)
123{
124#if defined(CONFIG_MUIC_HV)
125 hv_clear_hvcontrol(muic_if->phv);
126#endif
127 switch (path) {
128 case MUIC_PATH_OPEN:
129 muic_if->set_com_to_open(muic_if->muic_data);
130 break;
131
132 case MUIC_PATH_USB_AP:
133 case MUIC_PATH_USB_CP:
134 _muic_manager_switch_usb_path(muic_if, muic_if->pdata->usb_path);
135 break;
136 case MUIC_PATH_UART_AP:
137 case MUIC_PATH_UART_CP:
138 _muic_manager_switch_uart_path(muic_if, muic_if->pdata->uart_path);
139 break;
140
141 default:
142 pr_err("%s:A wrong com path!\n", __func__);
143 return -1;
144 }
145
146 return 0;
147}
148
149static int muic_manager_get_vbus(struct muic_interface_t *muic_if)
150{
151 int ret = 0;
152
153 ret = muic_if->get_vbus(muic_if->muic_data);
154
155 return ret;
156}
157
158static bool muic_manager_is_supported_dev(int attached_dev)
159{
160 switch (attached_dev) {
161 case ATTACHED_DEV_USB_MUIC:
162 case ATTACHED_DEV_CDP_MUIC:
163 case ATTACHED_DEV_TA_MUIC:
164 case ATTACHED_DEV_JIG_UART_OFF_MUIC:
165 case ATTACHED_DEV_JIG_UART_OFF_VB_MUIC:
166 case ATTACHED_DEV_JIG_UART_ON_MUIC:
167 case ATTACHED_DEV_JIG_UART_ON_VB_MUIC:
168 case ATTACHED_DEV_JIG_USB_OFF_MUIC:
169 case ATTACHED_DEV_JIG_USB_ON_MUIC:
170 case ATTACHED_DEV_OTG_MUIC:
171 case ATTACHED_DEV_AFC_CHARGER_5V_MUIC:
172 case ATTACHED_DEV_AFC_CHARGER_9V_MUIC:
173 case ATTACHED_DEV_QC_CHARGER_5V_MUIC:
174 case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
175 return true;
176 default:
177 break;
178 }
179
180 return false;
181}
182
183int muic_manager_is_ccic_supported_dev(muic_attached_dev_t new_dev)
184{
185 switch (new_dev) {
186 /* Legacy TA/USB. Noti. will be sent when ATTACH is received from CCIC. */
187 case ATTACHED_DEV_USB_MUIC:
188 case ATTACHED_DEV_CDP_MUIC:
189 case ATTACHED_DEV_TA_MUIC:
190 case ATTACHED_DEV_TIMEOUT_OPEN_MUIC:
191 return 1;
192 default:
193 break;
194 }
195
196 return 0;
197}
198
199void muic_manager_handle_ccic_detach(struct muic_interface_t *muic_if)
200{
201 struct ccic_desc_t *ccic = muic_if->ccic;
202 struct muic_platform_data *pdata = muic_if->pdata;
203
204 pr_info("%s\n", __func__);
205
206#if defined(CONFIG_MUIC_HV)
207 hv_do_detach(muic_if->phv);
208#endif
209 if (ccic->ccic_evt_rprd) {
210 /* FIXME : pvendor
211 * if (pvendor && pvendor->enable_chgdet)
212 * pvendor->enable_chgdet(muic_if->regmaccic, 1);
213 */
214 }
215
216 muic_manager_switch_path(muic_if, MUIC_PATH_OPEN);
217 if (muic_manager_is_supported_dev(ccic->attached_dev)) {
218 MUIC_SEND_NOTI_DETACH(ccic->attached_dev);
219 } else if (muic_if->legacy_dev != ATTACHED_DEV_NONE_MUIC) {
220 MUIC_SEND_NOTI_DETACH(muic_if->legacy_dev);
221 }
222
223 if (muic_core_get_ccic_cable_state(pdata))
224 muic_if->set_cable_state(muic_if->muic_data, ATTACHED_DEV_NONE_MUIC);
225
226 if (pdata->jig_uart_cb)
227 pdata->jig_uart_cb(0);
228
229 /* Reset status & flags */
230 ccic->attached_dev = 0;
231 ccic->ccic_evt_rid = 0;
232 ccic->ccic_evt_rprd = 0;
233 ccic->ccic_evt_roleswap = 0;
234 ccic->ccic_evt_dcdcnt = 0;
235 ccic->ccic_evt_attached = MUIC_CCIC_NOTI_UNDEFINED;
236
237 muic_if->legacy_dev = 0;
238 muic_if->attached_dev = 0;
239#if defined(CONFIG_MUIC_HV)
240 muic_if->phv->attached_dev = 0;
241#endif
242 muic_if->is_dcdtmr_intr = false;
243}
244
245void muic_manager_set_legacy_dev(struct muic_interface_t *muic_if, int new_dev)
246{
247 pr_info("%s: %d->%d\n", __func__, muic_if->legacy_dev, new_dev);
248
249 muic_if->legacy_dev = new_dev;
250}
251
252/* Get the charger type from muic interrupt or by reading the register directly */
253int muic_manager_get_legacy_dev(struct muic_interface_t *muic_if)
254{
255 return muic_if->legacy_dev;
256}
257
258static void muic_manager_show_status(struct muic_interface_t *muic_if)
259{
260 struct ccic_desc_t *ccic = muic_if->ccic;
261
262 pr_info("%s: attached_dev:%d rid:%d rprd:%d attached:%d legacy_dev:%d\n", __func__,
263 ccic->attached_dev, ccic->ccic_evt_rid, ccic->ccic_evt_rprd,
264 ccic->ccic_evt_attached, muic_if->legacy_dev);
265}
266
267int muic_manager_dcd_rescan(struct muic_interface_t *muic_if)
268{
269 struct ccic_desc_t *ccic = muic_if->ccic;
270 int vbus = muic_manager_get_vbus(muic_if);
271
272 pr_info("%s : ccic_evt_attached(%d), is_dcdtmr_intr(%d), ccic_evt_dcdcnt(%d)\n",
273 __func__, ccic->ccic_evt_attached, muic_if->is_dcdtmr_intr, ccic->ccic_evt_dcdcnt);
274
275 if (!(muic_if->opmode & OPMODE_DEVICE)) {
276 pr_info("%s : it's SMD board, skip rescan", __func__);
277 goto SKIP_RESCAN;
278 }
279
280 /* W/A for Incomplete insertion case */
281 if (muic_if->is_dcdtmr_intr && vbus && ccic->ccic_evt_dcdcnt < 1) {
282 pr_info("%s: Incomplete insertion. Do chgdet again\n", __func__);
283 ccic->ccic_evt_dcdcnt++;
284
285 if (muic_if->set_dcd_rescan != NULL)
286 muic_if->set_dcd_rescan(muic_if->muic_data);
287
288 return 0;
289 }
290
291SKIP_RESCAN:
292 return 1;
293}
294
295static int muic_manager_handle_legacy_dev(struct muic_interface_t *muic_if)
296{
297 struct ccic_desc_t *ccic = muic_if->ccic;
298 int attached_dev = 0;
299
300 pr_info("%s: vbvolt:%d legacy_dev:%d\n", __func__,
301 muic_if->vps.t.vbvolt, muic_if->legacy_dev);
302
303 /* 1. Run a charger detection algorithm manually if necessary. */
304 msleep(200);
305
306 /* 2. Get the result by polling or via an interrupt */
307 attached_dev = muic_manager_get_legacy_dev(muic_if);
308 pr_info("%s: detected legacy_dev=%d\n", __func__, attached_dev);
309
310 /* 3. Noti. if supported. */
311 if (!muic_manager_is_ccic_supported_dev(attached_dev)) {
312 pr_info("%s: Unsupported legacy_dev=%d\n", __func__, attached_dev);
313 return 0;
314 }
315
316 if (muic_manager_is_supported_dev(ccic->attached_dev)) {
317 MUIC_SEND_NOTI_DETACH(ccic->attached_dev);
318 ccic->attached_dev = 0;
319 } else if (muic_if->legacy_dev != ATTACHED_DEV_NONE_MUIC) {
320 MUIC_SEND_NOTI_DETACH(muic_if->legacy_dev);
321 muic_if->legacy_dev = 0;
322 }
323
324 ccic->attached_dev = attached_dev;
325 MUIC_SEND_NOTI_ATTACH(attached_dev);
326
327 return 0;
328}
329
330void muic_manager_init_dev_desc(struct muic_interface_t *muic_if)
331{
332 struct ccic_desc_t *ccic = muic_if->ccic;
333
334 pr_info("%s\n", __func__);
335 ccic->attached_dev = 0;
336 ccic->ccic_evt_rid = 0;
337 ccic->ccic_evt_rprd = 0;
338 ccic->ccic_evt_roleswap = 0;
339 ccic->ccic_evt_dcdcnt = 0;
340 ccic->ccic_evt_attached = MUIC_CCIC_NOTI_UNDEFINED;
341}
342
343static int muic_manager_conv_rid_to_dev(struct muic_interface_t *muic_if, int rid, int vbus)
344{
345 int attached_dev = 0;
346
347 pr_info("%s rid=%d vbus=%d\n", __func__, rid, vbus);
348
349 if (rid < 0 || rid > CCIC_RID_OPEN) {
350 pr_err("%s:Out of RID range: %d\n", __func__, rid);
351 return 0;
352 }
353
354 if ((rid == CCIC_RID_619K) && vbus)
355 attached_dev = ATTACHED_DEV_JIG_UART_ON_VB_MUIC;
356 else
357 attached_dev = muic_if->ccic->rid_desc[rid].attached_dev;
358
359 return attached_dev;
360}
361
362static bool muic_manager_is_valid_rid_open(struct muic_interface_t *muic_if, int vbus)
363{
364 int i, retry = 5;
365
366 if (vbus)
367 return true;
368
369 for (i = 0; i < retry; i++) {
370 pr_info("%s: %dth ...\n", __func__, i);
371 msleep(20);
372 if (muic_manager_get_vbus(muic_if))
373 return 1;
374 }
375
376 return 0;
377}
378
379#ifdef CONFIG_IFCONN_NOTIFIER
380static int muic_manager_handle_ccic_attach(struct muic_interface_t *muic_if, void *data)
381{
382 struct ccic_desc_t *ccic = muic_if->ccic;
383#ifdef CONFIG_IFCONN_NOTIFIER
384 struct ifconn_notifier_template *pnoti =
385 (struct ifconn_notifier_template *)data;
386#else
387 CC_NOTI_ATTACH_TYPEDEF *pnoti = (CC_NOTI_ATTACH_TYPEDEF *)data;
388#endif
389
390 pr_info("%s: src:%d dest:%d id:%d attach:%d cable_type:%d rprd:%d\n",
391 __func__, pnoti->src, pnoti->dest, pnoti->id, pnoti->attach,
392 pnoti->cable_type, pnoti->rprd);
393
394 /* Attached */
395 if (pnoti->event == IFCONN_NOTIFY_EVENT_ATTACH) {
396 pr_info("%s: Attach\n", __func__);
397 ccic->ccic_evt_attached = MUIC_CCIC_NOTI_ATTACH;
398 } else {
399 muic_manager_handle_ccic_detach(muic_if);
400 }
401
402 return 0;
403}
404#else
405static int muic_manager_handle_ccic_attach(struct muic_interface_t *muic_if, void *data)
406{
407 struct ccic_desc_t *ccic = muic_if->ccic;
408#ifdef CONFIG_IFCONN_NOTIFIER
409 struct ifconn_notifier_template *pnoti =
410 (struct ifconn_notifier_template *)data;
411#else
412 CC_NOTI_ATTACH_TYPEDEF *pnoti = (CC_NOTI_ATTACH_TYPEDEF *) data;
413#endif
414 int vbus = muic_manager_get_vbus(muic_if);
415
416 pr_info("%s: src:%d dest:%d id:%d attach:%d cable_type:%d rprd:%d\n",
417 __func__, pnoti->src, pnoti->dest, pnoti->id, pnoti->attach,
418 pnoti->cable_type, pnoti->rprd);
419
420 ccic->ccic_evt_attached = pnoti->attach ?
421 MUIC_CCIC_NOTI_ATTACH : MUIC_CCIC_NOTI_DETACH;
422
423 /* Attached */
424 if (ccic->ccic_evt_attached == MUIC_CCIC_NOTI_ATTACH) {
425 pr_info("%s: Attach\n", __func__);
426
427 if (ccic->ccic_evt_roleswap) {
428 pr_info("%s: roleswap event, attach USB\n", __func__);
429 ccic->ccic_evt_roleswap = 0;
430 if (muic_manager_get_vbus(muic_if)) {
431 ccic->attached_dev = ATTACHED_DEV_USB_MUIC;
432 MUIC_SEND_NOTI_ATTACH(ccic->attached_dev);
433 }
434 return 0;
435 }
436
437 if (pnoti->rprd) {
438 pr_info("%s: RPRD\n", __func__);
439 ccic->ccic_evt_rprd = 1;
440 ccic->attached_dev = ATTACHED_DEV_OTG_MUIC;
441 muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
442 muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
443 return 0;
444 }
445
446 if (muic_if->is_afc_reset) {
447 pr_info("%s: DCD RESCAN after afc reset\n", __func__);
448 muic_if->is_afc_reset = false;
449 if (muic_if->set_dcd_rescan != NULL && !muic_if->is_dcp_charger)
450 muic_if->set_dcd_rescan(muic_if->muic_data);
451 }
452
453 if (muic_manager_is_valid_rid_open(muic_if, vbus))
454 pr_info("%s: Valid VBUS-> handled in irq handler\n", __func__);
455 else
456 pr_info("%s: No VBUS-> doing nothing.\n", __func__);
457
458 /* CCIC ATTACH means NO WATER */
459 if (muic_if->afc_water_disable) {
460 pr_info("%s: Water is not detected, AFC Enable\n", __func__);
461 muic_if->afc_water_disable = false;
462 }
463
464 /* W/A for Incomplete insertion case */
465 ccic->ccic_evt_dcdcnt = 0;
466 if (muic_if->is_dcdtmr_intr && vbus) {
467 if (muic_if->vps.t.chgdetrun) {
468 pr_info("%s: Incomplete insertion. Chgdet runnung\n", __func__);
469 return 0;
470 }
471 pr_info("%s: Incomplete insertion. Do chgdet again\n", __func__);
472 muic_if->is_dcdtmr_intr = false;
473
474 if (muic_if->set_dcd_rescan != NULL)
475 muic_if->set_dcd_rescan(muic_if->muic_data);
476 }
477
478 } else {
479 if (pnoti->rprd) {
480 /* Role swap detach: attached=0, rprd=1 */
481 pr_info("%s: role swap event\n", __func__);
482 ccic->ccic_evt_roleswap = 1;
483 } else {
484 /* Detached */
485 muic_manager_handle_ccic_detach(muic_if);
486 }
487 }
488
489 return 0;
490}
491
492#endif
493static int muic_manager_handle_ccic_factory_jig(struct muic_interface_t *muic_if, int rid, int vbus)
494{
495 struct ccic_desc_t *ccic = muic_if->ccic;
496 struct muic_platform_data *pdata = muic_if->pdata;
497 int attached_dev = 0;
498
499 pr_info("%s: rid:%d vbus:%d\n", __func__, rid, vbus);
500
501 switch (rid) {
502 case CCIC_RID_255K:
503 case CCIC_RID_301K:
504 if (pdata->jig_uart_cb)
505 pdata->jig_uart_cb(1);
506 muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
507 break;
508 case CCIC_RID_523K:
509 case CCIC_RID_619K:
510 if (pdata->jig_uart_cb)
511 pdata->jig_uart_cb(1);
512 muic_manager_switch_path(muic_if, MUIC_PATH_UART_AP);
513 break;
514 default:
515 pr_info("%s: Unsupported rid\n", __func__);
516 return 0;
517 }
518
519 attached_dev = muic_manager_conv_rid_to_dev(muic_if, rid, vbus);
520
521 if (attached_dev != ccic->attached_dev) {
522 if (muic_manager_is_supported_dev(ccic->attached_dev)) {
523 MUIC_SEND_NOTI_DETACH(ccic->attached_dev);
524 ccic->attached_dev = 0;
525 } else if (muic_if->legacy_dev != ATTACHED_DEV_NONE_MUIC) {
526 MUIC_SEND_NOTI_DETACH(muic_if->legacy_dev);
527 muic_if->legacy_dev = 0;
528 }
529
530 ccic->attached_dev = attached_dev;
531 muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
532 MUIC_SEND_NOTI_ATTACH(attached_dev);
533 }
534
535 return 0;
536}
537
538static int muic_manager_handle_ccic_rid(struct muic_interface_t *muic_if, void *data)
539{
540 struct ccic_desc_t *ccic = muic_if->ccic;
541 struct muic_platform_data *pdata = muic_if->pdata;
542 int rid, vbus;
543#ifdef CONFIG_IFCONN_NOTIFIER
544 struct ifconn_notifier_template *pnoti =
545 (struct ifconn_notifier_template *)data;
546#else
547 CC_NOTI_RID_TYPEDEF *pnoti = (CC_NOTI_RID_TYPEDEF *) data;
548#endif
549
550 pr_info("%s: src:%d dest:%d id:%d rid:%d sub2:%d sub3:%d\n", __func__,
551 pnoti->src, pnoti->dest, pnoti->id, pnoti->rid, pnoti->sub2,
552 pnoti->sub3);
553
554 rid = pnoti->rid;
555
556 if (rid > CCIC_RID_OPEN) {
557 pr_info("%s: Out of range of RID\n", __func__);
558 return 0;
559 }
560
561 if (ccic->ccic_evt_attached != MUIC_CCIC_NOTI_ATTACH) {
562 pr_info("%s: RID but No ATTACH->discarded\n", __func__);
563 return 0;
564 }
565
566 ccic->ccic_evt_rid = rid;
567
568 switch (rid) {
569 case CCIC_RID_000K:
570 pr_info("%s: OTG -> RID000K\n", __func__);
571 muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
572 vbus = muic_manager_get_vbus(muic_if);
573 ccic->attached_dev = muic_manager_conv_rid_to_dev(muic_if, rid, vbus);
574 return 0;
575 case CCIC_RID_001K:
576 pr_info("%s: MHL -> discarded.\n", __func__);
577 return 0;
578 case CCIC_RID_255K:
579 case CCIC_RID_301K:
580 case CCIC_RID_523K:
581 case CCIC_RID_619K:
582 vbus = muic_manager_get_vbus(muic_if);
583 muic_manager_handle_ccic_factory_jig(muic_if, rid, vbus);
584 break;
585 case CCIC_RID_OPEN:
586 case CCIC_RID_UNDEFINED:
587 vbus = muic_manager_get_vbus(muic_if);
588 if (ccic->ccic_evt_attached == MUIC_CCIC_NOTI_ATTACH &&
589 muic_manager_is_valid_rid_open(muic_if, vbus)) {
590 if (pdata->jig_uart_cb)
591 pdata->jig_uart_cb(0);
592 /*
593 * USB team's requirement.
594 * Set AP USB for enumerations.
595 */
596 muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
597 muic_manager_handle_legacy_dev(muic_if);
598 } else {
599 /* RID OPEN + No VBUS = Assume detach */
600 muic_manager_handle_ccic_detach(muic_if);
601 }
602 break;
603 default:
604 pr_err("%s:Undefined RID\n", __func__);
605 return 0;
606 }
607
608 return 0;
609}
610
611static int muic_manager_handle_ccic_water(struct muic_interface_t *muic_if, void *data)
612{
613#ifdef CONFIG_IFCONN_NOTIFIER
614 struct ifconn_notifier_template *pnoti = (struct ifconn_notifier_template *)data;
615#else
616 CC_NOTI_ATTACH_TYPEDEF *pnoti = (CC_NOTI_ATTACH_TYPEDEF *) data;
617#endif
618
619 pr_info("%s: src:%d dest:%d id:%d attach:%d cable_type:%d rprd:%d\n", __func__,
620 pnoti->src, pnoti->dest, pnoti->id, pnoti->attach, pnoti->cable_type, pnoti->rprd);
621
622 muic_if->afc_water_disable = pnoti->attach ? true : false;
623 muic_if->set_water_detect(muic_if->muic_data, muic_if->afc_water_disable);
624
625 pr_info("%s: Water detect : %s\n", __func__, pnoti->attach ? "en":"dis");
626
627 return 0;
628}
629
630static int muic_manager_handle_ccic_TA(struct muic_interface_t *muic_if, void *data)
631{
632#ifdef CONFIG_IFCONN_NOTIFIER
633 struct ifconn_notifier_template *pnoti = (struct ifconn_notifier_template *)data;
634#else
635 CC_NOTI_ATTACH_TYPEDEF *pnoti = (CC_NOTI_ATTACH_TYPEDEF *) data;
636#endif
637
638 pr_info("%s: src:%d dest:%d id:%d attach:%d cable_type:%d rprd:%d\n", __func__,
639 pnoti->src, pnoti->dest, pnoti->id, pnoti->attach, pnoti->cable_type, pnoti->rprd);
640
641 return 0;
642}
643
644static int muic_manager_handle_otg(struct muic_interface_t *muic_if, void *data)
645{
646 int ret = 0;
647 struct ccic_desc_t *ccic = muic_if->ccic;
648#ifdef CONFIG_IFCONN_NOTIFIER
649 struct ifconn_notifier_template *pnoti = (struct ifconn_notifier_template *)data;
650#else
651 CC_NOTI_TYPEDEF *pnoti = (CC_NOTI_TYPEDEF *) data;
652#endif
653
654 pr_info("%s: src:%d dest:%d id:%d\n", __func__,
655 pnoti->src, pnoti->dest, pnoti->id);
656
657 /* OTG Attach */
658 if (ret == MUIC_NORMAL_OTG) {
659 MUIC_SEND_NOTI_TO_CCIC_ATTACH(ATTACHED_DEV_OTG_MUIC);
660 ccic->ccic_evt_rprd = 1;
661 ccic->attached_dev = ATTACHED_DEV_OTG_MUIC;
662 muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
663 muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
664 }
665#if 0
666 muic_if->set_otg_detect_en(muic_if->muic_data, pnoti->sub2 ? true:false);
667 pr_info("%s: set_otg_detect_en : %s\n", __func__, pnoti->sub2 ? "en":"dis");
668#endif
669
670 return 0;
671}
672
673static int muic_manager_handle_ccic_pd_charger(struct muic_interface_t *muic_if, void *data)
674{
675 struct ccic_desc_t *ccic = muic_if->ccic;
676#ifdef CONFIG_IFCONN_NOTIFIER
677 struct ifconn_notifier_template *pnoti = (struct ifconn_notifier_template *)data;
678#else
679 CC_NOTI_ATTACH_TYPEDEF *pnoti = (CC_NOTI_ATTACH_TYPEDEF *) data;
680#endif
681
682 pr_info("%s: src:%d dest:%d id:%d\n", __func__,
683 pnoti->src, pnoti->dest, pnoti->id);
684
685 ccic->attached_dev = ATTACHED_DEV_TYPE3_CHARGER_MUIC;
686 muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
687
688 return 0;
689}
690
691static int muic_manager_handle_notification(struct notifier_block *nb,
692 unsigned long action, void *data)
693{
694#ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER
695 struct muic_interface_t *muic_if =
696 container_of(nb, struct muic_interface_t, manager_nb);
697#else
698 struct muic_interface_t *muic_if =
699 container_of(nb, struct muic_interface_t, nb);
700#endif
701
702#ifdef CONFIG_IFCONN_NOTIFIER
703 struct ifconn_notifier_template *pnoti =
704 (struct ifconn_notifier_template *)data;
705 int attach = IFCONN_NOTIFY_ID_ATTACH;
706 int rid = IFCONN_NOTIFY_ID_RID;
707 int water = IFCONN_NOTIFY_ID_WATER;
708 int otg = IFCONN_NOTIFY_ID_OTG;
709 int ta = IFCONN_NOTIFY_ID_TA;
710 int pd = IFCONN_NOTIFY_ID_POWER_STATUS;
711#else
712 CC_NOTI_TYPEDEF *pnoti = (CC_NOTI_TYPEDEF *) data;
713 int attach = CCIC_NOTIFY_ID_ATTACH;
714 int rid = CCIC_NOTIFY_ID_RID;
715 int water = CCIC_NOTIFY_ID_WATER;
716 int otg = CCIC_NOTIFY_ID_OTG;
717 int ta = CCIC_NOTIFY_ID_TA;
718#ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER
719 if (pnoti->dest != CCIC_NOTIFY_DEV_MUIC) {
720 pr_info("%s destination id is invalid\n", __func__);
721 return 0;
722 }
723#endif
724#endif
725 muic_manager_show_status(muic_if);
726
727 if (pnoti->id == attach) {
728 pr_info("%s: NOTIFY_ID_ATTACH: %s\n", __func__,
729 pnoti->attach ? "Attached" : "Detached");
730 muic_manager_handle_ccic_attach(muic_if, data);
731 } else if (pnoti->id == rid) {
732 pr_info("%s: NOTIFY_ID_RID\n", __func__);
733 muic_manager_handle_ccic_rid(muic_if, data);
734 } else if (pnoti->id == water) {
735 pr_info("%s: NOTIFY_ID_WATER\n", __func__);
736 muic_manager_handle_ccic_water(muic_if, data);
737 } else if (pnoti->id == otg) {
738 pr_info("%s: NOTIFY_ID_OTG\n", __func__);
739 muic_manager_handle_otg(muic_if, data);
740 } else if (pnoti->id == ta) {
741 pr_info("%s: NOTIFY_ID_TA\n", __func__);
742 muic_manager_handle_ccic_TA(muic_if, data);
743 } else if (pnoti->id == pd) {
744 pr_info("%s: NOTIFY_ID_TA\n", __func__);
745 muic_manager_handle_ccic_pd_charger(muic_if, data);
746 } else {
747 pr_info("%s: Undefined Noti. ID\n", __func__);
748 }
749
750 muic_manager_show_status(muic_if);
751
752 return NOTIFY_DONE;
753}
754
755#ifndef CONFIG_IFCONN_NOTIFIER
756void _muic_delayed_notifier(struct work_struct *work)
757{
758 struct muic_interface_t *muic_if;
759 int ret = 0;
760
761 pr_info("%s\n", __func__);
762
763 muic_if = container_of(work, struct muic_interface_t, ccic_work.work);
764
765#ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER
766 ret = manager_notifier_register(&muic_if->manager_nb,
767 muic_manager_handle_notification,
768 MANAGER_NOTIFY_CCIC_MUIC);
769#else
770 ret = ccic_notifier_register(&muic_if->ccic_nb,
771 muic_manager_handle_notification,
772 CCIC_NOTIFY_DEV_MUIC);
773#endif
774
775 if (ret < 0) {
776 pr_info("%s: CCIC Noti. is not ready. Try again in 4sec...\n", __func__);
777 schedule_delayed_work(&muic_if->ccic_work, msecs_to_jiffies(4000));
778 return;
779 }
780
781 pr_info("%s: done.\n", __func__);
782}
783
784void muic_manager_register_notifier(struct muic_interface_t *muic_if)
785{
786 int ret = 0;
787
788 pr_info("%s: Registering CCIC_NOTIFY_DEV_MUIC.\n", __func__);
789
790 muic_manager_init_dev_desc(muic_if);
791
792#ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER
793 ret = manager_notifier_register(&muic_if->manager_nb,
794 muic_manager_handle_notification,
795 MANAGER_NOTIFY_CCIC_MUIC);
796#else
797 ret = ccic_notifier_register(&muic_if->ccic_nb,
798 muic_manager_handle_notification,
799 CCIC_NOTIFY_DEV_MUIC);
800#endif
801
802 if (ret < 0) {
803 pr_info("%s: CCIC Noti. is not ready. Try again in 8sec...\n", __func__);
804 INIT_DELAYED_WORK(&muic_if->ccic_work, _muic_delayed_notifier);
805 schedule_delayed_work(&muic_if->ccic_work, msecs_to_jiffies(8000));
806 return;
807 }
808
809 pr_info("%s: done.\n", __func__);
810}
811#endif
812
813struct muic_interface_t *muic_manager_init(void *pdata, void *drv_data)
814{
815#ifdef CONFIG_IFCONN_NOTIFIER
816 int ret;
817#endif
818 struct muic_interface_t *muic_if;
819 struct ccic_desc_t *ccic;
820
821 pr_info("%s\n", __func__);
822
823 muic_if = kzalloc(sizeof(*muic_if), GFP_KERNEL);
824 if (unlikely(!muic_if)) {
825 pr_err("%s failed to allocate driver data\n", __func__);
826 return NULL;
827 }
828
829 ccic = kzalloc(sizeof(*ccic), GFP_KERNEL);
830 if (unlikely(!ccic)) {
831 pr_err("%s failed to allocate driver data\n", __func__);
832 goto err_ccic_alloc;
833 }
834
835 muic_if->ccic = ccic;
836 muic_if->muic_data = drv_data;
837 muic_if->pdata = pdata;
838 muic_if->ccic->rid_desc = ccic_rid_tbl;
839 muic_if->is_afc_reset = false;
840 muic_if->is_dcp_charger = false;
841 muic_if->opmode = get_ccic_info() & 0xF;
842 muic_if->is_dcdtmr_intr = false;
843#ifdef CONFIG_IFCONN_NOTIFIER
844 ret = ifconn_notifier_register(&muic_if->nb,
845 muic_manager_handle_notification,
846 IFCONN_NOTIFY_MUIC, IFCONN_NOTIFY_CCIC);
847 ret = ifconn_notifier_register(&muic_if->nb,
848 muic_manager_handle_notification,
849 IFCONN_NOTIFY_MUIC, IFCONN_NOTIFY_PDIC);
850 if (ret) {
851 pr_err("%s failed register ifconn notifier\n", __func__);
852 goto err_reg_noti;
853 }
854#else
855 if (muic_if->opmode & OPMODE_DEVICE)
856 muic_manager_register_notifier(muic_if);
857 else
858 pr_info("OPMODE_MUIC CCIC NOTIFIER is not used\n");
859#endif
860 return muic_if;
861#ifdef CONFIG_IFCONN_NOTIFIER
862err_reg_noti:
863 kfree(ccic);
864#endif
865err_ccic_alloc:
866 kfree(muic_if);
867 return NULL;
868}
869
870void muic_manager_exit(struct muic_interface_t *muic_if)
871{
872 kfree(muic_if);
873}