diff options
author | Hakan Berg <hakan.berg@stericsson.com> | 2013-01-11 08:12:58 -0500 |
---|---|---|
committer | Anton Vorontsov <anton@enomsg.org> | 2013-01-15 20:44:32 -0500 |
commit | 74a8e349b1c882e34419877207ae850ed87dddf7 (patch) | |
tree | 4881d961c29f9d644a3d27d9dccc2887615d15f6 /drivers/power/ab8500_charger.c | |
parent | d36e3e6d50ccdb5cdef6da0a01dedddd317f23fc (diff) |
ab8500_bm: Adds support for Car/Travel Adapters
The Travel and Carkit adapter should be handled directly by
the charger driver.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Marcus Cooper <marcus.xm.cooper@stericsson.com>
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Signed-off-by: Anton Vorontsov <anton@enomsg.org>
Diffstat (limited to 'drivers/power/ab8500_charger.c')
-rw-r--r-- | drivers/power/ab8500_charger.c | 92 |
1 files changed, 68 insertions, 24 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 126b325cddc9..a0aeef2d2e05 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c | |||
@@ -108,6 +108,18 @@ enum ab8500_charger_link_status { | |||
108 | USB_STAT_HM_IDGND, | 108 | USB_STAT_HM_IDGND, |
109 | USB_STAT_RESERVED, | 109 | USB_STAT_RESERVED, |
110 | USB_STAT_NOT_VALID_LINK, | 110 | USB_STAT_NOT_VALID_LINK, |
111 | USB_STAT_PHY_EN, | ||
112 | USB_STAT_SUP_NO_IDGND_VBUS, | ||
113 | USB_STAT_SUP_IDGND_VBUS, | ||
114 | USB_STAT_CHARGER_LINE_1, | ||
115 | USB_STAT_CARKIT_1, | ||
116 | USB_STAT_CARKIT_2, | ||
117 | USB_STAT_ACA_DOCK_CHARGER, | ||
118 | USB_STAT_SAMSUNG_USB_PHY_DIS, | ||
119 | USB_STAT_SAMSUNG_USB_PHY_ENA, | ||
120 | USB_STAT_SAMSUNG_UART_PHY_DIS, | ||
121 | USB_STAT_SAMSUNG_UART_PHY_ENA, | ||
122 | USB_STAT_MOTOROLA_USB_PHY_ENA, | ||
111 | }; | 123 | }; |
112 | 124 | ||
113 | enum ab8500_usb_state { | 125 | enum ab8500_usb_state { |
@@ -586,7 +598,7 @@ static int ab8500_charger_detect_chargers(struct ab8500_charger *di) | |||
586 | * Returns error code in case of failure else 0 on success | 598 | * Returns error code in case of failure else 0 on success |
587 | */ | 599 | */ |
588 | static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | 600 | static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, |
589 | enum ab8500_charger_link_status link_status) | 601 | enum ab8500_charger_link_status link_status) |
590 | { | 602 | { |
591 | int ret = 0; | 603 | int ret = 0; |
592 | 604 | ||
@@ -595,15 +607,19 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
595 | case USB_STAT_STD_HOST_C_NS: | 607 | case USB_STAT_STD_HOST_C_NS: |
596 | case USB_STAT_STD_HOST_C_S: | 608 | case USB_STAT_STD_HOST_C_S: |
597 | dev_dbg(di->dev, "USB Type - Standard host is " | 609 | dev_dbg(di->dev, "USB Type - Standard host is " |
598 | "detected through USB driver\n"); | 610 | "detected through USB driver\n"); |
599 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; | 611 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; |
600 | break; | 612 | break; |
601 | case USB_STAT_HOST_CHG_HS_CHIRP: | 613 | case USB_STAT_HOST_CHG_HS_CHIRP: |
602 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 614 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; |
615 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
616 | di->max_usb_in_curr); | ||
603 | break; | 617 | break; |
604 | case USB_STAT_HOST_CHG_HS: | 618 | case USB_STAT_HOST_CHG_HS: |
605 | case USB_STAT_ACA_RID_C_HS: | 619 | case USB_STAT_ACA_RID_C_HS: |
606 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; | 620 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; |
621 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
622 | di->max_usb_in_curr); | ||
607 | break; | 623 | break; |
608 | case USB_STAT_ACA_RID_A: | 624 | case USB_STAT_ACA_RID_A: |
609 | /* | 625 | /* |
@@ -611,6 +627,8 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
611 | * can consume (300mA). Closest level is 1100mA | 627 | * can consume (300mA). Closest level is 1100mA |
612 | */ | 628 | */ |
613 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1; | 629 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1; |
630 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
631 | di->max_usb_in_curr); | ||
614 | break; | 632 | break; |
615 | case USB_STAT_ACA_RID_B: | 633 | case USB_STAT_ACA_RID_B: |
616 | /* | 634 | /* |
@@ -618,34 +636,50 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
618 | * 100mA for potential accessory). Closest level is 1300mA | 636 | * 100mA for potential accessory). Closest level is 1300mA |
619 | */ | 637 | */ |
620 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; | 638 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; |
639 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
640 | di->max_usb_in_curr); | ||
621 | break; | 641 | break; |
622 | case USB_STAT_DEDICATED_CHG: | ||
623 | case USB_STAT_HOST_CHG_NM: | 642 | case USB_STAT_HOST_CHG_NM: |
624 | case USB_STAT_ACA_RID_C_HS_CHIRP: | 643 | case USB_STAT_DEDICATED_CHG: |
625 | case USB_STAT_ACA_RID_C_NM: | 644 | case USB_STAT_ACA_RID_C_NM: |
645 | case USB_STAT_ACA_RID_C_HS_CHIRP: | ||
626 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | 646 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; |
627 | break; | 647 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, |
628 | case USB_STAT_RESERVED: | 648 | di->max_usb_in_curr); |
629 | /* | ||
630 | * This state is used to indicate that VBUS has dropped below | ||
631 | * the detection level 4 times in a row. This is due to the | ||
632 | * charger output current is set to high making the charger | ||
633 | * voltage collapse. This have to be propagated through to | ||
634 | * chargalg. This is done using the property | ||
635 | * POWER_SUPPLY_PROP_CURRENT_AVG = 1 | ||
636 | */ | ||
637 | di->flags.vbus_collapse = true; | ||
638 | dev_dbg(di->dev, "USB Type - USB_STAT_RESERVED " | ||
639 | "VBUS has collapsed\n"); | ||
640 | ret = -1; | ||
641 | break; | 649 | break; |
642 | case USB_STAT_HM_IDGND: | 650 | case USB_STAT_HM_IDGND: |
643 | case USB_STAT_NOT_CONFIGURED: | ||
644 | case USB_STAT_NOT_VALID_LINK: | 651 | case USB_STAT_NOT_VALID_LINK: |
652 | case USB_STAT_NOT_CONFIGURED: | ||
645 | dev_err(di->dev, "USB Type - Charging not allowed\n"); | 653 | dev_err(di->dev, "USB Type - Charging not allowed\n"); |
646 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 654 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; |
647 | ret = -ENXIO; | 655 | ret = -ENXIO; |
648 | break; | 656 | break; |
657 | case USB_STAT_RESERVED: | ||
658 | if (is_ab8500(di->parent)) { | ||
659 | di->flags.vbus_collapse = true; | ||
660 | dev_err(di->dev, "USB Type - USB_STAT_RESERVED " | ||
661 | "VBUS has collapsed\n"); | ||
662 | ret = -ENXIO; | ||
663 | break; | ||
664 | } | ||
665 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
666 | dev_dbg(di->dev, "USB Type - Charging not allowed\n"); | ||
667 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | ||
668 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", | ||
669 | link_status, di->max_usb_in_curr); | ||
670 | ret = -ENXIO; | ||
671 | break; | ||
672 | } | ||
673 | break; | ||
674 | case USB_STAT_CARKIT_1: | ||
675 | case USB_STAT_CARKIT_2: | ||
676 | case USB_STAT_ACA_DOCK_CHARGER: | ||
677 | case USB_STAT_CHARGER_LINE_1: | ||
678 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
679 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
680 | di->max_usb_in_curr); | ||
681 | break; | ||
682 | |||
649 | default: | 683 | default: |
650 | dev_err(di->dev, "USB Type - Unknown\n"); | 684 | dev_err(di->dev, "USB Type - Unknown\n"); |
651 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 685 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; |
@@ -677,8 +711,14 @@ static int ab8500_charger_read_usb_type(struct ab8500_charger *di) | |||
677 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 711 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
678 | return ret; | 712 | return ret; |
679 | } | 713 | } |
680 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 714 | if (is_ab8500(di->parent)) { |
681 | AB8500_USB_LINE_STAT_REG, &val); | 715 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, |
716 | AB8500_USB_LINE_STAT_REG, &val); | ||
717 | } else { | ||
718 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) | ||
719 | ret = abx500_get_register_interruptible(di->dev, | ||
720 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); | ||
721 | } | ||
682 | if (ret < 0) { | 722 | if (ret < 0) { |
683 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 723 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
684 | return ret; | 724 | return ret; |
@@ -718,8 +758,13 @@ static int ab8500_charger_detect_usb_type(struct ab8500_charger *di) | |||
718 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 758 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
719 | return ret; | 759 | return ret; |
720 | } | 760 | } |
721 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 761 | |
722 | AB8500_USB_LINE_STAT_REG, &val); | 762 | if (is_ab8500(di->parent)) |
763 | ret = abx500_get_register_interruptible(di->dev, | ||
764 | AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); | ||
765 | else | ||
766 | ret = abx500_get_register_interruptible(di->dev, | ||
767 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); | ||
723 | if (ret < 0) { | 768 | if (ret < 0) { |
724 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 769 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
725 | return ret; | 770 | return ret; |
@@ -2944,7 +2989,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2944 | } | 2989 | } |
2945 | 2990 | ||
2946 | if (charger_status & USB_PW_CONN) { | 2991 | if (charger_status & USB_PW_CONN) { |
2947 | dev_dbg(di->dev, "VBUS Detect during startup\n"); | ||
2948 | di->vbus_detected = true; | 2992 | di->vbus_detected = true; |
2949 | di->vbus_detected_start = true; | 2993 | di->vbus_detected_start = true; |
2950 | queue_work(di->charger_wq, | 2994 | queue_work(di->charger_wq, |