USB: Fix usb battery charger detect bug.
[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 /****** GET and SET REGISTER FIELDS IN GRF UOC ******/
20
21 #define BC_GET(x) grf_uoc_get_field(&pBC_UOC_FIELDS[x])
22 #define BC_SET(x, v) grf_uoc_set_field(&pBC_UOC_FIELDS[x], v)
23
24 uoc_field_t *pBC_UOC_FIELDS;
25 static void *pGRF_BASE;
26 int rk_usb_charger_status = USB_BC_TYPE_DISCNT;
27
28 /****** GET REGISTER FIELD INFO FROM Device Tree ******/
29
30 static inline void *get_grf_base(struct device_node *np)
31 {
32         void *grf_base = of_iomap(of_get_parent(np), 0);
33
34         if (of_machine_is_compatible("rockchip,rk3188"))
35                 grf_base -= 0xac;
36         else if (of_machine_is_compatible("rockchip,rk3288"))
37                 grf_base -= 0x284;
38
39         return grf_base;
40 }
41
42 void grf_uoc_set_field(uoc_field_t *field, u32 value)
43 {
44         if (!uoc_field_valid(field))
45                 return;
46         grf_uoc_set(pGRF_BASE, field->b.offset, field->b.bitmap, field->b.mask,
47                     value);
48 }
49
50 u32 grf_uoc_get_field(uoc_field_t *field)
51 {
52         return grf_uoc_get(pGRF_BASE, field->b.offset, field->b.bitmap,
53                            field->b.mask);
54 }
55
56 static inline int uoc_init_field(struct device_node *np, const char *name,
57                                  uoc_field_t *f)
58 {
59         of_property_read_u32_array(np, name, f->array, 3);
60         /* printk("usb battery charger detect: uoc_init_field: 0x%08x %d %d \n",
61          *        f->b.offset,f->b.bitmap,f->b.mask);*/
62         return 0;
63 }
64
65 static inline void uoc_init_synop(struct device_node *np)
66 {
67         pBC_UOC_FIELDS =
68             (uoc_field_t *) kzalloc(SYNOP_BC_MAX * sizeof(uoc_field_t),
69                                     GFP_ATOMIC);
70
71         uoc_init_field(np, "rk_usb,bvalid", &pBC_UOC_FIELDS[SYNOP_BC_BVALID]);
72         uoc_init_field(np, "rk_usb,iddig", &pBC_UOC_FIELDS[SYNOP_BC_IDDIG]);
73         uoc_init_field(np, "rk_usb,dcdenb", &pBC_UOC_FIELDS[SYNOP_BC_DCDENB]);
74         uoc_init_field(np, "rk_usb,vdatsrcenb",
75                        &pBC_UOC_FIELDS[SYNOP_BC_VDATSRCENB]);
76         uoc_init_field(np, "rk_usb,vdatdetenb",
77                        &pBC_UOC_FIELDS[SYNOP_BC_VDATDETENB]);
78         uoc_init_field(np, "rk_usb,chrgsel", &pBC_UOC_FIELDS[SYNOP_BC_CHRGSEL]);
79         uoc_init_field(np, "rk_usb,chgdet", &pBC_UOC_FIELDS[SYNOP_BC_CHGDET]);
80         uoc_init_field(np, "rk_usb,fsvplus", &pBC_UOC_FIELDS[SYNOP_BC_FSVPLUS]);
81         uoc_init_field(np, "rk_usb,fsvminus",
82                        &pBC_UOC_FIELDS[SYNOP_BC_FSVMINUS]);
83 }
84
85 static inline void uoc_init_rk(struct device_node *np)
86 {
87         pBC_UOC_FIELDS =
88             (uoc_field_t *) kzalloc(RK_BC_MAX * sizeof(uoc_field_t),
89                                     GFP_ATOMIC);
90
91         uoc_init_field(np, "rk_usb,bvalid", &pBC_UOC_FIELDS[RK_BC_BVALID]);
92         uoc_init_field(np, "rk_usb,iddig", &pBC_UOC_FIELDS[RK_BC_IDDIG]);
93         uoc_init_field(np, "rk_usb,line", &pBC_UOC_FIELDS[RK_BC_LINESTATE]);
94         uoc_init_field(np, "rk_usb,softctrl", &pBC_UOC_FIELDS[RK_BC_SOFTCTRL]);
95         uoc_init_field(np, "rk_usb,opmode", &pBC_UOC_FIELDS[RK_BC_OPMODE]);
96         uoc_init_field(np, "rk_usb,xcvrsel", &pBC_UOC_FIELDS[RK_BC_XCVRSELECT]);
97         uoc_init_field(np, "rk_usb,termsel", &pBC_UOC_FIELDS[RK_BC_TERMSELECT]);
98 }
99
100 static inline void uoc_init_inno(struct device_node *np)
101 {
102         ;
103 }
104
105 /****** BATTERY CHARGER DETECT FUNCTIONS ******/
106
107 int usb_battery_charger_detect_rk(bool wait)
108 {
109
110         int port_type = USB_BC_TYPE_DISCNT;
111
112         if (BC_GET(RK_BC_BVALID) &&
113             BC_GET(RK_BC_IDDIG)) {
114                 mdelay(10);
115                 BC_SET(RK_BC_SOFTCTRL, 1);
116                 BC_SET(RK_BC_OPMODE, 0);
117                 BC_SET(RK_BC_XCVRSELECT, 1);
118                 BC_SET(RK_BC_TERMSELECT, 1);
119
120                 mdelay(1);
121                 switch (BC_GET(RK_BC_LINESTATE)) {
122                 case 1:
123                         port_type = USB_BC_TYPE_SDP;
124                         break;
125
126                 case 3:
127                         port_type = USB_BC_TYPE_DCP;
128                         break;
129
130                 default:
131                         port_type = USB_BC_TYPE_SDP;
132                         /* printk("%s linestate = %d bad status\n",
133                          *        __func__, BC_GET(RK_BC_LINESTATE)); */
134                 }
135
136         }
137         BC_SET(RK_BC_SOFTCTRL, 0);
138
139         /* printk("%s , battery_charger_detect %d\n",
140          *        __func__, port_type); */
141         return port_type;
142 }
143
144 int usb_battery_charger_detect_inno(bool wait)
145 {
146
147         return -1;
148 }
149
150 /* When do BC detect PCD pull-up register should be disabled  */
151 /* wait wait for dcd timeout 900ms */
152 int usb_battery_charger_detect_synop(bool wait)
153 {
154         int port_type = USB_BC_TYPE_DISCNT;
155         int dcd_state = DCD_POSITIVE;
156         int timeout = 0, i = 0;
157
158         /* VBUS Valid detect */
159         if (BC_GET(SYNOP_BC_BVALID) &&
160             BC_GET(SYNOP_BC_IDDIG)) {
161                 if (wait) {
162                         /* Do DCD */
163                         dcd_state = DCD_TIMEOUT;
164                         BC_SET(SYNOP_BC_DCDENB, 1);
165                         timeout = T_DCD_TIMEOUT;
166                         while (timeout--) {
167                                 if (!BC_GET(SYNOP_BC_FSVPLUS))
168                                         i++;
169                                 if (i >= 3) {
170                                         /* It is a filter here to assure data
171                                          * lines contacted for at least 3ms */
172                                         dcd_state = DCD_POSITIVE;
173                                         break;
174                                 }
175
176                                 mdelay(1);
177                         }
178                         BC_SET(SYNOP_BC_DCDENB, 0);
179                 } else {
180                         dcd_state = DCD_PASSED;
181                 }
182                 if (dcd_state == DCD_TIMEOUT) {
183                         port_type = USB_BC_TYPE_UNKNOW;
184                         goto out;
185                 }
186
187                 /* Turn on VDPSRC */
188                 /* Primary Detection */
189                 BC_SET(SYNOP_BC_VDATSRCENB, 1);
190                 BC_SET(SYNOP_BC_VDATDETENB, 1);
191                 BC_SET(SYNOP_BC_CHRGSEL, 0);
192
193                 udelay(T_BC_CHGDET_VALID);
194
195                 /* SDP and CDP/DCP distinguish */
196                 if (BC_GET(SYNOP_BC_CHGDET)) {
197                         /* Turn off VDPSRC */
198                         BC_SET(SYNOP_BC_VDATSRCENB, 0);
199                         BC_SET(SYNOP_BC_VDATDETENB, 0);
200
201                         udelay(T_BC_CHGDET_VALID);
202
203                         /* Turn on VDMSRC */
204                         BC_SET(SYNOP_BC_VDATSRCENB, 1);
205                         BC_SET(SYNOP_BC_VDATDETENB, 1);
206                         BC_SET(SYNOP_BC_CHRGSEL, 1);
207                         udelay(T_BC_CHGDET_VALID);
208                         if (BC_GET(SYNOP_BC_CHGDET))
209                                 port_type = USB_BC_TYPE_DCP;
210                         else
211                                 port_type = USB_BC_TYPE_CDP;
212                 } else {
213                         port_type = USB_BC_TYPE_SDP;
214                 }
215                 BC_SET(SYNOP_BC_VDATSRCENB, 0);
216                 BC_SET(SYNOP_BC_VDATDETENB, 0);
217                 BC_SET(SYNOP_BC_CHRGSEL, 0);
218
219         }
220 out:
221         printk("%s , battery_charger_detect %d, %s DCD, dcd_state = %d\n",
222                __func__, port_type, wait ? "wait" : "pass", dcd_state);
223         return port_type;
224 }
225
226 int usb_battery_charger_detect(bool wait)
227 {
228         static struct device_node *np;
229         if (!np)
230                 np = of_find_node_by_name(NULL, "usb_bc");
231         if (!np)
232                 goto fail;
233         if (!pGRF_BASE)
234                 pGRF_BASE = get_grf_base(np);
235
236         if (of_device_is_compatible(np, "rockchip,ctrl")) {
237                 if (!pBC_UOC_FIELDS)
238                         uoc_init_rk(np);
239                 return usb_battery_charger_detect_rk(wait);
240         }
241
242         else if (of_device_is_compatible(np, "synopsys,phy")) {
243                 if (!pBC_UOC_FIELDS)
244                         uoc_init_synop(np);
245                 return usb_battery_charger_detect_synop(wait);
246         }
247
248         else if (of_device_is_compatible(np, "inno,phy")) {
249                 if (!pBC_UOC_FIELDS)
250                         uoc_init_inno(np);
251                 return usb_battery_charger_detect_inno(wait);
252         }
253 fail:
254         return -1;
255 }
256
257 EXPORT_SYMBOL(usb_battery_charger_detect);
258
259 int dwc_otg_check_dpdm(bool wait)
260 {
261         static struct device_node *np;
262         if (!np)
263                 np = of_find_node_by_name(NULL, "usb_bc");
264         if (!np)
265                 return -1;
266         if (!pGRF_BASE)
267                 pGRF_BASE = get_grf_base(np);
268
269         if (of_device_is_compatible(np, "rockchip,ctrl")) {
270                 if (!pBC_UOC_FIELDS)
271                         uoc_init_rk(np);
272                 if (!BC_GET(RK_BC_BVALID) ||
273                     !BC_GET(RK_BC_IDDIG))
274                         rk_usb_charger_status = USB_BC_TYPE_DISCNT;
275
276         } else if (of_device_is_compatible(np, "synopsys,phy")) {
277                 if (!pBC_UOC_FIELDS)
278                         uoc_init_synop(np);
279                 if (!BC_GET(SYNOP_BC_BVALID) ||
280                     !BC_GET(SYNOP_BC_IDDIG))
281                         rk_usb_charger_status = USB_BC_TYPE_DISCNT;
282
283         } else if (of_device_is_compatible(np, "inno,phy")) {
284                 if (!pBC_UOC_FIELDS)
285                         uoc_init_inno(np);
286         }
287
288         return rk_usb_charger_status;
289 }
290 EXPORT_SYMBOL(dwc_otg_check_dpdm);
291
292 /* CALL BACK FUNCTION for USB CHARGER TYPE CHANGED */
293
294 void usb20otg_battery_charger_detect_cb(int charger_type_new)
295 {
296         static int charger_type = USB_BC_TYPE_DISCNT;
297         if (charger_type != charger_type_new) {
298                 switch (charger_type_new) {
299                 case USB_BC_TYPE_DISCNT:
300                         break;
301
302                 case USB_BC_TYPE_SDP:
303                         break;
304
305                 case USB_BC_TYPE_DCP:
306                         break;
307
308                 case USB_BC_TYPE_CDP:
309                         break;
310
311                 case USB_BC_TYPE_UNKNOW:
312                         break;
313
314                 default:
315                         break;
316                 }
317
318                 /* printk("%s , battery_charger_detect %d\n",
319                  *        __func__, charger_type_new);*/
320         }
321         charger_type = charger_type_new;
322 }