usb: rk312x support usb charger detect

This commit is contained in:
lyz
2014-09-19 15:37:09 +08:00
parent 7c8d2e7bae
commit 5c977f1c64
3 changed files with 140 additions and 12 deletions

View File

@@ -678,6 +678,17 @@
usb_bc{
compatible = "inno,phy";
regbase = &dwc_control_usb;
rk_usb,bvalid = <0x14c 5 1>;
rk_usb,iddig = <0x14c 8 1>;
rk_usb,vdmsrcen = <0x184 12 1>;
rk_usb,vdpsrcen = <0x184 11 1>;
rk_usb,rdmpden = <0x184 10 1>;
rk_usb,idpsrcen = <0x184 9 1>;
rk_usb,idmsinken = <0x184 8 1>;
rk_usb,idpsinken = <0x184 7 1>;
rk_usb,dpattach = <0x2c0 7 1>;
rk_usb,cpdet = <0x2c0 6 1>;
rk_usb,dcpattach = <0x2c0 5 1>;
};
};

View File

@@ -16,8 +16,13 @@
#include "usbdev_rk.h"
/****** GET and SET REGISTER FIELDS IN GRF UOC ******/
char *bc_string[USB_BC_TYPE_MAX] = {"DISCONNECT",
"Starder Downstream Port",
"Dedicated Charging Port",
"Charging Downstream Port",
"UNKNOW"};
/****** GET and SET REGISTER FIELDS IN GRF UOC ******/
#define BC_GET(x) grf_uoc_get_field(&pBC_UOC_FIELDS[x])
#define BC_SET(x, v) grf_uoc_set_field(&pBC_UOC_FIELDS[x], v)
@@ -99,7 +104,31 @@ static inline void uoc_init_rk(struct device_node *np)
static inline void uoc_init_inno(struct device_node *np)
{
;
pBC_UOC_FIELDS = (uoc_field_t *)
kzalloc(INNO_BC_MAX * sizeof(uoc_field_t), GFP_ATOMIC);
uoc_init_field(np, "rk_usb,bvalid",
&pBC_UOC_FIELDS[INNO_BC_BVALID]);
uoc_init_field(np, "rk_usb,iddig",
&pBC_UOC_FIELDS[INNO_BC_IDDIG]);
uoc_init_field(np, "rk_usb,vdmsrcen",
&pBC_UOC_FIELDS[INNO_BC_VDMSRCEN]);
uoc_init_field(np, "rk_usb,vdpsrcen",
&pBC_UOC_FIELDS[INNO_BC_VDPSRCEN]);
uoc_init_field(np, "rk_usb,rdmpden",
&pBC_UOC_FIELDS[INNO_BC_RDMPDEN]);
uoc_init_field(np, "rk_usb,idpsrcen",
&pBC_UOC_FIELDS[INNO_BC_IDPSRCEN]);
uoc_init_field(np, "rk_usb,idmsinken",
&pBC_UOC_FIELDS[INNO_BC_IDMSINKEN]);
uoc_init_field(np, "rk_usb,idpsinken",
&pBC_UOC_FIELDS[INNO_BC_IDPSINKEN]);
uoc_init_field(np, "rk_usb,dpattach",
&pBC_UOC_FIELDS[INNO_BC_DPATTACH]);
uoc_init_field(np, "rk_usb,cpdet",
&pBC_UOC_FIELDS[INNO_BC_CPDET]);
uoc_init_field(np, "rk_usb,dcpattach",
&pBC_UOC_FIELDS[INNO_BC_DCPATTACH]);
}
/****** BATTERY CHARGER DETECT FUNCTIONS ******/
@@ -107,7 +136,7 @@ static inline void uoc_init_inno(struct device_node *np)
int usb_battery_charger_detect_rk(bool wait)
{
int port_type = USB_BC_TYPE_DISCNT;
enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
if (BC_GET(RK_BC_BVALID) &&
BC_GET(RK_BC_IDDIG)) {
@@ -143,14 +172,84 @@ int usb_battery_charger_detect_rk(bool wait)
int usb_battery_charger_detect_inno(bool wait)
{
return readl(RK_GRF_VIRT + RK312X_GRF_SOC_STATUS0) & (1 << 8);
enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
int dcd_state = DCD_POSITIVE;
int timeout = 0, i = 0;
/* VBUS Valid detect */
if (BC_GET(SYNOP_BC_BVALID) &&
BC_GET(SYNOP_BC_IDDIG)) {
if (wait) {
/* Do DCD */
dcd_state = DCD_TIMEOUT;
BC_SET(INNO_BC_RDMPDEN, 1);
BC_SET(INNO_BC_IDPSRCEN, 1);
timeout = T_DCD_TIMEOUT;
while (timeout--) {
if (BC_GET(INNO_BC_DPATTACH))
i++;
if (i >= 3) {
/* It is a filter here to assure data
* lines contacted for at least 3ms */
dcd_state = DCD_POSITIVE;
break;
}
mdelay(1);
}
BC_SET(INNO_BC_RDMPDEN, 0);
BC_SET(INNO_BC_IDPSRCEN, 0);
} else {
dcd_state = DCD_PASSED;
}
if (dcd_state == DCD_TIMEOUT) {
port_type = USB_BC_TYPE_UNKNOW;
goto out;
}
/* Turn on VDPSRC */
/* Primary Detection */
BC_SET(INNO_BC_VDPSRCEN, 1);
BC_SET(INNO_BC_IDMSINKEN, 1);
udelay(T_BC_CHGDET_VALID);
/* SDP and CDP/DCP distinguish */
if (BC_GET(INNO_BC_CPDET)) {
/* Turn off VDPSRC */
BC_SET(INNO_BC_VDPSRCEN, 0);
BC_SET(INNO_BC_IDMSINKEN, 0);
udelay(T_BC_CHGDET_VALID);
/* Turn on VDMSRC */
BC_SET(INNO_BC_VDMSRCEN, 1);
BC_SET(INNO_BC_IDPSINKEN, 1);
udelay(T_BC_CHGDET_VALID);
if (BC_GET(INNO_BC_DCPATTACH))
port_type = USB_BC_TYPE_DCP;
else
port_type = USB_BC_TYPE_CDP;
} else {
port_type = USB_BC_TYPE_SDP;
}
BC_SET(INNO_BC_VDPSRCEN, 0);
BC_SET(INNO_BC_IDMSINKEN, 0);
BC_SET(INNO_BC_VDMSRCEN, 0);
BC_SET(INNO_BC_IDPSINKEN, 0);
}
out:
printk("%s, Charger type %s, %s DCD, dcd_state = %d\n", __func__,
bc_string[port_type], wait ? "wait" : "pass", dcd_state);
return port_type;
}
/* When do BC detect PCD pull-up register should be disabled */
/* wait wait for dcd timeout 900ms */
int usb_battery_charger_detect_synop(bool wait)
{
int port_type = USB_BC_TYPE_DISCNT;
enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
int dcd_state = DCD_POSITIVE;
int timeout = 0, i = 0;
@@ -217,8 +316,8 @@ int usb_battery_charger_detect_synop(bool wait)
}
out:
printk("%s , battery_charger_detect %d, %s DCD, dcd_state = %d\n",
__func__, port_type, wait ? "wait" : "pass", dcd_state);
printk("%s, Charger type %s, %s DCD, dcd_state = %d\n", __func__,
bc_string[port_type], wait ? "wait" : "pass", dcd_state);
return port_type;
}

28
drivers/usb/dwc_otg_310/usbdev_bc.h Normal file → Executable file
View File

@@ -2,11 +2,14 @@
#define _USBDEV_BC_H
/* USB Charger Types */
#define USB_BC_TYPE_DISCNT (0)
#define USB_BC_TYPE_SDP (1)
#define USB_BC_TYPE_DCP (2)
#define USB_BC_TYPE_CDP (3)
#define USB_BC_TYPE_UNKNOW (4)
enum bc_port_type{
USB_BC_TYPE_DISCNT = 0,
USB_BC_TYPE_SDP,
USB_BC_TYPE_DCP,
USB_BC_TYPE_CDP,
USB_BC_TYPE_UNKNOW,
USB_BC_TYPE_MAX,
};
enum {
SYNOP_BC_BVALID = 0,
@@ -21,6 +24,21 @@ enum {
SYNOP_BC_MAX,
};
enum {
INNO_BC_BVALID = 0,
INNO_BC_IDDIG,
INNO_BC_VDMSRCEN,
INNO_BC_VDPSRCEN,
INNO_BC_RDMPDEN,
INNO_BC_IDPSRCEN,
INNO_BC_IDMSINKEN,
INNO_BC_IDPSINKEN,
INNO_BC_DPATTACH,
INNO_BC_CPDET,
INNO_BC_DCPATTACH,
INNO_BC_MAX,
};
enum {
RK_BC_BVALID = 0,
RK_BC_IDDIG,