diff options
author | Rakesh Bodla <rbodla@nvidia.com> | 2011-07-21 10:17:26 +0530 |
---|---|---|
committer | Manish Tuteja <mtuteja@nvidia.com> | 2011-07-25 02:31:40 -0700 |
commit | 06bdd7fc427abd7a6e907af52441dec07f92e2f6 (patch) | |
tree | f785d3ea25632ee58dad2ae34768ab33a5cb7d06 /drivers | |
parent | 69c083d495e1f187654c5a1bcd58569e54bf985b (diff) |
usb: gadget: udc: USB charger detection support
Adding the USB charger detection support for
device controller.
Bug 819334
Change-Id: I9350c6abaa2be38ecb40db6bc9bc5e84c5303998
Reviewed-on: http://git-master/r/42299
Reviewed-by: Rakesh Bodla <rbodla@nvidia.com>
Tested-by: Rakesh Bodla <rbodla@nvidia.com>
Reviewed-by: Hanumanth Venkateswa Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/fsl_tegra_udc.c | 5 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_udc_core.c | 28 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_usb2_udc.h | 6 |
3 files changed, 39 insertions, 0 deletions
diff --git a/drivers/usb/gadget/fsl_tegra_udc.c b/drivers/usb/gadget/fsl_tegra_udc.c index 712636d8ee8e..3e44aea98eeb 100644 --- a/drivers/usb/gadget/fsl_tegra_udc.c +++ b/drivers/usb/gadget/fsl_tegra_udc.c @@ -132,3 +132,8 @@ void fsl_udc_clk_resume(bool is_dpd) clk_enable(udc_clk); tegra_usb_phy_power_on(phy, is_dpd); } + +bool fsl_udc_charger_detect(void) +{ + return tegra_usb_phy_charger_detect(phy); +} diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 82118cd1cbf7..1dba4dfcacfd 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -39,6 +39,7 @@ #include <linux/fsl_devices.h> #include <linux/dmapool.h> #include <linux/delay.h> +#include <linux/workqueue.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -71,6 +72,9 @@ static struct usb_dr_device *dr_regs; static struct usb_sys_interface *usb_sys_regs; #endif +/* 1 sec wait time for charger detection after vbus is detected */ +#define USB_CHARGER_DETECTION_WAIT_TIME_MS 1000 + /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; @@ -1207,6 +1211,8 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active) if (udc->transceiver) { if (udc->vbus_active && !is_active) { + /* If cable disconnected, cancel any delayed work */ + cancel_delayed_work(&udc->work); spin_lock_irqsave(&udc->lock, flags); /* reset all internal Queues and inform client driver */ reset_queues(udc); @@ -1230,6 +1236,9 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active) udc->vbus_active = 1; /* start the controller */ dr_controller_run(udc); + /* Schedule work to wait for 1000 msec and check for + * charger if setup packet is not received */ + schedule_delayed_work(&udc->work, USB_CHARGER_DETECTION_WAIT_TIME_MS); } return 0; } @@ -1999,6 +2008,18 @@ static void reset_irq(struct fsl_udc *udc) #endif } +/* + * If VBUS is detected and setup packet is not received in 100ms then + * work thread starts and checks for the USB charger detection. + */ +static void fsl_udc_charger_detect_work(struct work_struct* work) +{ + /* check for the platform charger detection */ + if (fsl_udc_charger_detect()) { + printk(KERN_INFO "USB compliant charger detected\n"); + } +} + #if defined(CONFIG_ARCH_TEGRA) /* * Restart device controller in the OTG mode on VBUS detection @@ -2053,6 +2074,9 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc) VDBG("Packet int"); /* Setup package, we only support ep0 as control ep */ if (fsl_readl(&dr_regs->endptsetupstat) & EP_SETUP_STATUS_EP0) { + /* Setup packet received, we are connected to host and + * not charger. Cancel any delayed work */ + cancel_delayed_work(&udc->work); tripwire_handler(udc, 0, (u8 *) (&udc->local_setup_buff)); setup_received_irq(udc, &udc->local_setup_buff); @@ -2751,6 +2775,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) } create_proc_file(); + /* create a delayed work for detecting the USB charger */ + INIT_DELAYED_WORK(&udc_controller->work, fsl_udc_charger_detect_work); + #ifdef CONFIG_USB_OTG_UTILS udc_controller->transceiver = otg_get_transceiver(); if (udc_controller->transceiver) { @@ -2800,6 +2827,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) return -ENODEV; udc_controller->done = &done; + cancel_delayed_work(&udc_controller->work); if (udc_controller->transceiver) otg_set_peripheral(udc_controller->transceiver, NULL); diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 415b7c088962..599327d16634 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -512,6 +512,7 @@ struct fsl_udc { u32 ep0_dir; /* Endpoint zero direction: can be USB_DIR_IN or USB_DIR_OUT */ u8 device_address; /* Device USB address */ + struct delayed_work work; /* delayed work for charger detection */ }; /*-------------------------------------------------------------------------*/ @@ -593,6 +594,7 @@ void fsl_udc_clk_finalize(struct platform_device *pdev); void fsl_udc_clk_release(void); void fsl_udc_clk_suspend(bool is_dpd); void fsl_udc_clk_resume(bool is_dpd); +bool fsl_udc_charger_detect(void); #else static inline int fsl_udc_clk_init(struct platform_device *pdev) { @@ -610,6 +612,10 @@ static inline void fsl_udc_clk_suspend(bool is_dpd) static inline void fsl_udc_clk_resume(bool is_dpd) { } +static inline bool fsl_udc_charger_detect(void) +{ + return false; +} #endif #endif |