usb: dwc_otg_310: fix usb vbus power controlled by pmic
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / usbdev_bc.c
1 /*
2  * Copyright (C) 2013-2014 ROCKCHIP, Inc.
3  * Author: LIYUNZHI  <lyz@rock-chips.com>
4  * Data: 2014-3-14
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include "usbdev_rk.h"
18
19 char *bc_string[USB_BC_TYPE_MAX] = {"DISCONNECT",
20                                     "Stander Downstream Port",
21                                     "Dedicated Charging Port",
22                                     "Charging Downstream Port",
23                                     "UNKNOW"};
24
25 /****** GET and SET REGISTER FIELDS IN GRF UOC ******/
26 #define BC_GET(x) grf_uoc_get_field(&pBC_UOC_FIELDS[x])
27 #define BC_SET(x, v) grf_uoc_set_field(&pBC_UOC_FIELDS[x], v)
28
29 uoc_field_t *pBC_UOC_FIELDS;
30 static void *pGRF_BASE;
31 static void *pGRF_REGMAP;
32 DEFINE_MUTEX(bc_mutex);
33
34 static enum bc_port_type usb_charger_status = USB_BC_TYPE_DISCNT;
35
36 /****** GET REGISTER FIELD INFO FROM Device Tree ******/
37
38 static inline void *get_grf_base(struct device_node *np)
39 {
40         void *grf_base = of_iomap(of_get_parent(np), 0);
41
42         if (of_machine_is_compatible("rockchip,rk3188"))
43                 grf_base -= 0xac;
44         else if (of_machine_is_compatible("rockchip,rk3288"))
45                 grf_base -= 0x284;
46
47         return grf_base;
48 }
49
50 static inline struct regmap *get_grf_regmap(struct device_node *np)
51 {
52         struct regmap *grf;
53
54         grf = syscon_regmap_lookup_by_phandle(of_get_parent(np),
55                                               "rockchip,grf");
56         if (IS_ERR(grf))
57                 return NULL;
58         return grf;
59 }
60
61 void grf_uoc_set_field(uoc_field_t *field, u32 value)
62 {
63         if (!uoc_field_valid(field))
64                 return;
65
66         if (pGRF_BASE) {
67                 grf_uoc_set(pGRF_BASE, field->b.offset, field->b.bitmap,
68                             field->b.mask, value);
69         } else if (pGRF_REGMAP) {
70                 regmap_grf_uoc_set(pGRF_REGMAP, field->b.offset,
71                                    field->b.bitmap,
72                                    field->b.mask, value);
73         }
74 }
75
76 u32 grf_uoc_get_field(uoc_field_t *field)
77 {
78         if (pGRF_BASE) {
79                 return grf_uoc_get(pGRF_BASE, field->b.offset, field->b.bitmap,
80                                    field->b.mask);
81         } else if (pGRF_REGMAP) {
82                 return regmap_grf_uoc_get(pGRF_REGMAP, field->b.offset,
83                                           field->b.bitmap, field->b.mask);
84         } else {
85                 return 0;
86         }
87 }
88
89 static inline int uoc_init_field(struct device_node *np, const char *name,
90                                  uoc_field_t *f)
91 {
92         of_property_read_u32_array(np, name, f->array, 3);
93         /* printk("usb battery charger detect: uoc_init_field: 0x%08x %d %d \n",
94          *        f->b.offset,f->b.bitmap,f->b.mask);*/
95         return 0;
96 }
97
98 static inline void uoc_init_synop(struct device_node *np)
99 {
100         pBC_UOC_FIELDS =
101             (uoc_field_t *) kzalloc(SYNOP_BC_MAX * sizeof(uoc_field_t),
102                                     GFP_ATOMIC);
103
104         uoc_init_field(np, "rk_usb,bvalid", &pBC_UOC_FIELDS[SYNOP_BC_BVALID]);
105         uoc_init_field(np, "rk_usb,iddig", &pBC_UOC_FIELDS[SYNOP_BC_IDDIG]);
106         uoc_init_field(np, "rk_usb,dcdenb", &pBC_UOC_FIELDS[SYNOP_BC_DCDENB]);
107         uoc_init_field(np, "rk_usb,vdatsrcenb",
108                        &pBC_UOC_FIELDS[SYNOP_BC_VDATSRCENB]);
109         uoc_init_field(np, "rk_usb,vdatdetenb",
110                        &pBC_UOC_FIELDS[SYNOP_BC_VDATDETENB]);
111         uoc_init_field(np, "rk_usb,chrgsel", &pBC_UOC_FIELDS[SYNOP_BC_CHRGSEL]);
112         uoc_init_field(np, "rk_usb,chgdet", &pBC_UOC_FIELDS[SYNOP_BC_CHGDET]);
113         uoc_init_field(np, "rk_usb,fsvplus", &pBC_UOC_FIELDS[SYNOP_BC_FSVPLUS]);
114         uoc_init_field(np, "rk_usb,fsvminus",
115                        &pBC_UOC_FIELDS[SYNOP_BC_FSVMINUS]);
116 }
117
118 static inline void uoc_init_rk(struct device_node *np)
119 {
120         pBC_UOC_FIELDS =
121             (uoc_field_t *) kzalloc(RK_BC_MAX * sizeof(uoc_field_t),
122                                     GFP_ATOMIC);
123
124         uoc_init_field(np, "rk_usb,bvalid", &pBC_UOC_FIELDS[RK_BC_BVALID]);
125         uoc_init_field(np, "rk_usb,iddig", &pBC_UOC_FIELDS[RK_BC_IDDIG]);
126         uoc_init_field(np, "rk_usb,line", &pBC_UOC_FIELDS[RK_BC_LINESTATE]);
127         uoc_init_field(np, "rk_usb,softctrl", &pBC_UOC_FIELDS[RK_BC_SOFTCTRL]);
128         uoc_init_field(np, "rk_usb,opmode", &pBC_UOC_FIELDS[RK_BC_OPMODE]);
129         uoc_init_field(np, "rk_usb,xcvrsel", &pBC_UOC_FIELDS[RK_BC_XCVRSELECT]);
130         uoc_init_field(np, "rk_usb,termsel", &pBC_UOC_FIELDS[RK_BC_TERMSELECT]);
131 }
132
133 static inline void uoc_init_inno(struct device_node *np)
134 {
135         pBC_UOC_FIELDS = (uoc_field_t *)
136                          kzalloc(INNO_BC_MAX * sizeof(uoc_field_t), GFP_ATOMIC);
137
138         uoc_init_field(np, "rk_usb,bvalid",
139                            &pBC_UOC_FIELDS[INNO_BC_BVALID]);
140         uoc_init_field(np, "rk_usb,iddig",
141                            &pBC_UOC_FIELDS[INNO_BC_IDDIG]);
142         uoc_init_field(np, "rk_usb,vdmsrcen",
143                            &pBC_UOC_FIELDS[INNO_BC_VDMSRCEN]);
144         uoc_init_field(np, "rk_usb,vdpsrcen",
145                            &pBC_UOC_FIELDS[INNO_BC_VDPSRCEN]);
146         uoc_init_field(np, "rk_usb,rdmpden",
147                            &pBC_UOC_FIELDS[INNO_BC_RDMPDEN]);
148         uoc_init_field(np, "rk_usb,idpsrcen",
149                            &pBC_UOC_FIELDS[INNO_BC_IDPSRCEN]);
150         uoc_init_field(np, "rk_usb,idmsinken",
151                            &pBC_UOC_FIELDS[INNO_BC_IDMSINKEN]);
152         uoc_init_field(np, "rk_usb,idpsinken",
153                            &pBC_UOC_FIELDS[INNO_BC_IDPSINKEN]);
154         uoc_init_field(np, "rk_usb,dpattach",
155                            &pBC_UOC_FIELDS[INNO_BC_DPATTACH]);
156         uoc_init_field(np, "rk_usb,cpdet",
157                            &pBC_UOC_FIELDS[INNO_BC_CPDET]);
158         uoc_init_field(np, "rk_usb,dcpattach",
159                            &pBC_UOC_FIELDS[INNO_BC_DCPATTACH]);
160 }
161
162 /****** BATTERY CHARGER DETECT FUNCTIONS ******/
163 bool is_connected(void)
164 {
165         if (!pGRF_BASE && !pGRF_REGMAP)
166                 return false;
167         if (BC_GET(BC_BVALID) && BC_GET(BC_IDDIG))
168                 return true;
169         return false;
170 }
171
172 enum bc_port_type usb_battery_charger_detect_rk(bool wait)
173 {
174
175         enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
176
177         if (BC_GET(RK_BC_BVALID) &&
178             BC_GET(RK_BC_IDDIG)) {
179                 mdelay(10);
180                 BC_SET(RK_BC_SOFTCTRL, 1);
181                 BC_SET(RK_BC_OPMODE, 0);
182                 BC_SET(RK_BC_XCVRSELECT, 1);
183                 BC_SET(RK_BC_TERMSELECT, 1);
184
185                 mdelay(1);
186                 switch (BC_GET(RK_BC_LINESTATE)) {
187                 case 1:
188                         port_type = USB_BC_TYPE_SDP;
189                         break;
190
191                 case 3:
192                         port_type = USB_BC_TYPE_DCP;
193                         break;
194
195                 default:
196                         port_type = USB_BC_TYPE_SDP;
197                         /* printk("%s linestate = %d bad status\n",
198                          *        __func__, BC_GET(RK_BC_LINESTATE)); */
199                 }
200
201         }
202         BC_SET(RK_BC_SOFTCTRL, 0);
203
204         /* printk("%s , battery_charger_detect %d\n",
205          *        __func__, port_type); */
206         return port_type;
207 }
208
209 enum bc_port_type usb_battery_charger_detect_inno(bool wait)
210 {
211         enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
212         int dcd_state = DCD_POSITIVE;
213         int timeout = 0, i = 0, filted_cpdet = 0;
214
215         /* VBUS Valid detect */
216         if (BC_GET(INNO_BC_BVALID) &&
217                 BC_GET(INNO_BC_IDDIG)) {
218                 if (wait) {
219                         /* Do DCD */
220                         dcd_state = DCD_TIMEOUT;
221                         BC_SET(INNO_BC_RDMPDEN, 1);
222                         BC_SET(INNO_BC_IDPSRCEN, 1);
223                         timeout = T_DCD_TIMEOUT;
224                         while (timeout--) {
225                                 if (BC_GET(INNO_BC_DPATTACH))
226                                         i++;
227                                 if (i >= 3) {
228                                         /* It is a filter here to assure data
229                                          * lines contacted for at least 3ms */
230                                         dcd_state = DCD_POSITIVE;
231                                         break;
232                                 }
233                                 mdelay(1);
234                         }
235                         BC_SET(INNO_BC_RDMPDEN, 0);
236                         BC_SET(INNO_BC_IDPSRCEN, 0);
237                 } else {
238                         dcd_state = DCD_PASSED;
239                 }
240                 if (dcd_state == DCD_TIMEOUT) {
241                         port_type = USB_BC_TYPE_UNKNOW;
242                         goto out;
243                 }
244
245                 /* Turn on VDPSRC */
246                 /* Primary Detection */
247                 BC_SET(INNO_BC_VDPSRCEN, 1);
248                 BC_SET(INNO_BC_IDMSINKEN, 1);
249                 udelay(T_BC_CHGDET_VALID);
250
251                 /*
252                  * Filter for Primary Detection,
253                  * double check CPDET field
254                  */
255                 timeout = T_BC_CHGDET_VALID;
256                 while(timeout--) {
257                         /*
258                          * In rapidly hotplug case, it's more likely to
259                          * distinguish SDP as DCP/CDP because of line
260                          * bounce
261                          */
262                         filted_cpdet += (BC_GET(INNO_BC_CPDET) ? 1 : -2);
263                         udelay(1);
264                 }
265                 /* SDP and CDP/DCP distinguish */
266                 if (filted_cpdet > 0) {
267                         /* Turn off VDPSRC */
268                         BC_SET(INNO_BC_VDPSRCEN, 0);
269                         BC_SET(INNO_BC_IDMSINKEN, 0);
270
271                         udelay(T_BC_CHGDET_VALID);
272
273                         /* Turn on VDMSRC */
274                         BC_SET(INNO_BC_VDMSRCEN, 1);
275                         BC_SET(INNO_BC_IDPSINKEN, 1);
276                         udelay(T_BC_CHGDET_VALID);
277                         if (BC_GET(INNO_BC_DCPATTACH))
278                                 port_type = USB_BC_TYPE_DCP;
279                         else
280                                 port_type = USB_BC_TYPE_CDP;
281                 } else {
282                         port_type = USB_BC_TYPE_SDP;
283                 }
284
285                 BC_SET(INNO_BC_VDPSRCEN, 0);
286                 BC_SET(INNO_BC_IDMSINKEN, 0);
287                 BC_SET(INNO_BC_VDMSRCEN, 0);
288                 BC_SET(INNO_BC_IDPSINKEN, 0);
289
290         }
291 out:
292         /*
293         printk("%s, Charger type %s, %s DCD, dcd_state = %d\n", __func__,
294                bc_string[port_type], wait ? "wait" : "pass", dcd_state);
295         */
296         return port_type;
297
298 }
299
300 /* When do BC detect PCD pull-up register should be disabled  */
301 /* wait wait for dcd timeout 900ms */
302 enum bc_port_type usb_battery_charger_detect_synop(bool wait)
303 {
304         enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
305         int dcd_state = DCD_POSITIVE;
306         int timeout = 0, i = 0;
307
308         /* VBUS Valid detect */
309         if (BC_GET(SYNOP_BC_BVALID) &&
310             BC_GET(SYNOP_BC_IDDIG)) {
311                 if (wait) {
312                         /* Do DCD */
313                         dcd_state = DCD_TIMEOUT;
314                         BC_SET(SYNOP_BC_DCDENB, 1);
315                         timeout = T_DCD_TIMEOUT;
316                         while (timeout--) {
317                                 if (!BC_GET(SYNOP_BC_FSVPLUS))
318                                         i++;
319                                 if (i >= 3) {
320                                         /* It is a filter here to assure data
321                                          * lines contacted for at least 3ms */
322                                         dcd_state = DCD_POSITIVE;
323                                         break;
324                                 }
325
326                                 mdelay(1);
327                         }
328                         BC_SET(SYNOP_BC_DCDENB, 0);
329                 } else {
330                         dcd_state = DCD_PASSED;
331                 }
332                 if (dcd_state == DCD_TIMEOUT) {
333                         port_type = USB_BC_TYPE_UNKNOW;
334                         goto out;
335                 }
336
337                 /* Turn on VDPSRC */
338                 /* Primary Detection */
339                 BC_SET(SYNOP_BC_VDATSRCENB, 1);
340                 BC_SET(SYNOP_BC_VDATDETENB, 1);
341                 BC_SET(SYNOP_BC_CHRGSEL, 0);
342
343                 udelay(T_BC_CHGDET_VALID);
344
345                 /* SDP and CDP/DCP distinguish */
346                 if (BC_GET(SYNOP_BC_CHGDET)) {
347                         /* Turn off VDPSRC */
348                         BC_SET(SYNOP_BC_VDATSRCENB, 0);
349                         BC_SET(SYNOP_BC_VDATDETENB, 0);
350
351                         udelay(T_BC_CHGDET_VALID);
352
353                         /* Turn on VDMSRC */
354                         BC_SET(SYNOP_BC_VDATSRCENB, 1);
355                         BC_SET(SYNOP_BC_VDATDETENB, 1);
356                         BC_SET(SYNOP_BC_CHRGSEL, 1);
357                         udelay(T_BC_CHGDET_VALID);
358                         if (BC_GET(SYNOP_BC_CHGDET))
359                                 port_type = USB_BC_TYPE_DCP;
360                         else
361                                 port_type = USB_BC_TYPE_CDP;
362                 } else {
363                         port_type = USB_BC_TYPE_SDP;
364                 }
365                 BC_SET(SYNOP_BC_VDATSRCENB, 0);
366                 BC_SET(SYNOP_BC_VDATDETENB, 0);
367                 BC_SET(SYNOP_BC_CHRGSEL, 0);
368
369         }
370 out:
371         /*
372         printk("%s, Charger type %s, %s DCD, dcd_state = %d\n", __func__,
373                bc_string[port_type], wait ? "wait" : "pass", dcd_state);
374         */
375         return port_type;
376 }
377
378 enum bc_port_type usb_battery_charger_detect(bool wait)
379 {
380         static struct device_node *np;
381         enum bc_port_type ret = USB_BC_TYPE_DISCNT;
382
383         might_sleep();
384
385         if (!np)
386                 np = of_find_node_by_name(NULL, "usb_bc");
387         if (!np)
388                 return -1;
389         if (!pGRF_BASE && !pGRF_REGMAP) {
390                 pGRF_BASE = get_grf_base(np);
391                 pGRF_REGMAP = get_grf_regmap(np);
392         }
393
394         mutex_lock(&bc_mutex);
395         if (of_device_is_compatible(np, "rockchip,ctrl")) {
396                 if (!pBC_UOC_FIELDS)
397                         uoc_init_rk(np);
398                 ret = usb_battery_charger_detect_rk(wait);
399         }
400
401         else if (of_device_is_compatible(np, "synopsys,phy")) {
402                 if (!pBC_UOC_FIELDS)
403                         uoc_init_synop(np);
404                 ret = usb_battery_charger_detect_synop(wait);
405         }
406
407         else if (of_device_is_compatible(np, "inno,phy")) {
408                 if (!pBC_UOC_FIELDS)
409                         uoc_init_inno(np);
410                 ret = usb_battery_charger_detect_inno(wait);
411         }
412         if (ret == USB_BC_TYPE_UNKNOW)
413                 ret = USB_BC_TYPE_DCP;
414         mutex_unlock(&bc_mutex);
415         rk_battery_charger_detect_cb(ret);
416         return ret;
417 }
418
419 int dwc_otg_check_dpdm(bool wait)
420 {
421         return (is_connected() ? usb_charger_status : USB_BC_TYPE_DISCNT);
422 }
423 EXPORT_SYMBOL(dwc_otg_check_dpdm);
424
425 /* Call back function for USB charger type changed */
426 static ATOMIC_NOTIFIER_HEAD(rk_bc_notifier);
427
428 int rk_bc_detect_notifier_register(struct notifier_block *nb,
429                                    enum bc_port_type *type)
430 {
431         *type = (int)usb_battery_charger_detect(0);
432         return atomic_notifier_chain_register(&rk_bc_notifier, nb);
433 }
434 EXPORT_SYMBOL(rk_bc_detect_notifier_register);
435
436 int rk_bc_detect_notifier_unregister(struct notifier_block *nb)
437 {
438         return atomic_notifier_chain_unregister(&rk_bc_notifier, nb);
439 }
440 EXPORT_SYMBOL(rk_bc_detect_notifier_unregister);
441
442 void rk_bc_detect_notifier_callback(int bc_mode)
443 {
444         atomic_notifier_call_chain(&rk_bc_notifier,bc_mode, NULL);
445 }
446
447 void rk_battery_charger_detect_cb(int new_type)
448 {
449         might_sleep();
450
451         if (usb_charger_status != new_type) {
452                 printk("%s , battery_charger_detect %d\n", __func__, new_type);
453                 atomic_notifier_call_chain(&rk_bc_notifier, new_type, NULL);
454         }
455         mutex_lock(&bc_mutex);
456         usb_charger_status = new_type;
457         mutex_unlock(&bc_mutex);
458 }