dctl.d32);
dwc_otg_disable_global_interrupts(core_if);
core_if->otg_dev->pcd->vbus_status = USB_BC_TYPE_DISCNT;
- DWC_PRINTF
- ("********session end ,soft disconnect************************\n");
+
+ DWC_PRINTF("********session end ,soft disconnect***********\n");
gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
} else if (pldata->get_status(USB_STATUS_BVABLID)) {
/* if usb not connect before ,then start connect */
if (_pcd->vbus_status == USB_BC_TYPE_DISCNT) {
- printk("*****************vbus detect*******************\n");
- /* if( pldata->bc_detect_cb != NULL ) */
- /* pldata->bc_detect_cb(_pcd->vbus_status */
- /* = usb_battery_charger_detect(1)); */
- /* else */
- _pcd->vbus_status = USB_BC_TYPE_SDP;
+ printk("***************vbus detect*****************\n");
+ if( pldata->bc_detect_cb != NULL )
+ pldata->bc_detect_cb(_pcd->vbus_status =
+ usb_battery_charger_detect(1));
+ else
+ _pcd->vbus_status = USB_BC_TYPE_SDP;
if (_pcd->conn_en) {
goto connect;
} else if (pldata->phy_status == USB_PHY_ENABLED) {
}
} else if ((_pcd->conn_en) && (_pcd->conn_status >= 0)
&& (_pcd->conn_status < 2)) {
- printk("****************soft reconnect******************\n");
+ printk("**************soft reconnect**************\n");
goto connect;
} else if (_pcd->conn_status == 2) {
/* release pcd->wake_lock if fail to connect,
dwc_otg_msc_unlock(_pcd);
_pcd->conn_status++;
if (pldata->bc_detect_cb != NULL) {
- rk_usb_charger_status = USB_BC_TYPE_DCP;
pldata->bc_detect_cb(_pcd->vbus_status =
USB_BC_TYPE_DCP);
} else {
_pcd->vbus_status = USB_BC_TYPE_DCP;
- rk_usb_charger_status = USB_BC_TYPE_DCP;
}
/* fail to connect, suspend usb phy and disable clk */
if (pldata->phy_status == USB_PHY_ENABLED) {
} else {
if (pldata->bc_detect_cb != NULL)
pldata->bc_detect_cb(_pcd->vbus_status =
- USB_BC_TYPE_DISCNT);
+ usb_battery_charger_detect(0));
else
_pcd->vbus_status = USB_BC_TYPE_DISCNT;
/* usb phy bypass to uart mode */
pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
}
- schedule_delayed_work(&pcd->check_vbus_work, (HZ << 4));
+ schedule_delayed_work(&pcd->check_vbus_work, (HZ << 3));
}
else if (pldata->dwc_otg_uart_mode != NULL)
/* host mode,enter usb phy mode */
uoc_field_t *pBC_UOC_FIELDS;
static void *pGRF_BASE;
-int rk_usb_charger_status = USB_BC_TYPE_DISCNT;
+static struct mutex bc_mutex;
+
+static enum bc_port_type usb_charger_status = USB_BC_TYPE_DISCNT;
/****** GET REGISTER FIELD INFO FROM Device Tree ******/
}
/****** BATTERY CHARGER DETECT FUNCTIONS ******/
+bool is_connected(void)
+{
+ if (!pGRF_BASE)
+ return false;
+ if (BC_GET(BC_BVALID) && BC_GET(BC_IDDIG))
+ return true;
+ return false;
+}
-int usb_battery_charger_detect_rk(bool wait)
+enum bc_port_type usb_battery_charger_detect_rk(bool wait)
{
enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
return port_type;
}
-int usb_battery_charger_detect_inno(bool wait)
+enum bc_port_type usb_battery_charger_detect_inno(bool wait)
{
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 (BC_GET(INNO_BC_BVALID) &&
+ BC_GET(INNO_BC_IDDIG)) {
if (wait) {
/* Do DCD */
dcd_state = DCD_TIMEOUT;
/* 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)
+enum bc_port_type usb_battery_charger_detect_synop(bool wait)
{
enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
int dcd_state = DCD_POSITIVE;
}
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;
}
-int usb_battery_charger_detect(bool wait)
+enum bc_port_type usb_battery_charger_detect(bool wait)
{
static struct device_node *np;
+ enum bc_port_type ret = USB_BC_TYPE_DISCNT;
+
+ might_sleep();
+
if (!np)
np = of_find_node_by_name(NULL, "usb_bc");
if (!np)
- goto fail;
- if (!pGRF_BASE)
+ return -1;
+ if (!pGRF_BASE) {
pGRF_BASE = get_grf_base(np);
+ mutex_init(&bc_mutex);
+ }
+ mutex_lock(&bc_mutex);
if (of_device_is_compatible(np, "rockchip,ctrl")) {
if (!pBC_UOC_FIELDS)
uoc_init_rk(np);
- return usb_battery_charger_detect_rk(wait);
+ ret = usb_battery_charger_detect_rk(wait);
}
else if (of_device_is_compatible(np, "synopsys,phy")) {
if (!pBC_UOC_FIELDS)
uoc_init_synop(np);
- return usb_battery_charger_detect_synop(wait);
+ ret = usb_battery_charger_detect_synop(wait);
}
else if (of_device_is_compatible(np, "inno,phy")) {
if (!pBC_UOC_FIELDS)
uoc_init_inno(np);
- return usb_battery_charger_detect_inno(wait);
+ ret = usb_battery_charger_detect_inno(wait);
}
-fail:
- return -1;
+ if (ret == USB_BC_TYPE_UNKNOW)
+ ret = USB_BC_TYPE_DCP;
+ mutex_unlock(&bc_mutex);
+ rk_battery_charger_detect_cb(ret);
+ return ret;
}
-EXPORT_SYMBOL(usb_battery_charger_detect);
-
int dwc_otg_check_dpdm(bool wait)
{
- static struct device_node *np;
- if (!np)
- np = of_find_node_by_name(NULL, "usb_bc");
- if (!np)
- return -1;
- if (!pGRF_BASE)
- pGRF_BASE = get_grf_base(np);
-
- if (of_device_is_compatible(np, "rockchip,ctrl")) {
- if (!pBC_UOC_FIELDS)
- uoc_init_rk(np);
- if (!BC_GET(RK_BC_BVALID) ||
- !BC_GET(RK_BC_IDDIG))
- rk_usb_charger_status = USB_BC_TYPE_DISCNT;
-
- } else if (of_device_is_compatible(np, "synopsys,phy")) {
- if (!pBC_UOC_FIELDS)
- uoc_init_synop(np);
- if (!BC_GET(SYNOP_BC_BVALID) ||
- !BC_GET(SYNOP_BC_IDDIG))
- rk_usb_charger_status = USB_BC_TYPE_DISCNT;
-
- } else if (of_device_is_compatible(np, "inno,phy")) {
- if (!pBC_UOC_FIELDS)
- uoc_init_inno(np);
- }
-
- return rk_usb_charger_status;
+ return (is_connected() ? usb_charger_status : USB_BC_TYPE_DISCNT);
}
EXPORT_SYMBOL(dwc_otg_check_dpdm);
-/* CALL BACK FUNCTION for USB CHARGER TYPE CHANGED */
+/* Call back function for USB charger type changed */
+static ATOMIC_NOTIFIER_HEAD(rk_bc_notifier);
-void usb20otg_battery_charger_detect_cb(int charger_type_new)
+int rk_bc_detect_notifier_register(struct notifier_block *nb,
+ int *type)
{
- static int charger_type = USB_BC_TYPE_DISCNT;
- if (charger_type != charger_type_new) {
- switch (charger_type_new) {
- case USB_BC_TYPE_DISCNT:
- break;
-
- case USB_BC_TYPE_SDP:
- break;
-
- case USB_BC_TYPE_DCP:
- break;
+ *type = (int)usb_battery_charger_detect(0);
+ return atomic_notifier_chain_register(&rk_bc_notifier, nb);
+}
+EXPORT_SYMBOL(rk_bc_detect_notifier_register);
- case USB_BC_TYPE_CDP:
- break;
+int rk_bc_detect_notifier_unregister(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&rk_bc_notifier, nb);
+}
+EXPORT_SYMBOL(rk_bc_detect_notifier_unregister);
- case USB_BC_TYPE_UNKNOW:
- break;
+void rk_bc_detect_notifier_callback(int bc_mode)
+{
+ atomic_notifier_call_chain(&rk_bc_notifier,bc_mode, NULL);
+}
- default:
- break;
- }
+void rk_battery_charger_detect_cb(int new_type)
+{
+ might_sleep();
- /* printk("%s , battery_charger_detect %d\n",
- * __func__, charger_type_new);*/
+ if (usb_charger_status != new_type) {
+ printk("%s , battery_charger_detect %d\n", __func__, new_type);
+ atomic_notifier_call_chain(&rk_bc_notifier, new_type, NULL);
}
- charger_type = charger_type_new;
+ mutex_lock(&bc_mutex);
+ usb_charger_status = new_type;
+ mutex_unlock(&bc_mutex);
}
USB_BC_TYPE_UNKNOW,
USB_BC_TYPE_MAX,
};
+enum {
+ BC_BVALID = 0,
+ BC_IDDIG,
+};
enum {
SYNOP_BC_BVALID = 0,
2 : DCP - charger
3 : CDP - pc with big currect charge
***********************************/
-
extern int dwc_otg_check_dpdm(bool wait);
-extern int usb_battery_charger_detect(bool wait);
-extern void usb20otg_battery_charger_detect_cb(int charger_type_new);
+extern enum bc_port_type usb_battery_charger_detect(bool wait);
+extern void rk_battery_charger_detect_cb(int charger_type_new);
+extern int rk_bc_detect_register_notifier(struct notifier_block *nb,
+ enum bc_port_type *type);
+extern int rk_bc_detect_unregister_notifier(struct notifier_block *nb);
#endif
RST_OTHER,
};
-extern int rk_usb_charger_status;
extern void rk_send_wakeup_key(void);
/* rk3188 platform data */
extern struct dwc_otg_platform_data usb20otg_pdata_rk3188;
#ifdef CONFIG_RK_USB_UART
.dwc_otg_uart_mode = dwc_otg_uart_mode,
#endif
- .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+ .bc_detect_cb = rk_battery_charger_detect_cb,
};
#endif
.get_status = usb20otg_get_status,
.power_enable = usb20otg_power_enable,
.dwc_otg_uart_mode = dwc_otg_uart_mode,
- .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+ .bc_detect_cb = rk_battery_charger_detect_cb,
};
#endif
static void usb_battery_charger_detect_work(struct work_struct *work)
{
- rk_usb_charger_status = usb_battery_charger_detect(0);
+ rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
}
/********** handler for bvalid irq **********/
HZ / 10);
}
- rk_usb_charger_status = USB_BC_TYPE_SDP;
schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
return IRQ_HANDLED;
clk_prepare_enable(hclk_usb_peri);
#ifdef CONFIG_USB20_OTG
- if (usb20otg_get_status(USB_STATUS_BVABLID)) {
- rk_usb_charger_status = USB_BC_TYPE_SDP;
+ if (usb20otg_get_status(USB_STATUS_BVABLID))
schedule_delayed_work(&control_usb->usb_charger_det_work,
HZ / 10);
- }
#endif
ret = otg_irq_detect_init(pdev);
.get_status = usb20otg_get_status,
.power_enable = usb20otg_power_enable,
.dwc_otg_uart_mode = dwc_otg_uart_mode,
- .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+ .bc_detect_cb = rk_battery_charger_detect_cb,
};
#endif
static void usb_battery_charger_detect_work(struct work_struct *work)
{
- rk_usb_charger_status = usb_battery_charger_detect(0);
+ rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
}
/********** handler for bvalid irq **********/
HZ / 10);
}
- rk_usb_charger_status = USB_BC_TYPE_SDP;
schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
return IRQ_HANDLED;
clk_prepare_enable(hclk_usb_peri);
#ifdef CONFIG_USB20_OTG
- if (usb20otg_get_status(USB_STATUS_BVABLID)) {
- rk_usb_charger_status = USB_BC_TYPE_SDP;
+ if (usb20otg_get_status(USB_STATUS_BVABLID))
schedule_delayed_work(&control_usb->usb_charger_det_work,
HZ / 10);
- }
#endif
ret = otg_irq_detect_init(pdev);
.get_status = usb20otg_get_status,
.power_enable = usb20otg_power_enable,
.dwc_otg_uart_mode = dwc_otg_uart_mode,
- .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+ .bc_detect_cb = rk_battery_charger_detect_cb,
};
#endif
static void usb_battery_charger_detect_work(struct work_struct *work)
{
- rk_usb_charger_status = usb_battery_charger_detect(0);
+ rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
}
/********** handler for bvalid irq **********/
schedule_delayed_work(&control_usb->usb_det_wakeup_work,
HZ / 10);
}
-
- rk_usb_charger_status = USB_BC_TYPE_SDP;
schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
return IRQ_HANDLED;
{
int ret = 0;
int irq = 0;
-
if (control_usb->usb_irq_wakeup) {
wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND,
"usb_detect");
goto err2;
}
#ifdef CONFIG_USB20_OTG
- if (usb20otg_get_status(USB_STATUS_BVABLID)) {
- rk_usb_charger_status = USB_BC_TYPE_SDP;
+ if (usb20otg_get_status(USB_STATUS_BVABLID))
schedule_delayed_work(&control_usb->usb_charger_det_work,
HZ / 10);
- }
#endif
ret = otg_irq_detect_init(pdev);