diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl-core.c | 190 |
1 files changed, 153 insertions, 37 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 2bd9e0676bc2..b8f2a4e7f6e7 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -198,6 +198,7 @@ | |||
198 | #define TWL6030_BASEADD_GASGAUGE 0x00C0 | 198 | #define TWL6030_BASEADD_GASGAUGE 0x00C0 |
199 | #define TWL6030_BASEADD_PIH 0x00D0 | 199 | #define TWL6030_BASEADD_PIH 0x00D0 |
200 | #define TWL6030_BASEADD_CHARGER 0x00E0 | 200 | #define TWL6030_BASEADD_CHARGER 0x00E0 |
201 | #define TWL6025_BASEADD_CHARGER 0x00DA | ||
201 | 202 | ||
202 | /* subchip/slave 2 0x4A - DFT */ | 203 | /* subchip/slave 2 0x4A - DFT */ |
203 | #define TWL6030_BASEADD_DIEID 0x00C0 | 204 | #define TWL6030_BASEADD_DIEID 0x00C0 |
@@ -331,6 +332,7 @@ static struct twl_mapping twl6030_map[] = { | |||
331 | 332 | ||
332 | { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, | 333 | { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, |
333 | { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, | 334 | { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, |
335 | { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER }, | ||
334 | }; | 336 | }; |
335 | 337 | ||
336 | /*----------------------------------------------------------------------*/ | 338 | /*----------------------------------------------------------------------*/ |
@@ -604,7 +606,7 @@ static inline struct device *add_child(unsigned chip, const char *name, | |||
604 | static struct device * | 606 | static struct device * |
605 | add_regulator_linked(int num, struct regulator_init_data *pdata, | 607 | add_regulator_linked(int num, struct regulator_init_data *pdata, |
606 | struct regulator_consumer_supply *consumers, | 608 | struct regulator_consumer_supply *consumers, |
607 | unsigned num_consumers) | 609 | unsigned num_consumers, unsigned long features) |
608 | { | 610 | { |
609 | unsigned sub_chip_id; | 611 | unsigned sub_chip_id; |
610 | /* regulator framework demands init_data ... */ | 612 | /* regulator framework demands init_data ... */ |
@@ -616,6 +618,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
616 | pdata->num_consumer_supplies = num_consumers; | 618 | pdata->num_consumer_supplies = num_consumers; |
617 | } | 619 | } |
618 | 620 | ||
621 | pdata->driver_data = (void *)features; | ||
622 | |||
619 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ | 623 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ |
620 | sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; | 624 | sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; |
621 | return add_numbered_child(sub_chip_id, "twl_reg", num, | 625 | return add_numbered_child(sub_chip_id, "twl_reg", num, |
@@ -623,9 +627,10 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
623 | } | 627 | } |
624 | 628 | ||
625 | static struct device * | 629 | static struct device * |
626 | add_regulator(int num, struct regulator_init_data *pdata) | 630 | add_regulator(int num, struct regulator_init_data *pdata, |
631 | unsigned long features) | ||
627 | { | 632 | { |
628 | return add_regulator_linked(num, pdata, NULL, 0); | 633 | return add_regulator_linked(num, pdata, NULL, 0, features); |
629 | } | 634 | } |
630 | 635 | ||
631 | /* | 636 | /* |
@@ -705,17 +710,20 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
705 | }; | 710 | }; |
706 | 711 | ||
707 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, | 712 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, |
708 | &usb_fixed, &usb1v5, 1); | 713 | &usb_fixed, &usb1v5, 1, |
714 | features); | ||
709 | if (IS_ERR(child)) | 715 | if (IS_ERR(child)) |
710 | return PTR_ERR(child); | 716 | return PTR_ERR(child); |
711 | 717 | ||
712 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, | 718 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, |
713 | &usb_fixed, &usb1v8, 1); | 719 | &usb_fixed, &usb1v8, 1, |
720 | features); | ||
714 | if (IS_ERR(child)) | 721 | if (IS_ERR(child)) |
715 | return PTR_ERR(child); | 722 | return PTR_ERR(child); |
716 | 723 | ||
717 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, | 724 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, |
718 | &usb_fixed, &usb3v1, 1); | 725 | &usb_fixed, &usb3v1, 1, |
726 | features); | ||
719 | if (IS_ERR(child)) | 727 | if (IS_ERR(child)) |
720 | return PTR_ERR(child); | 728 | return PTR_ERR(child); |
721 | 729 | ||
@@ -740,9 +748,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
740 | } | 748 | } |
741 | if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { | 749 | if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { |
742 | 750 | ||
743 | static struct regulator_consumer_supply usb3v3 = { | 751 | static struct regulator_consumer_supply usb3v3; |
744 | .supply = "vusb", | 752 | int regulator; |
745 | }; | ||
746 | 753 | ||
747 | if (twl_has_regulator()) { | 754 | if (twl_has_regulator()) { |
748 | /* this is a template that gets copied */ | 755 | /* this is a template that gets copied */ |
@@ -755,12 +762,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
755 | | REGULATOR_CHANGE_STATUS, | 762 | | REGULATOR_CHANGE_STATUS, |
756 | }; | 763 | }; |
757 | 764 | ||
758 | child = add_regulator_linked(TWL6030_REG_VUSB, | 765 | if (features & TWL6025_SUBCLASS) { |
759 | &usb_fixed, &usb3v3, 1); | 766 | usb3v3.supply = "ldousb"; |
767 | regulator = TWL6025_REG_LDOUSB; | ||
768 | } else { | ||
769 | usb3v3.supply = "vusb"; | ||
770 | regulator = TWL6030_REG_VUSB; | ||
771 | } | ||
772 | child = add_regulator_linked(regulator, &usb_fixed, | ||
773 | &usb3v3, 1, | ||
774 | features); | ||
760 | if (IS_ERR(child)) | 775 | if (IS_ERR(child)) |
761 | return PTR_ERR(child); | 776 | return PTR_ERR(child); |
762 | } | 777 | } |
763 | 778 | ||
779 | pdata->usb->features = features; | ||
780 | |||
764 | child = add_child(0, "twl6030_usb", | 781 | child = add_child(0, "twl6030_usb", |
765 | pdata->usb, sizeof(*pdata->usb), | 782 | pdata->usb, sizeof(*pdata->usb), |
766 | true, | 783 | true, |
@@ -773,7 +790,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
773 | /* we need to connect regulators to this transceiver */ | 790 | /* we need to connect regulators to this transceiver */ |
774 | if (twl_has_regulator() && child) | 791 | if (twl_has_regulator() && child) |
775 | usb3v3.dev = child; | 792 | usb3v3.dev = child; |
793 | } else if (twl_has_regulator() && twl_class_is_6030()) { | ||
794 | if (features & TWL6025_SUBCLASS) | ||
795 | child = add_regulator(TWL6025_REG_LDOUSB, | ||
796 | pdata->ldousb, features); | ||
797 | else | ||
798 | child = add_regulator(TWL6030_REG_VUSB, | ||
799 | pdata->vusb, features); | ||
776 | 800 | ||
801 | if (IS_ERR(child)) | ||
802 | return PTR_ERR(child); | ||
777 | } | 803 | } |
778 | 804 | ||
779 | if (twl_has_watchdog() && twl_class_is_4030()) { | 805 | if (twl_has_watchdog() && twl_class_is_4030()) { |
@@ -810,46 +836,55 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
810 | 836 | ||
811 | /* twl4030 regulators */ | 837 | /* twl4030 regulators */ |
812 | if (twl_has_regulator() && twl_class_is_4030()) { | 838 | if (twl_has_regulator() && twl_class_is_4030()) { |
813 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); | 839 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1, |
840 | features); | ||
814 | if (IS_ERR(child)) | 841 | if (IS_ERR(child)) |
815 | return PTR_ERR(child); | 842 | return PTR_ERR(child); |
816 | 843 | ||
817 | child = add_regulator(TWL4030_REG_VIO, pdata->vio); | 844 | child = add_regulator(TWL4030_REG_VIO, pdata->vio, |
845 | features); | ||
818 | if (IS_ERR(child)) | 846 | if (IS_ERR(child)) |
819 | return PTR_ERR(child); | 847 | return PTR_ERR(child); |
820 | 848 | ||
821 | child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1); | 849 | child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1, |
850 | features); | ||
822 | if (IS_ERR(child)) | 851 | if (IS_ERR(child)) |
823 | return PTR_ERR(child); | 852 | return PTR_ERR(child); |
824 | 853 | ||
825 | child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2); | 854 | child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2, |
855 | features); | ||
826 | if (IS_ERR(child)) | 856 | if (IS_ERR(child)) |
827 | return PTR_ERR(child); | 857 | return PTR_ERR(child); |
828 | 858 | ||
829 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); | 859 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1, |
860 | features); | ||
830 | if (IS_ERR(child)) | 861 | if (IS_ERR(child)) |
831 | return PTR_ERR(child); | 862 | return PTR_ERR(child); |
832 | 863 | ||
833 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); | 864 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac, |
865 | features); | ||
834 | if (IS_ERR(child)) | 866 | if (IS_ERR(child)) |
835 | return PTR_ERR(child); | 867 | return PTR_ERR(child); |
836 | 868 | ||
837 | child = add_regulator((features & TWL4030_VAUX2) | 869 | child = add_regulator((features & TWL4030_VAUX2) |
838 | ? TWL4030_REG_VAUX2_4030 | 870 | ? TWL4030_REG_VAUX2_4030 |
839 | : TWL4030_REG_VAUX2, | 871 | : TWL4030_REG_VAUX2, |
840 | pdata->vaux2); | 872 | pdata->vaux2, features); |
841 | if (IS_ERR(child)) | 873 | if (IS_ERR(child)) |
842 | return PTR_ERR(child); | 874 | return PTR_ERR(child); |
843 | 875 | ||
844 | child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1); | 876 | child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1, |
877 | features); | ||
845 | if (IS_ERR(child)) | 878 | if (IS_ERR(child)) |
846 | return PTR_ERR(child); | 879 | return PTR_ERR(child); |
847 | 880 | ||
848 | child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2); | 881 | child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2, |
882 | features); | ||
849 | if (IS_ERR(child)) | 883 | if (IS_ERR(child)) |
850 | return PTR_ERR(child); | 884 | return PTR_ERR(child); |
851 | 885 | ||
852 | child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig); | 886 | child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig, |
887 | features); | ||
853 | if (IS_ERR(child)) | 888 | if (IS_ERR(child)) |
854 | return PTR_ERR(child); | 889 | return PTR_ERR(child); |
855 | } | 890 | } |
@@ -857,72 +892,152 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
857 | /* maybe add LDOs that are omitted on cost-reduced parts */ | 892 | /* maybe add LDOs that are omitted on cost-reduced parts */ |
858 | if (twl_has_regulator() && !(features & TPS_SUBSET) | 893 | if (twl_has_regulator() && !(features & TPS_SUBSET) |
859 | && twl_class_is_4030()) { | 894 | && twl_class_is_4030()) { |
860 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); | 895 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2, |
896 | features); | ||
861 | if (IS_ERR(child)) | 897 | if (IS_ERR(child)) |
862 | return PTR_ERR(child); | 898 | return PTR_ERR(child); |
863 | 899 | ||
864 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); | 900 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2, |
901 | features); | ||
865 | if (IS_ERR(child)) | 902 | if (IS_ERR(child)) |
866 | return PTR_ERR(child); | 903 | return PTR_ERR(child); |
867 | 904 | ||
868 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); | 905 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim, |
906 | features); | ||
869 | if (IS_ERR(child)) | 907 | if (IS_ERR(child)) |
870 | return PTR_ERR(child); | 908 | return PTR_ERR(child); |
871 | 909 | ||
872 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); | 910 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1, |
911 | features); | ||
873 | if (IS_ERR(child)) | 912 | if (IS_ERR(child)) |
874 | return PTR_ERR(child); | 913 | return PTR_ERR(child); |
875 | 914 | ||
876 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); | 915 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3, |
916 | features); | ||
877 | if (IS_ERR(child)) | 917 | if (IS_ERR(child)) |
878 | return PTR_ERR(child); | 918 | return PTR_ERR(child); |
879 | 919 | ||
880 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); | 920 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4, |
921 | features); | ||
881 | if (IS_ERR(child)) | 922 | if (IS_ERR(child)) |
882 | return PTR_ERR(child); | 923 | return PTR_ERR(child); |
883 | } | 924 | } |
884 | 925 | ||
885 | /* twl6030 regulators */ | 926 | /* twl6030 regulators */ |
927 | if (twl_has_regulator() && twl_class_is_6030() && | ||
928 | !(features & TWL6025_SUBCLASS)) { | ||
929 | child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc, | ||
930 | features); | ||
931 | if (IS_ERR(child)) | ||
932 | return PTR_ERR(child); | ||
933 | |||
934 | child = add_regulator(TWL6030_REG_VPP, pdata->vpp, | ||
935 | features); | ||
936 | if (IS_ERR(child)) | ||
937 | return PTR_ERR(child); | ||
938 | |||
939 | child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim, | ||
940 | features); | ||
941 | if (IS_ERR(child)) | ||
942 | return PTR_ERR(child); | ||
943 | |||
944 | child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio, | ||
945 | features); | ||
946 | if (IS_ERR(child)) | ||
947 | return PTR_ERR(child); | ||
948 | |||
949 | child = add_regulator(TWL6030_REG_VDAC, pdata->vdac, | ||
950 | features); | ||
951 | if (IS_ERR(child)) | ||
952 | return PTR_ERR(child); | ||
953 | |||
954 | child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1, | ||
955 | features); | ||
956 | if (IS_ERR(child)) | ||
957 | return PTR_ERR(child); | ||
958 | |||
959 | child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2, | ||
960 | features); | ||
961 | if (IS_ERR(child)) | ||
962 | return PTR_ERR(child); | ||
963 | |||
964 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3, | ||
965 | features); | ||
966 | if (IS_ERR(child)) | ||
967 | return PTR_ERR(child); | ||
968 | |||
969 | child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg, | ||
970 | features); | ||
971 | if (IS_ERR(child)) | ||
972 | return PTR_ERR(child); | ||
973 | } | ||
974 | |||
975 | /* 6030 and 6025 share this regulator */ | ||
886 | if (twl_has_regulator() && twl_class_is_6030()) { | 976 | if (twl_has_regulator() && twl_class_is_6030()) { |
887 | child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); | 977 | child = add_regulator(TWL6030_REG_VANA, pdata->vana, |
978 | features); | ||
979 | if (IS_ERR(child)) | ||
980 | return PTR_ERR(child); | ||
981 | } | ||
982 | |||
983 | /* twl6025 regulators */ | ||
984 | if (twl_has_regulator() && twl_class_is_6030() && | ||
985 | (features & TWL6025_SUBCLASS)) { | ||
986 | child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5, | ||
987 | features); | ||
888 | if (IS_ERR(child)) | 988 | if (IS_ERR(child)) |
889 | return PTR_ERR(child); | 989 | return PTR_ERR(child); |
890 | 990 | ||
891 | child = add_regulator(TWL6030_REG_VPP, pdata->vpp); | 991 | child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1, |
992 | features); | ||
892 | if (IS_ERR(child)) | 993 | if (IS_ERR(child)) |
893 | return PTR_ERR(child); | 994 | return PTR_ERR(child); |
894 | 995 | ||
895 | child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); | 996 | child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7, |
997 | features); | ||
896 | if (IS_ERR(child)) | 998 | if (IS_ERR(child)) |
897 | return PTR_ERR(child); | 999 | return PTR_ERR(child); |
898 | 1000 | ||
899 | child = add_regulator(TWL6030_REG_VANA, pdata->vana); | 1001 | child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6, |
1002 | features); | ||
900 | if (IS_ERR(child)) | 1003 | if (IS_ERR(child)) |
901 | return PTR_ERR(child); | 1004 | return PTR_ERR(child); |
902 | 1005 | ||
903 | child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); | 1006 | child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln, |
1007 | features); | ||
904 | if (IS_ERR(child)) | 1008 | if (IS_ERR(child)) |
905 | return PTR_ERR(child); | 1009 | return PTR_ERR(child); |
906 | 1010 | ||
907 | child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); | 1011 | child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2, |
1012 | features); | ||
908 | if (IS_ERR(child)) | 1013 | if (IS_ERR(child)) |
909 | return PTR_ERR(child); | 1014 | return PTR_ERR(child); |
910 | 1015 | ||
911 | child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); | 1016 | child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4, |
1017 | features); | ||
912 | if (IS_ERR(child)) | 1018 | if (IS_ERR(child)) |
913 | return PTR_ERR(child); | 1019 | return PTR_ERR(child); |
914 | 1020 | ||
915 | child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); | 1021 | child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3, |
1022 | features); | ||
916 | if (IS_ERR(child)) | 1023 | if (IS_ERR(child)) |
917 | return PTR_ERR(child); | 1024 | return PTR_ERR(child); |
918 | 1025 | ||
919 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); | 1026 | child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3, |
1027 | features); | ||
920 | if (IS_ERR(child)) | 1028 | if (IS_ERR(child)) |
921 | return PTR_ERR(child); | 1029 | return PTR_ERR(child); |
922 | 1030 | ||
923 | child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg); | 1031 | child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4, |
1032 | features); | ||
924 | if (IS_ERR(child)) | 1033 | if (IS_ERR(child)) |
925 | return PTR_ERR(child); | 1034 | return PTR_ERR(child); |
1035 | |||
1036 | child = add_regulator(TWL6025_REG_VIO, pdata->vio6025, | ||
1037 | features); | ||
1038 | if (IS_ERR(child)) | ||
1039 | return PTR_ERR(child); | ||
1040 | |||
926 | } | 1041 | } |
927 | 1042 | ||
928 | if (twl_has_bci() && pdata->bci && | 1043 | if (twl_has_bci() && pdata->bci && |
@@ -1170,6 +1285,7 @@ static const struct i2c_device_id twl_ids[] = { | |||
1170 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ | 1285 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ |
1171 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ | 1286 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ |
1172 | { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ | 1287 | { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ |
1288 | { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */ | ||
1173 | { /* end of list */ }, | 1289 | { /* end of list */ }, |
1174 | }; | 1290 | }; |
1175 | MODULE_DEVICE_TABLE(i2c, twl_ids); | 1291 | MODULE_DEVICE_TABLE(i2c, twl_ids); |