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,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]);
85 static inline void uoc_init_rk(struct device_node *np)
88 (uoc_field_t *) kzalloc(RK_BC_MAX * sizeof(uoc_field_t),
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]);
100 static inline void uoc_init_inno(struct device_node *np)
105 /****** BATTERY CHARGER DETECT FUNCTIONS ******/
107 int usb_battery_charger_detect_rk(bool wait)
110 int port_type = USB_BC_TYPE_DISCNT;
112 if (BC_GET(RK_BC_BVALID) &&
113 BC_GET(RK_BC_IDDIG)) {
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);
121 switch (BC_GET(RK_BC_LINESTATE)) {
123 port_type = USB_BC_TYPE_SDP;
127 port_type = USB_BC_TYPE_DCP;
131 port_type = USB_BC_TYPE_SDP;
132 /* printk("%s linestate = %d bad status\n",
133 * __func__, BC_GET(RK_BC_LINESTATE)); */
137 BC_SET(RK_BC_SOFTCTRL, 0);
139 /* printk("%s , battery_charger_detect %d\n",
140 * __func__, port_type); */
144 int usb_battery_charger_detect_inno(bool wait)
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)
154 int port_type = USB_BC_TYPE_DISCNT;
155 int dcd_state = DCD_POSITIVE;
156 int timeout = 0, i = 0;
158 /* VBUS Valid detect */
159 if (BC_GET(SYNOP_BC_BVALID) &&
160 BC_GET(SYNOP_BC_IDDIG)) {
163 dcd_state = DCD_TIMEOUT;
164 BC_SET(SYNOP_BC_DCDENB, 1);
165 timeout = T_DCD_TIMEOUT;
167 if (!BC_GET(SYNOP_BC_FSVPLUS))
170 /* It is a filter here to assure data
171 * lines contacted for at least 3ms */
172 dcd_state = DCD_POSITIVE;
178 BC_SET(SYNOP_BC_DCDENB, 0);
180 dcd_state = DCD_PASSED;
182 if (dcd_state == DCD_TIMEOUT) {
183 port_type = USB_BC_TYPE_UNKNOW;
188 /* Primary Detection */
189 BC_SET(SYNOP_BC_VDATSRCENB, 1);
190 BC_SET(SYNOP_BC_VDATDETENB, 1);
191 BC_SET(SYNOP_BC_CHRGSEL, 0);
193 udelay(T_BC_CHGDET_VALID);
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);
201 udelay(T_BC_CHGDET_VALID);
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;
211 port_type = USB_BC_TYPE_CDP;
213 port_type = USB_BC_TYPE_SDP;
215 BC_SET(SYNOP_BC_VDATSRCENB, 0);
216 BC_SET(SYNOP_BC_VDATDETENB, 0);
217 BC_SET(SYNOP_BC_CHRGSEL, 0);
221 printk("%s , battery_charger_detect %d, %s DCD, dcd_state = %d\n",
222 __func__, port_type, wait ? "wait" : "pass", dcd_state);
226 int usb_battery_charger_detect(bool wait)
228 static struct device_node *np;
230 np = of_find_node_by_name(NULL, "usb_bc");
234 pGRF_BASE = get_grf_base(np);
236 if (of_device_is_compatible(np, "rockchip,ctrl")) {
239 return usb_battery_charger_detect_rk(wait);
242 else if (of_device_is_compatible(np, "synopsys,phy")) {
245 return usb_battery_charger_detect_synop(wait);
248 else if (of_device_is_compatible(np, "inno,phy")) {
251 return usb_battery_charger_detect_inno(wait);
257 EXPORT_SYMBOL(usb_battery_charger_detect);
259 int dwc_otg_check_dpdm(bool wait)
261 static struct device_node *np;
263 np = of_find_node_by_name(NULL, "usb_bc");
267 pGRF_BASE = get_grf_base(np);
269 if (of_device_is_compatible(np, "rockchip,ctrl")) {
272 if (!BC_GET(RK_BC_BVALID) ||
273 !BC_GET(RK_BC_IDDIG))
274 rk_usb_charger_status = USB_BC_TYPE_DISCNT;
276 } else if (of_device_is_compatible(np, "synopsys,phy")) {
279 if (!BC_GET(SYNOP_BC_BVALID) ||
280 !BC_GET(SYNOP_BC_IDDIG))
281 rk_usb_charger_status = USB_BC_TYPE_DISCNT;
283 } else if (of_device_is_compatible(np, "inno,phy")) {
288 return rk_usb_charger_status;
290 EXPORT_SYMBOL(dwc_otg_check_dpdm);
292 /* CALL BACK FUNCTION for USB CHARGER TYPE CHANGED */
294 void usb20otg_battery_charger_detect_cb(int charger_type_new)
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:
302 case USB_BC_TYPE_SDP:
305 case USB_BC_TYPE_DCP:
308 case USB_BC_TYPE_CDP:
311 case USB_BC_TYPE_UNKNOW:
318 /* printk("%s , battery_charger_detect %d\n",
319 * __func__, charger_type_new);*/
321 charger_type = charger_type_new;