diff options
Diffstat (limited to 'drivers/regulator/qcom_rpm-regulator.c')
-rw-r--r-- | drivers/regulator/qcom_rpm-regulator.c | 244 |
1 files changed, 161 insertions, 83 deletions
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index bd8360ca7750..40cf6ff0d1ff 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c | |||
@@ -607,31 +607,6 @@ static const struct qcom_rpm_reg smb208_smps = { | |||
607 | .supports_force_mode_bypass = false, | 607 | .supports_force_mode_bypass = false, |
608 | }; | 608 | }; |
609 | 609 | ||
610 | static const struct of_device_id rpm_of_match[] = { | ||
611 | { .compatible = "qcom,rpm-pm8058-pldo", .data = &pm8058_pldo }, | ||
612 | { .compatible = "qcom,rpm-pm8058-nldo", .data = &pm8058_nldo }, | ||
613 | { .compatible = "qcom,rpm-pm8058-smps", .data = &pm8058_smps }, | ||
614 | { .compatible = "qcom,rpm-pm8058-ncp", .data = &pm8058_ncp }, | ||
615 | { .compatible = "qcom,rpm-pm8058-switch", .data = &pm8058_switch }, | ||
616 | |||
617 | { .compatible = "qcom,rpm-pm8901-pldo", .data = &pm8901_pldo }, | ||
618 | { .compatible = "qcom,rpm-pm8901-nldo", .data = &pm8901_nldo }, | ||
619 | { .compatible = "qcom,rpm-pm8901-ftsmps", .data = &pm8901_ftsmps }, | ||
620 | { .compatible = "qcom,rpm-pm8901-switch", .data = &pm8901_switch }, | ||
621 | |||
622 | { .compatible = "qcom,rpm-pm8921-pldo", .data = &pm8921_pldo }, | ||
623 | { .compatible = "qcom,rpm-pm8921-nldo", .data = &pm8921_nldo }, | ||
624 | { .compatible = "qcom,rpm-pm8921-nldo1200", .data = &pm8921_nldo1200 }, | ||
625 | { .compatible = "qcom,rpm-pm8921-smps", .data = &pm8921_smps }, | ||
626 | { .compatible = "qcom,rpm-pm8921-ftsmps", .data = &pm8921_ftsmps }, | ||
627 | { .compatible = "qcom,rpm-pm8921-ncp", .data = &pm8921_ncp }, | ||
628 | { .compatible = "qcom,rpm-pm8921-switch", .data = &pm8921_switch }, | ||
629 | |||
630 | { .compatible = "qcom,rpm-smb208", .data = &smb208_smps }, | ||
631 | { } | ||
632 | }; | ||
633 | MODULE_DEVICE_TABLE(of, rpm_of_match); | ||
634 | |||
635 | static int rpm_reg_set(struct qcom_rpm_reg *vreg, | 610 | static int rpm_reg_set(struct qcom_rpm_reg *vreg, |
636 | const struct request_member *req, | 611 | const struct request_member *req, |
637 | const int value) | 612 | const int value) |
@@ -773,74 +748,177 @@ static int rpm_reg_of_parse(struct device_node *node, | |||
773 | return 0; | 748 | return 0; |
774 | } | 749 | } |
775 | 750 | ||
776 | static int rpm_reg_probe(struct platform_device *pdev) | 751 | struct rpm_regulator_data { |
777 | { | 752 | const char *name; |
778 | struct regulator_init_data *initdata; | 753 | int resource; |
779 | const struct qcom_rpm_reg *template; | 754 | const struct qcom_rpm_reg *template; |
780 | const struct of_device_id *match; | 755 | const char *supply; |
781 | struct regulator_config config = { }; | 756 | }; |
782 | struct regulator_dev *rdev; | 757 | |
783 | struct qcom_rpm_reg *vreg; | 758 | static const struct rpm_regulator_data rpm_pm8058_regulators[] = { |
784 | const char *key; | 759 | { "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" }, |
785 | u32 val; | 760 | { "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" }, |
786 | int ret; | 761 | { "l2", QCOM_RPM_PM8058_LDO2, &pm8058_pldo, "vdd_l2_l11_l12" }, |
762 | { "l3", QCOM_RPM_PM8058_LDO3, &pm8058_pldo, "vdd_l3_l4_l5" }, | ||
763 | { "l4", QCOM_RPM_PM8058_LDO4, &pm8058_pldo, "vdd_l3_l4_l5" }, | ||
764 | { "l5", QCOM_RPM_PM8058_LDO5, &pm8058_pldo, "vdd_l3_l4_l5" }, | ||
765 | { "l6", QCOM_RPM_PM8058_LDO6, &pm8058_pldo, "vdd_l6_l7" }, | ||
766 | { "l7", QCOM_RPM_PM8058_LDO7, &pm8058_pldo, "vdd_l6_l7" }, | ||
767 | { "l8", QCOM_RPM_PM8058_LDO8, &pm8058_pldo, "vdd_l8" }, | ||
768 | { "l9", QCOM_RPM_PM8058_LDO9, &pm8058_pldo, "vdd_l9" }, | ||
769 | { "l10", QCOM_RPM_PM8058_LDO10, &pm8058_pldo, "vdd_l10" }, | ||
770 | { "l11", QCOM_RPM_PM8058_LDO11, &pm8058_pldo, "vdd_l2_l11_l12" }, | ||
771 | { "l12", QCOM_RPM_PM8058_LDO12, &pm8058_pldo, "vdd_l2_l11_l12" }, | ||
772 | { "l13", QCOM_RPM_PM8058_LDO13, &pm8058_pldo, "vdd_l13_l16" }, | ||
773 | { "l14", QCOM_RPM_PM8058_LDO14, &pm8058_pldo, "vdd_l14_l15" }, | ||
774 | { "l15", QCOM_RPM_PM8058_LDO15, &pm8058_pldo, "vdd_l14_l15" }, | ||
775 | { "l16", QCOM_RPM_PM8058_LDO16, &pm8058_pldo, "vdd_l13_l16" }, | ||
776 | { "l17", QCOM_RPM_PM8058_LDO17, &pm8058_pldo, "vdd_l17_l18" }, | ||
777 | { "l18", QCOM_RPM_PM8058_LDO18, &pm8058_pldo, "vdd_l17_l18" }, | ||
778 | { "l19", QCOM_RPM_PM8058_LDO19, &pm8058_pldo, "vdd_l19_l20" }, | ||
779 | { "l20", QCOM_RPM_PM8058_LDO20, &pm8058_pldo, "vdd_l19_l20" }, | ||
780 | { "l21", QCOM_RPM_PM8058_LDO21, &pm8058_nldo, "vdd_l21" }, | ||
781 | { "l22", QCOM_RPM_PM8058_LDO22, &pm8058_nldo, "vdd_l22" }, | ||
782 | { "l23", QCOM_RPM_PM8058_LDO23, &pm8058_nldo, "vdd_l23_l24_l25" }, | ||
783 | { "l24", QCOM_RPM_PM8058_LDO24, &pm8058_nldo, "vdd_l23_l24_l25" }, | ||
784 | { "l25", QCOM_RPM_PM8058_LDO25, &pm8058_nldo, "vdd_l23_l24_l25" }, | ||
785 | |||
786 | { "s0", QCOM_RPM_PM8058_SMPS0, &pm8058_smps, "vdd_s0" }, | ||
787 | { "s1", QCOM_RPM_PM8058_SMPS1, &pm8058_smps, "vdd_s1" }, | ||
788 | { "s2", QCOM_RPM_PM8058_SMPS2, &pm8058_smps, "vdd_s2" }, | ||
789 | { "s3", QCOM_RPM_PM8058_SMPS3, &pm8058_smps, "vdd_s3" }, | ||
790 | { "s4", QCOM_RPM_PM8058_SMPS4, &pm8058_smps, "vdd_s4" }, | ||
791 | |||
792 | { "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" }, | ||
793 | { "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" }, | ||
794 | |||
795 | { "ncp", QCOM_RPM_PM8058_NCP, &pm8058_ncp, "vdd_ncp" }, | ||
796 | { } | ||
797 | }; | ||
787 | 798 | ||
788 | match = of_match_device(rpm_of_match, &pdev->dev); | 799 | static const struct rpm_regulator_data rpm_pm8901_regulators[] = { |
789 | template = match->data; | 800 | { "l0", QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" }, |
801 | { "l1", QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" }, | ||
802 | { "l2", QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" }, | ||
803 | { "l3", QCOM_RPM_PM8901_LDO3, &pm8901_pldo, "vdd_l3" }, | ||
804 | { "l4", QCOM_RPM_PM8901_LDO4, &pm8901_pldo, "vdd_l4" }, | ||
805 | { "l5", QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" }, | ||
806 | { "l6", QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" }, | ||
790 | 807 | ||
791 | vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); | 808 | { "s0", QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" }, |
792 | if (!vreg) { | 809 | { "s1", QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" }, |
793 | dev_err(&pdev->dev, "failed to allocate vreg\n"); | 810 | { "s2", QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" }, |
794 | return -ENOMEM; | 811 | { "s3", QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" }, |
795 | } | 812 | { "s4", QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" }, |
796 | memcpy(vreg, template, sizeof(*vreg)); | ||
797 | mutex_init(&vreg->lock); | ||
798 | vreg->dev = &pdev->dev; | ||
799 | vreg->desc.id = -1; | ||
800 | vreg->desc.owner = THIS_MODULE; | ||
801 | vreg->desc.type = REGULATOR_VOLTAGE; | ||
802 | vreg->desc.name = pdev->dev.of_node->name; | ||
803 | vreg->desc.supply_name = "vin"; | ||
804 | |||
805 | vreg->rpm = dev_get_drvdata(pdev->dev.parent); | ||
806 | if (!vreg->rpm) { | ||
807 | dev_err(&pdev->dev, "unable to retrieve handle to rpm\n"); | ||
808 | return -ENODEV; | ||
809 | } | ||
810 | 813 | ||
811 | initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, | 814 | { "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" }, |
812 | &vreg->desc); | 815 | { "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" }, |
813 | if (!initdata) | 816 | { "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" }, |
814 | return -EINVAL; | 817 | { "lvs3", QCOM_RPM_PM8901_LVS3, &pm8901_switch, "lvs3_in" }, |
815 | 818 | ||
816 | key = "reg"; | 819 | { "mvs", QCOM_RPM_PM8901_MVS, &pm8901_switch, "mvs_in" }, |
817 | ret = of_property_read_u32(pdev->dev.of_node, key, &val); | 820 | { } |
818 | if (ret) { | 821 | }; |
819 | dev_err(&pdev->dev, "failed to read %s\n", key); | ||
820 | return ret; | ||
821 | } | ||
822 | vreg->resource = val; | ||
823 | 822 | ||
824 | if ((vreg->parts->uV.mask || vreg->parts->mV.mask) && | 823 | static const struct rpm_regulator_data rpm_pm8921_regulators[] = { |
825 | (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) { | 824 | { "s1", QCOM_RPM_PM8921_SMPS1, &pm8921_smps, "vdd_s1" }, |
826 | dev_err(&pdev->dev, "no voltage specified for regulator\n"); | 825 | { "s2", QCOM_RPM_PM8921_SMPS2, &pm8921_smps, "vdd_s2" }, |
827 | return -EINVAL; | 826 | { "s3", QCOM_RPM_PM8921_SMPS3, &pm8921_smps }, |
828 | } | 827 | { "s4", QCOM_RPM_PM8921_SMPS4, &pm8921_smps, "vdd_s4" }, |
828 | { "s7", QCOM_RPM_PM8921_SMPS7, &pm8921_smps, "vdd_s7" }, | ||
829 | { "s8", QCOM_RPM_PM8921_SMPS8, &pm8921_smps, "vdd_s8" }, | ||
830 | |||
831 | { "l1", QCOM_RPM_PM8921_LDO1, &pm8921_nldo, "vdd_l1_l2_l12_l18" }, | ||
832 | { "l2", QCOM_RPM_PM8921_LDO2, &pm8921_nldo, "vdd_l1_l2_l12_l18" }, | ||
833 | { "l3", QCOM_RPM_PM8921_LDO3, &pm8921_pldo, "vdd_l3_l15_l17" }, | ||
834 | { "l4", QCOM_RPM_PM8921_LDO4, &pm8921_pldo, "vdd_l4_l14" }, | ||
835 | { "l5", QCOM_RPM_PM8921_LDO5, &pm8921_pldo, "vdd_l5_l8_l16" }, | ||
836 | { "l6", QCOM_RPM_PM8921_LDO6, &pm8921_pldo, "vdd_l6_l7" }, | ||
837 | { "l7", QCOM_RPM_PM8921_LDO7, &pm8921_pldo, "vdd_l6_l7" }, | ||
838 | { "l8", QCOM_RPM_PM8921_LDO8, &pm8921_pldo, "vdd_l5_l8_l16" }, | ||
839 | { "l9", QCOM_RPM_PM8921_LDO9, &pm8921_pldo, "vdd_l9_l11" }, | ||
840 | { "l10", QCOM_RPM_PM8921_LDO10, &pm8921_pldo, "vdd_l10_l22" }, | ||
841 | { "l11", QCOM_RPM_PM8921_LDO11, &pm8921_pldo, "vdd_l9_l11" }, | ||
842 | { "l12", QCOM_RPM_PM8921_LDO12, &pm8921_nldo, "vdd_l1_l2_l12_l18" }, | ||
843 | { "l14", QCOM_RPM_PM8921_LDO14, &pm8921_pldo, "vdd_l4_l14" }, | ||
844 | { "l15", QCOM_RPM_PM8921_LDO15, &pm8921_pldo, "vdd_l3_l15_l17" }, | ||
845 | { "l16", QCOM_RPM_PM8921_LDO16, &pm8921_pldo, "vdd_l5_l8_l16" }, | ||
846 | { "l17", QCOM_RPM_PM8921_LDO17, &pm8921_pldo, "vdd_l3_l15_l17" }, | ||
847 | { "l18", QCOM_RPM_PM8921_LDO18, &pm8921_nldo, "vdd_l1_l2_l12_l18" }, | ||
848 | { "l21", QCOM_RPM_PM8921_LDO21, &pm8921_pldo, "vdd_l21_l23_l29" }, | ||
849 | { "l22", QCOM_RPM_PM8921_LDO22, &pm8921_pldo, "vdd_l10_l22" }, | ||
850 | { "l23", QCOM_RPM_PM8921_LDO23, &pm8921_pldo, "vdd_l21_l23_l29" }, | ||
851 | { "l24", QCOM_RPM_PM8921_LDO24, &pm8921_nldo1200, "vdd_l24" }, | ||
852 | { "l25", QCOM_RPM_PM8921_LDO25, &pm8921_nldo1200, "vdd_l25" }, | ||
853 | { "l26", QCOM_RPM_PM8921_LDO26, &pm8921_nldo1200, "vdd_l26" }, | ||
854 | { "l27", QCOM_RPM_PM8921_LDO27, &pm8921_nldo1200, "vdd_l27" }, | ||
855 | { "l28", QCOM_RPM_PM8921_LDO28, &pm8921_nldo1200, "vdd_l28" }, | ||
856 | { "l29", QCOM_RPM_PM8921_LDO29, &pm8921_pldo, "vdd_l21_l23_l29" }, | ||
857 | |||
858 | { "lvs1", QCOM_RPM_PM8921_LVS1, &pm8921_switch, "vin_lvs1_3_6" }, | ||
859 | { "lvs2", QCOM_RPM_PM8921_LVS2, &pm8921_switch, "vin_lvs2" }, | ||
860 | { "lvs3", QCOM_RPM_PM8921_LVS3, &pm8921_switch, "vin_lvs1_3_6" }, | ||
861 | { "lvs4", QCOM_RPM_PM8921_LVS4, &pm8921_switch, "vin_lvs4_5_7" }, | ||
862 | { "lvs5", QCOM_RPM_PM8921_LVS5, &pm8921_switch, "vin_lvs4_5_7" }, | ||
863 | { "lvs6", QCOM_RPM_PM8921_LVS6, &pm8921_switch, "vin_lvs1_3_6" }, | ||
864 | { "lvs7", QCOM_RPM_PM8921_LVS7, &pm8921_switch, "vin_lvs4_5_7" }, | ||
865 | |||
866 | { "usb-switch", QCOM_RPM_USB_OTG_SWITCH, &pm8921_switch, "vin_5vs" }, | ||
867 | { "hdmi-switch", QCOM_RPM_HDMI_SWITCH, &pm8921_switch, "vin_5vs" }, | ||
868 | { "ncp", QCOM_RPM_PM8921_NCP, &pm8921_ncp, "vdd_ncp" }, | ||
869 | { } | ||
870 | }; | ||
829 | 871 | ||
872 | static const struct of_device_id rpm_of_match[] = { | ||
873 | { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, | ||
874 | { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, | ||
875 | { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, | ||
876 | { } | ||
877 | }; | ||
878 | MODULE_DEVICE_TABLE(of, rpm_of_match); | ||
830 | 879 | ||
831 | config.dev = &pdev->dev; | 880 | static int rpm_reg_probe(struct platform_device *pdev) |
832 | config.init_data = initdata; | 881 | { |
833 | config.driver_data = vreg; | 882 | const struct rpm_regulator_data *reg; |
834 | config.of_node = pdev->dev.of_node; | 883 | const struct of_device_id *match; |
884 | struct regulator_config config = { }; | ||
885 | struct regulator_dev *rdev; | ||
886 | struct qcom_rpm_reg *vreg; | ||
835 | 887 | ||
836 | ret = rpm_reg_of_parse(pdev->dev.of_node, &vreg->desc, &config); | 888 | match = of_match_device(rpm_of_match, &pdev->dev); |
837 | if (ret) | 889 | for (reg = match->data; reg->name; reg++) { |
838 | return ret; | 890 | vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); |
891 | if (!vreg) { | ||
892 | dev_err(&pdev->dev, "failed to allocate vreg\n"); | ||
893 | return -ENOMEM; | ||
894 | } | ||
895 | memcpy(vreg, reg->template, sizeof(*vreg)); | ||
896 | mutex_init(&vreg->lock); | ||
897 | |||
898 | vreg->dev = &pdev->dev; | ||
899 | vreg->resource = reg->resource; | ||
900 | |||
901 | vreg->desc.id = -1; | ||
902 | vreg->desc.owner = THIS_MODULE; | ||
903 | vreg->desc.type = REGULATOR_VOLTAGE; | ||
904 | vreg->desc.name = reg->name; | ||
905 | vreg->desc.supply_name = reg->supply; | ||
906 | vreg->desc.of_match = reg->name; | ||
907 | vreg->desc.of_parse_cb = rpm_reg_of_parse; | ||
908 | |||
909 | vreg->rpm = dev_get_drvdata(pdev->dev.parent); | ||
910 | if (!vreg->rpm) { | ||
911 | dev_err(&pdev->dev, "unable to retrieve handle to rpm\n"); | ||
912 | return -ENODEV; | ||
913 | } | ||
839 | 914 | ||
840 | rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config); | 915 | config.dev = &pdev->dev; |
841 | if (IS_ERR(rdev)) { | 916 | config.driver_data = vreg; |
842 | dev_err(&pdev->dev, "can't register regulator\n"); | 917 | rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config); |
843 | return PTR_ERR(rdev); | 918 | if (IS_ERR(rdev)) { |
919 | dev_err(&pdev->dev, "can't register regulator\n"); | ||
920 | return PTR_ERR(rdev); | ||
921 | } | ||
844 | } | 922 | } |
845 | 923 | ||
846 | return 0; | 924 | return 0; |