2 * Copyright (C) 2013-2014 ROCKCHIP, Inc.
3 * Author: LIYUNZHI <lyz@rock-chips.com>
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.
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.
17 #include "usbdev_rk.h"
19 /****** GET and SET REGISTER FIELDS IN GRF UOC ******/
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)
24 uoc_field_t *pBC_UOC_FIELDS;
25 static void *pGRF_BASE;
26 int rk_usb_charger_status = USB_BC_TYPE_DISCNT;
28 /****** GET REGISTER FIELD INFO FROM Device Tree ******/
30 static inline void *get_grf_base(struct device_node *np)
32 void *grf_base = of_iomap(of_get_parent(np), 0);
34 if (of_machine_is_compatible("rockchip,rk3188"))
36 else if (of_machine_is_compatible("rockchip,rk3288"))
42 void grf_uoc_set_field(uoc_field_t *field, u32 value)
44 if (!uoc_field_valid(field))
46 grf_uoc_set(pGRF_BASE, field->b.offset, field->b.bitmap, field->b.mask,
50 u32 grf_uoc_get_field(uoc_field_t *field)
52 return grf_uoc_get(pGRF_BASE, field->b.offset, field->b.bitmap,
56 static inline int uoc_init_field(struct device_node *np, const char *name,
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);*/
65 static inline void uoc_init_synop(struct device_node *np)
68 (uoc_field_t *) kzalloc(SYNOP_BC_MAX * sizeof(uoc_field_t),
71 uoc_init_field(np, "rk_usb,bvalid", &pBC_UOC_FIELDS[SYNOP_BC_BVALID]);
72 uoc_init_field(np, "rk_usb,dcdenb", &pBC_UOC_FIELDS[SYNOP_BC_DCDENB]);
73 uoc_init_field(np, "rk_usb,vdatsrcenb",
74 &pBC_UOC_FIELDS[SYNOP_BC_VDATSRCENB]);
75 uoc_init_field(np, "rk_usb,vdatdetenb",
76 &pBC_UOC_FIELDS[SYNOP_BC_VDATDETENB]);
77 uoc_init_field(np, "rk_usb,chrgsel", &pBC_UOC_FIELDS[SYNOP_BC_CHRGSEL]);
78 uoc_init_field(np, "rk_usb,chgdet", &pBC_UOC_FIELDS[SYNOP_BC_CHGDET]);
79 uoc_init_field(np, "rk_usb,fsvplus", &pBC_UOC_FIELDS[SYNOP_BC_FSVPLUS]);
80 uoc_init_field(np, "rk_usb,fsvminus",
81 &pBC_UOC_FIELDS[SYNOP_BC_FSVMINUS]);
84 static inline void uoc_init_rk(struct device_node *np)
87 (uoc_field_t *) kzalloc(RK_BC_MAX * sizeof(uoc_field_t),
90 uoc_init_field(np, "rk_usb,bvalid", &pBC_UOC_FIELDS[RK_BC_BVALID]);
91 uoc_init_field(np, "rk_usb,line", &pBC_UOC_FIELDS[RK_BC_LINESTATE]);
92 uoc_init_field(np, "rk_usb,softctrl", &pBC_UOC_FIELDS[RK_BC_SOFTCTRL]);
93 uoc_init_field(np, "rk_usb,opmode", &pBC_UOC_FIELDS[RK_BC_OPMODE]);
94 uoc_init_field(np, "rk_usb,xcvrsel", &pBC_UOC_FIELDS[RK_BC_XCVRSELECT]);
95 uoc_init_field(np, "rk_usb,termsel", &pBC_UOC_FIELDS[RK_BC_TERMSELECT]);
98 static inline void uoc_init_inno(struct device_node *np)
103 /****** BATTERY CHARGER DETECT FUNCTIONS ******/
105 int usb_battery_charger_detect_rk(bool wait)
108 int port_type = USB_BC_TYPE_DISCNT;
110 if (BC_GET(RK_BC_BVALID)) {
112 BC_SET(RK_BC_SOFTCTRL, 1);
113 BC_SET(RK_BC_OPMODE, 0);
114 BC_SET(RK_BC_XCVRSELECT, 1);
115 BC_SET(RK_BC_TERMSELECT, 1);
118 switch (BC_GET(RK_BC_LINESTATE)) {
120 port_type = USB_BC_TYPE_SDP;
124 port_type = USB_BC_TYPE_DCP;
128 port_type = USB_BC_TYPE_SDP;
129 /* printk("%s linestate = %d bad status\n",
130 * __func__, BC_GET(RK_BC_LINESTATE)); */
134 BC_SET(RK_BC_SOFTCTRL, 0);
136 /* printk("%s , battery_charger_detect %d\n",
137 * __func__, port_type); */
141 int usb_battery_charger_detect_inno(bool wait)
147 /* When do BC detect PCD pull-up register should be disabled */
148 /* wait wait for dcd timeout 900ms */
149 int usb_battery_charger_detect_synop(bool wait)
151 int port_type = USB_BC_TYPE_DISCNT;
153 int timeout = 0, i = 0;
154 /* VBUS Valid detect */
155 if (BC_GET(SYNOP_BC_BVALID)) {
158 dcd_state = DCD_TIMEOUT;
159 BC_SET(SYNOP_BC_DCDENB, 1);
160 timeout = T_DCD_TIMEOUT;
162 if (!BC_GET(SYNOP_BC_FSVPLUS))
165 /* It is a filter here to assure data
166 * lines contacted for at least 3ms */
167 dcd_state = DCD_POSITIVE;
173 BC_SET(SYNOP_BC_DCDENB, 0);
175 dcd_state = DCD_PASSED;
177 if (dcd_state == DCD_TIMEOUT) {
178 port_type = USB_BC_TYPE_UNKNOW;
183 /* Primary Detection */
184 BC_SET(SYNOP_BC_VDATSRCENB, 1);
185 BC_SET(SYNOP_BC_VDATDETENB, 1);
186 BC_SET(SYNOP_BC_CHRGSEL, 0);
188 udelay(T_BC_CHGDET_VALID);
190 /* SDP and CDP/DCP distinguish */
191 if (BC_GET(SYNOP_BC_CHGDET)) {
192 /* Turn off VDPSRC */
193 BC_SET(SYNOP_BC_VDATSRCENB, 0);
194 BC_SET(SYNOP_BC_VDATDETENB, 0);
196 udelay(T_BC_CHGDET_VALID);
199 BC_SET(SYNOP_BC_VDATSRCENB, 1);
200 BC_SET(SYNOP_BC_VDATDETENB, 1);
201 BC_SET(SYNOP_BC_CHRGSEL, 1);
202 udelay(T_BC_CHGDET_VALID);
203 if (BC_GET(SYNOP_BC_CHGDET))
204 port_type = USB_BC_TYPE_DCP;
206 port_type = USB_BC_TYPE_CDP;
208 port_type = USB_BC_TYPE_SDP;
210 BC_SET(SYNOP_BC_VDATSRCENB, 0);
211 BC_SET(SYNOP_BC_VDATDETENB, 0);
212 BC_SET(SYNOP_BC_CHRGSEL, 0);
216 printk("%s , battery_charger_detect %d, %s DCD, dcd_state = %d\n",
217 __func__, port_type, wait ? "wait" : "pass", dcd_state);
221 int usb_battery_charger_detect(bool wait)
223 static struct device_node *np;
225 np = of_find_node_by_name(NULL, "usb_bc");
229 pGRF_BASE = get_grf_base(np);
231 if (of_device_is_compatible(np, "rockchip,ctrl")) {
234 return usb_battery_charger_detect_rk(wait);
237 else if (of_device_is_compatible(np, "synopsys,phy")) {
240 return usb_battery_charger_detect_synop(wait);
243 else if (of_device_is_compatible(np, "inno,phy")) {
246 return usb_battery_charger_detect_inno(wait);
252 EXPORT_SYMBOL(usb_battery_charger_detect);
254 int dwc_otg_check_dpdm(bool wait)
256 static struct device_node *np;
258 np = of_find_node_by_name(NULL, "usb_bc");
262 pGRF_BASE = get_grf_base(np);
264 if (of_device_is_compatible(np, "rockchip,ctrl")) {
267 if (!BC_GET(RK_BC_BVALID))
268 rk_usb_charger_status = USB_BC_TYPE_DISCNT;
270 } else if (of_device_is_compatible(np, "synopsys,phy")) {
273 if (!BC_GET(SYNOP_BC_BVALID))
274 rk_usb_charger_status = USB_BC_TYPE_DISCNT;
276 } else if (of_device_is_compatible(np, "inno,phy")) {
281 return rk_usb_charger_status;
283 EXPORT_SYMBOL(dwc_otg_check_dpdm);
285 /* CALL BACK FUNCTION for USB CHARGER TYPE CHANGED */
287 void usb20otg_battery_charger_detect_cb(int charger_type_new)
289 static int charger_type = USB_BC_TYPE_DISCNT;
290 if (charger_type != charger_type_new) {
291 switch (charger_type_new) {
292 case USB_BC_TYPE_DISCNT:
295 case USB_BC_TYPE_SDP:
298 case USB_BC_TYPE_DCP:
301 case USB_BC_TYPE_CDP:
304 case USB_BC_TYPE_UNKNOW:
311 /* printk("%s , battery_charger_detect %d\n",
312 * __func__, charger_type_new);*/
314 charger_type = charger_type_new;