From: lyz Date: Fri, 10 Oct 2014 05:42:32 +0000 (+0800) Subject: usb: support different type of usb charger X-Git-Tag: firefly_0821_release~4593 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=495f30d3377374f0578d4339769a9d88532b2178;p=firefly-linux-kernel-4.4.55.git usb: support different type of usb charger --- diff --git a/drivers/usb/dwc_otg_310/dwc_otg_cil_intr.c b/drivers/usb/dwc_otg_310/dwc_otg_cil_intr.c index a4327dc176f8..199765d6abec 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_cil_intr.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_cil_intr.c @@ -109,8 +109,8 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *core_if) 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); diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c index da339bfba076..d4db1e73930f 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c @@ -1529,12 +1529,12 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) } 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) { @@ -1545,7 +1545,7 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) } } 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, @@ -1554,12 +1554,10 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) 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) { @@ -1571,7 +1569,7 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) } 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; @@ -1666,7 +1664,7 @@ static void dwc_otg_pcd_work_init(dwc_otg_pcd_t *pcd, /* 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 */ diff --git a/drivers/usb/dwc_otg_310/usbdev_bc.c b/drivers/usb/dwc_otg_310/usbdev_bc.c index 96f2234b112b..a62c489d9cad 100755 --- a/drivers/usb/dwc_otg_310/usbdev_bc.c +++ b/drivers/usb/dwc_otg_310/usbdev_bc.c @@ -28,7 +28,9 @@ char *bc_string[USB_BC_TYPE_MAX] = {"DISCONNECT", 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 ******/ @@ -132,8 +134,16 @@ static inline void uoc_init_inno(struct device_node *np) } /****** 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; @@ -170,15 +180,15 @@ int usb_battery_charger_detect_rk(bool wait) 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; @@ -247,7 +257,7 @@ out: /* 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; @@ -316,105 +326,91 @@ int usb_battery_charger_detect_synop(bool wait) } 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); } diff --git a/drivers/usb/dwc_otg_310/usbdev_bc.h b/drivers/usb/dwc_otg_310/usbdev_bc.h index 52898230b510..b4891d72721a 100755 --- a/drivers/usb/dwc_otg_310/usbdev_bc.h +++ b/drivers/usb/dwc_otg_310/usbdev_bc.h @@ -10,6 +10,10 @@ enum bc_port_type{ USB_BC_TYPE_UNKNOW, USB_BC_TYPE_MAX, }; +enum { + BC_BVALID = 0, + BC_IDDIG, +}; enum { SYNOP_BC_BVALID = 0, @@ -67,9 +71,11 @@ USB Port Type 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 diff --git a/drivers/usb/dwc_otg_310/usbdev_rk.h b/drivers/usb/dwc_otg_310/usbdev_rk.h index 06584dd516ca..fba8eea5173c 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk.h +++ b/drivers/usb/dwc_otg_310/usbdev_rk.h @@ -52,7 +52,6 @@ enum rkusb_rst_flag { 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; diff --git a/drivers/usb/dwc_otg_310/usbdev_rk30.c b/drivers/usb/dwc_otg_310/usbdev_rk30.c index dcdfb7d38e24..7e7465fbb464 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk30.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk30.c @@ -158,7 +158,7 @@ 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 diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3036.c b/drivers/usb/dwc_otg_310/usbdev_rk3036.c index 6f2e197cf8a4..2d507af84da1 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk3036.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk3036.c @@ -204,7 +204,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3036 = { .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 @@ -392,7 +392,7 @@ static inline void do_wakeup(struct work_struct *work) 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 **********/ @@ -413,7 +413,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) HZ / 10); } - rk_usb_charger_status = USB_BC_TYPE_SDP; schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10); return IRQ_HANDLED; @@ -571,11 +570,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) 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); diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3126.c b/drivers/usb/dwc_otg_310/usbdev_rk3126.c index 4f7326ff6eb9..ccc817b7d25e 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk3126.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk3126.c @@ -206,7 +206,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3126 = { .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 @@ -400,7 +400,7 @@ static inline void do_wakeup(struct work_struct *work) 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 **********/ @@ -421,7 +421,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) HZ / 10); } - rk_usb_charger_status = USB_BC_TYPE_SDP; schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10); return IRQ_HANDLED; @@ -579,11 +578,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) 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); diff --git a/drivers/usb/dwc_otg_310/usbdev_rk32.c b/drivers/usb/dwc_otg_310/usbdev_rk32.c index 6d28789d758d..e0394614614a 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk32.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk32.c @@ -195,7 +195,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3288 = { .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 @@ -682,7 +682,7 @@ static inline void do_wakeup(struct work_struct *work) 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 **********/ @@ -700,8 +700,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) 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; @@ -771,7 +769,6 @@ static int otg_irq_detect_init(struct platform_device *pdev) { int ret = 0; int irq = 0; - if (control_usb->usb_irq_wakeup) { wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect"); @@ -1112,11 +1109,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) 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);