diff options
-rw-r--r-- | drivers/usb/gadget/ci13xxx_udc.c | 10 | ||||
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 380 | ||||
-rw-r--r-- | include/linux/usb/msm_hsusb.h | 72 |
3 files changed, 457 insertions, 5 deletions
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 68123ee01392..baaf87ed7685 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c | |||
@@ -2506,6 +2506,15 @@ out: | |||
2506 | return ret; | 2506 | return ret; |
2507 | } | 2507 | } |
2508 | 2508 | ||
2509 | static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) | ||
2510 | { | ||
2511 | struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | ||
2512 | |||
2513 | if (udc->transceiver) | ||
2514 | return otg_set_power(udc->transceiver, mA); | ||
2515 | return -ENOTSUPP; | ||
2516 | } | ||
2517 | |||
2509 | /** | 2518 | /** |
2510 | * Device operations part of the API to the USB controller hardware, | 2519 | * Device operations part of the API to the USB controller hardware, |
2511 | * which don't involve endpoints (or i/o) | 2520 | * which don't involve endpoints (or i/o) |
@@ -2514,6 +2523,7 @@ out: | |||
2514 | static const struct usb_gadget_ops usb_gadget_ops = { | 2523 | static const struct usb_gadget_ops usb_gadget_ops = { |
2515 | .vbus_session = ci13xxx_vbus_session, | 2524 | .vbus_session = ci13xxx_vbus_session, |
2516 | .wakeup = ci13xxx_wakeup, | 2525 | .wakeup = ci13xxx_wakeup, |
2526 | .vbus_draw = ci13xxx_vbus_draw, | ||
2517 | }; | 2527 | }; |
2518 | 2528 | ||
2519 | /** | 2529 | /** |
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 7792fef0be5e..854b7e3413dd 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | 1 | /* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | 3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License version 2 and | 4 | * it under the terms of the GNU General Public License version 2 and |
@@ -409,6 +409,33 @@ skip_phy_resume: | |||
409 | } | 409 | } |
410 | #endif | 410 | #endif |
411 | 411 | ||
412 | static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) | ||
413 | { | ||
414 | if (motg->cur_power == mA) | ||
415 | return; | ||
416 | |||
417 | /* TODO: Notify PMIC about available current */ | ||
418 | dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA); | ||
419 | motg->cur_power = mA; | ||
420 | } | ||
421 | |||
422 | static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA) | ||
423 | { | ||
424 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
425 | |||
426 | /* | ||
427 | * Gadget driver uses set_power method to notify about the | ||
428 | * available current based on suspend/configured states. | ||
429 | * | ||
430 | * IDEV_CHG can be drawn irrespective of suspend/un-configured | ||
431 | * states when CDP/ACA is connected. | ||
432 | */ | ||
433 | if (motg->chg_type == USB_SDP_CHARGER) | ||
434 | msm_otg_notify_charger(motg, mA); | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
412 | static void msm_otg_start_host(struct otg_transceiver *otg, int on) | 439 | static void msm_otg_start_host(struct otg_transceiver *otg, int on) |
413 | { | 440 | { |
414 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | 441 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); |
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg, | |||
563 | return 0; | 590 | return 0; |
564 | } | 591 | } |
565 | 592 | ||
593 | static bool msm_chg_check_secondary_det(struct msm_otg *motg) | ||
594 | { | ||
595 | struct otg_transceiver *otg = &motg->otg; | ||
596 | u32 chg_det; | ||
597 | bool ret = false; | ||
598 | |||
599 | switch (motg->pdata->phy_type) { | ||
600 | case CI_45NM_INTEGRATED_PHY: | ||
601 | chg_det = ulpi_read(otg, 0x34); | ||
602 | ret = chg_det & (1 << 4); | ||
603 | break; | ||
604 | case SNPS_28NM_INTEGRATED_PHY: | ||
605 | chg_det = ulpi_read(otg, 0x87); | ||
606 | ret = chg_det & 1; | ||
607 | break; | ||
608 | default: | ||
609 | break; | ||
610 | } | ||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | static void msm_chg_enable_secondary_det(struct msm_otg *motg) | ||
615 | { | ||
616 | struct otg_transceiver *otg = &motg->otg; | ||
617 | u32 chg_det; | ||
618 | |||
619 | switch (motg->pdata->phy_type) { | ||
620 | case CI_45NM_INTEGRATED_PHY: | ||
621 | chg_det = ulpi_read(otg, 0x34); | ||
622 | /* Turn off charger block */ | ||
623 | chg_det |= ~(1 << 1); | ||
624 | ulpi_write(otg, chg_det, 0x34); | ||
625 | udelay(20); | ||
626 | /* control chg block via ULPI */ | ||
627 | chg_det &= ~(1 << 3); | ||
628 | ulpi_write(otg, chg_det, 0x34); | ||
629 | /* put it in host mode for enabling D- source */ | ||
630 | chg_det &= ~(1 << 2); | ||
631 | ulpi_write(otg, chg_det, 0x34); | ||
632 | /* Turn on chg detect block */ | ||
633 | chg_det &= ~(1 << 1); | ||
634 | ulpi_write(otg, chg_det, 0x34); | ||
635 | udelay(20); | ||
636 | /* enable chg detection */ | ||
637 | chg_det &= ~(1 << 0); | ||
638 | ulpi_write(otg, chg_det, 0x34); | ||
639 | break; | ||
640 | case SNPS_28NM_INTEGRATED_PHY: | ||
641 | /* | ||
642 | * Configure DM as current source, DP as current sink | ||
643 | * and enable battery charging comparators. | ||
644 | */ | ||
645 | ulpi_write(otg, 0x8, 0x85); | ||
646 | ulpi_write(otg, 0x2, 0x85); | ||
647 | ulpi_write(otg, 0x1, 0x85); | ||
648 | break; | ||
649 | default: | ||
650 | break; | ||
651 | } | ||
652 | } | ||
653 | |||
654 | static bool msm_chg_check_primary_det(struct msm_otg *motg) | ||
655 | { | ||
656 | struct otg_transceiver *otg = &motg->otg; | ||
657 | u32 chg_det; | ||
658 | bool ret = false; | ||
659 | |||
660 | switch (motg->pdata->phy_type) { | ||
661 | case CI_45NM_INTEGRATED_PHY: | ||
662 | chg_det = ulpi_read(otg, 0x34); | ||
663 | ret = chg_det & (1 << 4); | ||
664 | break; | ||
665 | case SNPS_28NM_INTEGRATED_PHY: | ||
666 | chg_det = ulpi_read(otg, 0x87); | ||
667 | ret = chg_det & 1; | ||
668 | break; | ||
669 | default: | ||
670 | break; | ||
671 | } | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static void msm_chg_enable_primary_det(struct msm_otg *motg) | ||
676 | { | ||
677 | struct otg_transceiver *otg = &motg->otg; | ||
678 | u32 chg_det; | ||
679 | |||
680 | switch (motg->pdata->phy_type) { | ||
681 | case CI_45NM_INTEGRATED_PHY: | ||
682 | chg_det = ulpi_read(otg, 0x34); | ||
683 | /* enable chg detection */ | ||
684 | chg_det &= ~(1 << 0); | ||
685 | ulpi_write(otg, chg_det, 0x34); | ||
686 | break; | ||
687 | case SNPS_28NM_INTEGRATED_PHY: | ||
688 | /* | ||
689 | * Configure DP as current source, DM as current sink | ||
690 | * and enable battery charging comparators. | ||
691 | */ | ||
692 | ulpi_write(otg, 0x2, 0x85); | ||
693 | ulpi_write(otg, 0x1, 0x85); | ||
694 | break; | ||
695 | default: | ||
696 | break; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | static bool msm_chg_check_dcd(struct msm_otg *motg) | ||
701 | { | ||
702 | struct otg_transceiver *otg = &motg->otg; | ||
703 | u32 line_state; | ||
704 | bool ret = false; | ||
705 | |||
706 | switch (motg->pdata->phy_type) { | ||
707 | case CI_45NM_INTEGRATED_PHY: | ||
708 | line_state = ulpi_read(otg, 0x15); | ||
709 | ret = !(line_state & 1); | ||
710 | break; | ||
711 | case SNPS_28NM_INTEGRATED_PHY: | ||
712 | line_state = ulpi_read(otg, 0x87); | ||
713 | ret = line_state & 2; | ||
714 | break; | ||
715 | default: | ||
716 | break; | ||
717 | } | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | static void msm_chg_disable_dcd(struct msm_otg *motg) | ||
722 | { | ||
723 | struct otg_transceiver *otg = &motg->otg; | ||
724 | u32 chg_det; | ||
725 | |||
726 | switch (motg->pdata->phy_type) { | ||
727 | case CI_45NM_INTEGRATED_PHY: | ||
728 | chg_det = ulpi_read(otg, 0x34); | ||
729 | chg_det &= ~(1 << 5); | ||
730 | ulpi_write(otg, chg_det, 0x34); | ||
731 | break; | ||
732 | case SNPS_28NM_INTEGRATED_PHY: | ||
733 | ulpi_write(otg, 0x10, 0x86); | ||
734 | break; | ||
735 | default: | ||
736 | break; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | static void msm_chg_enable_dcd(struct msm_otg *motg) | ||
741 | { | ||
742 | struct otg_transceiver *otg = &motg->otg; | ||
743 | u32 chg_det; | ||
744 | |||
745 | switch (motg->pdata->phy_type) { | ||
746 | case CI_45NM_INTEGRATED_PHY: | ||
747 | chg_det = ulpi_read(otg, 0x34); | ||
748 | /* Turn on D+ current source */ | ||
749 | chg_det |= (1 << 5); | ||
750 | ulpi_write(otg, chg_det, 0x34); | ||
751 | break; | ||
752 | case SNPS_28NM_INTEGRATED_PHY: | ||
753 | /* Data contact detection enable */ | ||
754 | ulpi_write(otg, 0x10, 0x85); | ||
755 | break; | ||
756 | default: | ||
757 | break; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | static void msm_chg_block_on(struct msm_otg *motg) | ||
762 | { | ||
763 | struct otg_transceiver *otg = &motg->otg; | ||
764 | u32 func_ctrl, chg_det; | ||
765 | |||
766 | /* put the controller in non-driving mode */ | ||
767 | func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); | ||
768 | func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
769 | func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
770 | ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); | ||
771 | |||
772 | switch (motg->pdata->phy_type) { | ||
773 | case CI_45NM_INTEGRATED_PHY: | ||
774 | chg_det = ulpi_read(otg, 0x34); | ||
775 | /* control chg block via ULPI */ | ||
776 | chg_det &= ~(1 << 3); | ||
777 | ulpi_write(otg, chg_det, 0x34); | ||
778 | /* Turn on chg detect block */ | ||
779 | chg_det &= ~(1 << 1); | ||
780 | ulpi_write(otg, chg_det, 0x34); | ||
781 | udelay(20); | ||
782 | break; | ||
783 | case SNPS_28NM_INTEGRATED_PHY: | ||
784 | /* Clear charger detecting control bits */ | ||
785 | ulpi_write(otg, 0x3F, 0x86); | ||
786 | /* Clear alt interrupt latch and enable bits */ | ||
787 | ulpi_write(otg, 0x1F, 0x92); | ||
788 | ulpi_write(otg, 0x1F, 0x95); | ||
789 | udelay(100); | ||
790 | break; | ||
791 | default: | ||
792 | break; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | static void msm_chg_block_off(struct msm_otg *motg) | ||
797 | { | ||
798 | struct otg_transceiver *otg = &motg->otg; | ||
799 | u32 func_ctrl, chg_det; | ||
800 | |||
801 | switch (motg->pdata->phy_type) { | ||
802 | case CI_45NM_INTEGRATED_PHY: | ||
803 | chg_det = ulpi_read(otg, 0x34); | ||
804 | /* Turn off charger block */ | ||
805 | chg_det |= ~(1 << 1); | ||
806 | ulpi_write(otg, chg_det, 0x34); | ||
807 | break; | ||
808 | case SNPS_28NM_INTEGRATED_PHY: | ||
809 | /* Clear charger detecting control bits */ | ||
810 | ulpi_write(otg, 0x3F, 0x86); | ||
811 | /* Clear alt interrupt latch and enable bits */ | ||
812 | ulpi_write(otg, 0x1F, 0x92); | ||
813 | ulpi_write(otg, 0x1F, 0x95); | ||
814 | break; | ||
815 | default: | ||
816 | break; | ||
817 | } | ||
818 | |||
819 | /* put the controller in normal mode */ | ||
820 | func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); | ||
821 | func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
822 | func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL; | ||
823 | ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); | ||
824 | } | ||
825 | |||
826 | #define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */ | ||
827 | #define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */ | ||
828 | #define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */ | ||
829 | #define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */ | ||
830 | static void msm_chg_detect_work(struct work_struct *w) | ||
831 | { | ||
832 | struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work); | ||
833 | struct otg_transceiver *otg = &motg->otg; | ||
834 | bool is_dcd, tmout, vout; | ||
835 | unsigned long delay; | ||
836 | |||
837 | dev_dbg(otg->dev, "chg detection work\n"); | ||
838 | switch (motg->chg_state) { | ||
839 | case USB_CHG_STATE_UNDEFINED: | ||
840 | pm_runtime_get_sync(otg->dev); | ||
841 | msm_chg_block_on(motg); | ||
842 | msm_chg_enable_dcd(motg); | ||
843 | motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; | ||
844 | motg->dcd_retries = 0; | ||
845 | delay = MSM_CHG_DCD_POLL_TIME; | ||
846 | break; | ||
847 | case USB_CHG_STATE_WAIT_FOR_DCD: | ||
848 | is_dcd = msm_chg_check_dcd(motg); | ||
849 | tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES; | ||
850 | if (is_dcd || tmout) { | ||
851 | msm_chg_disable_dcd(motg); | ||
852 | msm_chg_enable_primary_det(motg); | ||
853 | delay = MSM_CHG_PRIMARY_DET_TIME; | ||
854 | motg->chg_state = USB_CHG_STATE_DCD_DONE; | ||
855 | } else { | ||
856 | delay = MSM_CHG_DCD_POLL_TIME; | ||
857 | } | ||
858 | break; | ||
859 | case USB_CHG_STATE_DCD_DONE: | ||
860 | vout = msm_chg_check_primary_det(motg); | ||
861 | if (vout) { | ||
862 | msm_chg_enable_secondary_det(motg); | ||
863 | delay = MSM_CHG_SECONDARY_DET_TIME; | ||
864 | motg->chg_state = USB_CHG_STATE_PRIMARY_DONE; | ||
865 | } else { | ||
866 | motg->chg_type = USB_SDP_CHARGER; | ||
867 | motg->chg_state = USB_CHG_STATE_DETECTED; | ||
868 | delay = 0; | ||
869 | } | ||
870 | break; | ||
871 | case USB_CHG_STATE_PRIMARY_DONE: | ||
872 | vout = msm_chg_check_secondary_det(motg); | ||
873 | if (vout) | ||
874 | motg->chg_type = USB_DCP_CHARGER; | ||
875 | else | ||
876 | motg->chg_type = USB_CDP_CHARGER; | ||
877 | motg->chg_state = USB_CHG_STATE_SECONDARY_DONE; | ||
878 | /* fall through */ | ||
879 | case USB_CHG_STATE_SECONDARY_DONE: | ||
880 | motg->chg_state = USB_CHG_STATE_DETECTED; | ||
881 | case USB_CHG_STATE_DETECTED: | ||
882 | msm_chg_block_off(motg); | ||
883 | dev_dbg(otg->dev, "charger = %d\n", motg->chg_type); | ||
884 | schedule_work(&motg->sm_work); | ||
885 | return; | ||
886 | default: | ||
887 | return; | ||
888 | } | ||
889 | |||
890 | schedule_delayed_work(&motg->chg_work, delay); | ||
891 | } | ||
892 | |||
566 | /* | 893 | /* |
567 | * We support OTG, Peripheral only and Host only configurations. In case | 894 | * We support OTG, Peripheral only and Host only configurations. In case |
568 | * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen | 895 | * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen |
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w) | |||
633 | writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); | 960 | writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); |
634 | msm_otg_start_host(otg, 1); | 961 | msm_otg_start_host(otg, 1); |
635 | otg->state = OTG_STATE_A_HOST; | 962 | otg->state = OTG_STATE_A_HOST; |
636 | } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) { | 963 | } else if (test_bit(B_SESS_VLD, &motg->inputs)) { |
637 | msm_otg_start_peripheral(otg, 1); | 964 | switch (motg->chg_state) { |
638 | otg->state = OTG_STATE_B_PERIPHERAL; | 965 | case USB_CHG_STATE_UNDEFINED: |
966 | msm_chg_detect_work(&motg->chg_work.work); | ||
967 | break; | ||
968 | case USB_CHG_STATE_DETECTED: | ||
969 | switch (motg->chg_type) { | ||
970 | case USB_DCP_CHARGER: | ||
971 | msm_otg_notify_charger(motg, | ||
972 | IDEV_CHG_MAX); | ||
973 | break; | ||
974 | case USB_CDP_CHARGER: | ||
975 | msm_otg_notify_charger(motg, | ||
976 | IDEV_CHG_MAX); | ||
977 | msm_otg_start_peripheral(otg, 1); | ||
978 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
979 | break; | ||
980 | case USB_SDP_CHARGER: | ||
981 | msm_otg_notify_charger(motg, IUNIT); | ||
982 | msm_otg_start_peripheral(otg, 1); | ||
983 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
984 | break; | ||
985 | default: | ||
986 | break; | ||
987 | } | ||
988 | break; | ||
989 | default: | ||
990 | break; | ||
991 | } | ||
992 | } else { | ||
993 | /* | ||
994 | * If charger detection work is pending, decrement | ||
995 | * the pm usage counter to balance with the one that | ||
996 | * is incremented in charger detection work. | ||
997 | */ | ||
998 | if (cancel_delayed_work_sync(&motg->chg_work)) { | ||
999 | pm_runtime_put_sync(otg->dev); | ||
1000 | msm_otg_reset(otg); | ||
1001 | } | ||
1002 | msm_otg_notify_charger(motg, 0); | ||
1003 | motg->chg_state = USB_CHG_STATE_UNDEFINED; | ||
1004 | motg->chg_type = USB_INVALID_CHARGER; | ||
639 | } | 1005 | } |
640 | pm_runtime_put_sync(otg->dev); | 1006 | pm_runtime_put_sync(otg->dev); |
641 | break; | 1007 | break; |
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w) | |||
643 | dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); | 1009 | dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); |
644 | if (!test_bit(B_SESS_VLD, &motg->inputs) || | 1010 | if (!test_bit(B_SESS_VLD, &motg->inputs) || |
645 | !test_bit(ID, &motg->inputs)) { | 1011 | !test_bit(ID, &motg->inputs)) { |
1012 | msm_otg_notify_charger(motg, 0); | ||
646 | msm_otg_start_peripheral(otg, 0); | 1013 | msm_otg_start_peripheral(otg, 0); |
1014 | motg->chg_state = USB_CHG_STATE_UNDEFINED; | ||
1015 | motg->chg_type = USB_INVALID_CHARGER; | ||
647 | otg->state = OTG_STATE_B_IDLE; | 1016 | otg->state = OTG_STATE_B_IDLE; |
648 | msm_otg_reset(otg); | 1017 | msm_otg_reset(otg); |
649 | schedule_work(w); | 1018 | schedule_work(w); |
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) | |||
935 | writel(0, USB_OTGSC); | 1304 | writel(0, USB_OTGSC); |
936 | 1305 | ||
937 | INIT_WORK(&motg->sm_work, msm_otg_sm_work); | 1306 | INIT_WORK(&motg->sm_work, msm_otg_sm_work); |
1307 | INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); | ||
938 | ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED, | 1308 | ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED, |
939 | "msm_otg", motg); | 1309 | "msm_otg", motg); |
940 | if (ret) { | 1310 | if (ret) { |
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) | |||
945 | otg->init = msm_otg_reset; | 1315 | otg->init = msm_otg_reset; |
946 | otg->set_host = msm_otg_set_host; | 1316 | otg->set_host = msm_otg_set_host; |
947 | otg->set_peripheral = msm_otg_set_peripheral; | 1317 | otg->set_peripheral = msm_otg_set_peripheral; |
1318 | otg->set_power = msm_otg_set_power; | ||
948 | 1319 | ||
949 | otg->io_ops = &msm_otg_io_ops; | 1320 | otg->io_ops = &msm_otg_io_ops; |
950 | 1321 | ||
@@ -1004,6 +1375,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) | |||
1004 | return -EBUSY; | 1375 | return -EBUSY; |
1005 | 1376 | ||
1006 | msm_otg_debugfs_cleanup(); | 1377 | msm_otg_debugfs_cleanup(); |
1378 | cancel_delayed_work_sync(&motg->chg_work); | ||
1007 | cancel_work_sync(&motg->sm_work); | 1379 | cancel_work_sync(&motg->sm_work); |
1008 | 1380 | ||
1009 | pm_runtime_resume(&pdev->dev); | 1381 | pm_runtime_resume(&pdev->dev); |
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 31ef1853f93c..00311fe9d0df 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 2008 Google, Inc. | 3 | * Copyright (C) 2008 Google, Inc. |
4 | * Author: Brian Swetland <swetland@google.com> | 4 | * Author: Brian Swetland <swetland@google.com> |
5 | * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | 5 | * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. |
6 | * | 6 | * |
7 | * This software is licensed under the terms of the GNU General Public | 7 | * This software is licensed under the terms of the GNU General Public |
8 | * License version 2, as published by the Free Software Foundation, and | 8 | * License version 2, as published by the Free Software Foundation, and |
@@ -54,6 +54,64 @@ enum otg_control_type { | |||
54 | }; | 54 | }; |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * PHY used in | ||
58 | * | ||
59 | * INVALID_PHY Unsupported PHY | ||
60 | * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY | ||
61 | * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY | ||
62 | * | ||
63 | */ | ||
64 | enum msm_usb_phy_type { | ||
65 | INVALID_PHY = 0, | ||
66 | CI_45NM_INTEGRATED_PHY, | ||
67 | SNPS_28NM_INTEGRATED_PHY, | ||
68 | }; | ||
69 | |||
70 | #define IDEV_CHG_MAX 1500 | ||
71 | #define IUNIT 100 | ||
72 | |||
73 | /** | ||
74 | * Different states involved in USB charger detection. | ||
75 | * | ||
76 | * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection | ||
77 | * process is not yet started. | ||
78 | * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact. | ||
79 | * USB_CHG_STATE_DCD_DONE Data pin contact is detected. | ||
80 | * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects | ||
81 | * between SDP and DCP/CDP). | ||
82 | * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects | ||
83 | * between DCP and CDP). | ||
84 | * USB_CHG_STATE_DETECTED USB charger type is determined. | ||
85 | * | ||
86 | */ | ||
87 | enum usb_chg_state { | ||
88 | USB_CHG_STATE_UNDEFINED = 0, | ||
89 | USB_CHG_STATE_WAIT_FOR_DCD, | ||
90 | USB_CHG_STATE_DCD_DONE, | ||
91 | USB_CHG_STATE_PRIMARY_DONE, | ||
92 | USB_CHG_STATE_SECONDARY_DONE, | ||
93 | USB_CHG_STATE_DETECTED, | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * USB charger types | ||
98 | * | ||
99 | * USB_INVALID_CHARGER Invalid USB charger. | ||
100 | * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port | ||
101 | * on USB2.0 compliant host/hub. | ||
102 | * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger). | ||
103 | * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and | ||
104 | * IDEV_CHG_MAX can be drawn irrespective of USB state. | ||
105 | * | ||
106 | */ | ||
107 | enum usb_chg_type { | ||
108 | USB_INVALID_CHARGER = 0, | ||
109 | USB_SDP_CHARGER, | ||
110 | USB_DCP_CHARGER, | ||
111 | USB_CDP_CHARGER, | ||
112 | }; | ||
113 | |||
114 | /** | ||
57 | * struct msm_otg_platform_data - platform device data | 115 | * struct msm_otg_platform_data - platform device data |
58 | * for msm_otg driver. | 116 | * for msm_otg driver. |
59 | * @phy_init_seq: PHY configuration sequence. val, reg pairs | 117 | * @phy_init_seq: PHY configuration sequence. val, reg pairs |
@@ -74,6 +132,7 @@ struct msm_otg_platform_data { | |||
74 | enum usb_mode_type mode; | 132 | enum usb_mode_type mode; |
75 | enum otg_control_type otg_control; | 133 | enum otg_control_type otg_control; |
76 | enum usb_mode_type default_mode; | 134 | enum usb_mode_type default_mode; |
135 | enum msm_usb_phy_type phy_type; | ||
77 | void (*setup_gpio)(enum usb_otg_state state); | 136 | void (*setup_gpio)(enum usb_otg_state state); |
78 | char *pclk_src_name; | 137 | char *pclk_src_name; |
79 | }; | 138 | }; |
@@ -93,6 +152,12 @@ struct msm_otg_platform_data { | |||
93 | * @sm_work: OTG state machine work. | 152 | * @sm_work: OTG state machine work. |
94 | * @in_lpm: indicates low power mode (LPM) state. | 153 | * @in_lpm: indicates low power mode (LPM) state. |
95 | * @async_int: Async interrupt arrived. | 154 | * @async_int: Async interrupt arrived. |
155 | * @cur_power: The amount of mA available from downstream port. | ||
156 | * @chg_work: Charger detection work. | ||
157 | * @chg_state: The state of charger detection process. | ||
158 | * @chg_type: The type of charger attached. | ||
159 | * @dcd_retires: The retry count used to track Data contact | ||
160 | * detection process. | ||
96 | */ | 161 | */ |
97 | struct msm_otg { | 162 | struct msm_otg { |
98 | struct otg_transceiver otg; | 163 | struct otg_transceiver otg; |
@@ -110,6 +175,11 @@ struct msm_otg { | |||
110 | struct work_struct sm_work; | 175 | struct work_struct sm_work; |
111 | atomic_t in_lpm; | 176 | atomic_t in_lpm; |
112 | int async_int; | 177 | int async_int; |
178 | unsigned cur_power; | ||
179 | struct delayed_work chg_work; | ||
180 | enum usb_chg_state chg_state; | ||
181 | enum usb_chg_type chg_type; | ||
182 | u8 dcd_retries; | ||
113 | }; | 183 | }; |
114 | 184 | ||
115 | #endif | 185 | #endif |