diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index 00c5cc3d9546..538733bb7e8b 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -581,27 +581,347 @@ static const struct qcom_rpm_reg smb208_smps = {
 	.supports_force_mode_bypass = false,
 };
 
+struct qcom_rpm_reg_desc {
+	const struct qcom_rpm_reg *template;
+	int resource;
+	const char *supply;
+};
+
+struct qcom_rpm_of_match {
+	struct of_regulator_match *of_match;
+	unsigned int size;
+};
+
+#define DEFINE_QCOM_RPM_OF_MATCH(t)		\
+	struct qcom_rpm_of_match t##_m = {	\
+		.of_match = (t), 		\
+		.size = ARRAY_SIZE(t), 		\
+	}
+
+static struct of_regulator_match pm8921_regs[] = {
+	{
+		.name = "s1",
+		.driver_data = &(struct qcom_rpm_reg_desc){
+			.template = &pm8921_smps,
+			.resource = QCOM_RPM_PM8921_SMPS1,
+		},
+	},
+	{
+		.name = "s2",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_smps,
+			.resource = QCOM_RPM_PM8921_SMPS2,
+		},
+	},
+	{
+		.name = "s3",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_smps,
+			.resource = QCOM_RPM_PM8921_SMPS3,
+		},
+	},
+	{
+		.name = "s4",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_smps,
+			.resource = QCOM_RPM_PM8921_SMPS4,
+		},
+	},
+	{
+		.name = "s7",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_smps,
+			.resource = QCOM_RPM_PM8921_SMPS7,
+		},
+	},
+	{
+		.name = "s8",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_smps,
+			.resource = QCOM_RPM_PM8921_SMPS8,
+		},
+	},
+	{
+		.name = "l1",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo,
+			.resource = QCOM_RPM_PM8921_LDO1,
+			.supply = "vin_l1_l2_l12_l18",
+		},
+	},
+	{
+		.name = "l2",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo,
+			.resource = QCOM_RPM_PM8921_LDO2,
+			.supply = "vin_l1_l2_l12_l18",
+		},
+	},
+	{
+		.name = "l3",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO3,
+		},
+	},
+	{
+		.name = "l4",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO4,
+		},
+	},
+	{
+		.name = "l5",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO5,
+		},
+	},
+	{
+		.name = "l6",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO6,
+		},
+	},
+	{
+		.name = "l7",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO7,
+		},
+	},
+	{
+		.name = "l8",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO8,
+		},
+	},
+	{
+		.name = "l9",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO9,
+		},
+	},
+	{
+		.name = "l10",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO10,
+		},
+	},
+	{
+		.name = "l11",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO11,
+		},
+	},
+	{
+		.name = "l12",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo,
+			.resource = QCOM_RPM_PM8921_LDO12,
+			.supply = "vin_l1_l2_l12_l18",
+		},
+	},
+	{
+		.name = "l13",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO13,
+		},
+	},
+	{
+		.name = "l14",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO14,
+		},
+	},
+	{
+		.name = "l15",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO15,
+		},
+	},
+	{
+		.name = "l16",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO16,
+		},
+	},
+	{
+		.name = "l17",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO17,
+		},
+	},
+	{
+		.name = "l18",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo,
+			.resource = QCOM_RPM_PM8921_LDO18,
+			.supply = "vin_l1_l2_l12_l18",
+		},
+	},
+	{
+		.name = "l21",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO21,
+		},
+	},
+	{
+		.name = "l22",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO22,
+		},
+	},
+	{
+		.name = "l23",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO23,
+		},
+	},
+	{
+		.name = "l24",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo1200,
+			.resource = QCOM_RPM_PM8921_LDO24,
+			.supply = "vin_l24",
+		},
+	},
+	{
+		.name = "l25",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo1200,
+			.resource = QCOM_RPM_PM8921_LDO25,
+			.supply = "vin_l25",
+		},
+	},
+	{
+		.name = "l26",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo1200,
+			.resource = QCOM_RPM_PM8921_LDO26,
+		},
+	},
+	{
+		.name = "l27",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo1200,
+			.resource = QCOM_RPM_PM8921_LDO27,
+			.supply = "vin_l27",
+		},
+	},
+	{
+		.name = "l28",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_nldo1200,
+			.resource = QCOM_RPM_PM8921_LDO28,
+			.supply = "vin_l28",
+		},
+	},
+	{
+		.name = "l29",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_pldo,
+			.resource = QCOM_RPM_PM8921_LDO29
+		},
+	},
+	{
+		.name = "lvs1",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS1,
+			.supply = "vin_lvs_1_3_6",
+		},
+	},
+	{
+		.name = "lvs2",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS2,
+			.supply = "vin_lvs2",
+		},
+	},
+	{
+		.name = "lvs3",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS3,
+			.supply = "vin_lvs_1_3_6",
+		},
+	},
+	{
+		.name = "lvs4",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS4,
+			.supply = "vin_lvs_4_5_7",
+		},
+	},
+	{
+		.name = "lvs5",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS5,
+			.supply = "vin_lvs_4_5_7",
+		},
+	},
+	{
+		.name = "lvs6",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS6,
+			.supply = "vin_lvs_1_3_6",
+		},
+	},
+	{
+		.name = "lvs7",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_PM8921_LVS7,
+			.supply = "vin_lvs_4_5_7",
+		},
+	},
+	{
+		.name = "usb-switch",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_USB_OTG_SWITCH,
+		},
+	},
+	{
+		.name = "hdmi-switch",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_switch,
+			.resource = QCOM_RPM_HDMI_SWITCH,
+		},
+	},
+	{
+		.name = "ncp",
+		.driver_data = &(struct qcom_rpm_reg_desc) {
+			.template = &pm8921_ncp,
+			.resource = QCOM_RPM_PM8921_NCP,
+			.supply = "vin_ncp",
+		},
+	},
+};
+
+static DEFINE_QCOM_RPM_OF_MATCH(pm8921_regs);
+
 static const struct of_device_id rpm_of_match[] = {
-	{ .compatible = "qcom,rpm-pm8058-pldo",     .data = &pm8058_pldo },
-	{ .compatible = "qcom,rpm-pm8058-nldo",     .data = &pm8058_nldo },
-	{ .compatible = "qcom,rpm-pm8058-smps",     .data = &pm8058_smps },
-	{ .compatible = "qcom,rpm-pm8058-ncp",      .data = &pm8058_ncp },
-	{ .compatible = "qcom,rpm-pm8058-switch",   .data = &pm8058_switch },
-
-	{ .compatible = "qcom,rpm-pm8901-pldo",     .data = &pm8901_pldo },
-	{ .compatible = "qcom,rpm-pm8901-nldo",     .data = &pm8901_nldo },
-	{ .compatible = "qcom,rpm-pm8901-ftsmps",   .data = &pm8901_ftsmps },
-	{ .compatible = "qcom,rpm-pm8901-switch",   .data = &pm8901_switch },
-
-	{ .compatible = "qcom,rpm-pm8921-pldo",     .data = &pm8921_pldo },
-	{ .compatible = "qcom,rpm-pm8921-nldo",     .data = &pm8921_nldo },
-	{ .compatible = "qcom,rpm-pm8921-nldo1200", .data = &pm8921_nldo1200 },
-	{ .compatible = "qcom,rpm-pm8921-smps",     .data = &pm8921_smps },
-	{ .compatible = "qcom,rpm-pm8921-ftsmps",   .data = &pm8921_ftsmps },
-	{ .compatible = "qcom,rpm-pm8921-ncp",      .data = &pm8921_ncp },
-	{ .compatible = "qcom,rpm-pm8921-switch",   .data = &pm8921_switch },
-
-	{ .compatible = "qcom,rpm-smb208", .data = &smb208_smps },
+	{ .compatible = "qcom,rpm-pm8921-regulators", .data = &pm8921_regs_m },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, rpm_of_match);
@@ -619,7 +939,8 @@ static int rpm_reg_set(struct qcom_rpm_reg *vreg,
 	return 0;
 }
 
-static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
+static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg,
+		struct device_node *of_node)
 {
 	static const int freq_table[] = {
 		19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
@@ -633,9 +954,10 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
 	int i;
 
 	key = "qcom,switch-mode-frequency";
-	ret = of_property_read_u32(dev->of_node, key, &freq);
+	ret = of_property_read_u32(of_node, key, &freq);
 	if (ret) {
-		dev_err(dev, "regulator requires %s property\n", key);
+		dev_err(dev, "regulator %s requires %s property\n",
+				vreg->desc.name, key);
 		return -EINVAL;
 	}
 
@@ -646,88 +968,74 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
 		}
 	}
 
-	dev_err(dev, "invalid frequency %d\n", freq);
+	dev_err(dev, "regulator %s has invalid frequency %d\n", vreg->desc.name,
+			freq);
 	return -EINVAL;
 }
 
-static int rpm_reg_probe(struct platform_device *pdev)
+static int rpm_regulator_register(struct platform_device *pdev,
+				  struct of_regulator_match *match,
+				  struct qcom_rpm *rpm)
 {
+	struct qcom_rpm_reg_desc *rpm_desc = match->driver_data;
 	struct regulator_init_data *initdata;
-	const struct qcom_rpm_reg *template;
-	const struct of_device_id *match;
 	struct regulator_config config = { };
 	struct regulator_dev *rdev;
 	struct qcom_rpm_reg *vreg;
+	struct device_node *of_node = match->of_node;
 	const char *key;
 	u32 force_mode;
 	bool pwm;
 	u32 val;
 	int ret;
 
-	match = of_match_device(rpm_of_match, &pdev->dev);
-	template = match->data;
-
 	vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
-	if (!vreg) {
-		dev_err(&pdev->dev, "failed to allocate vreg\n");
+	if (!vreg)
 		return -ENOMEM;
-	}
-	memcpy(vreg, template, sizeof(*vreg));
+
+	memcpy(vreg, rpm_desc->template, sizeof(*vreg));
 	mutex_init(&vreg->lock);
 	vreg->dev = &pdev->dev;
 	vreg->desc.id = -1;
 	vreg->desc.owner = THIS_MODULE;
 	vreg->desc.type = REGULATOR_VOLTAGE;
-	vreg->desc.name = pdev->dev.of_node->name;
-	vreg->desc.supply_name = "vin";
-
+	vreg->desc.name = of_node->name;
+	vreg->desc.supply_name = rpm_desc->supply;
 	vreg->rpm = dev_get_drvdata(pdev->dev.parent);
-	if (!vreg->rpm) {
-		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
-		return -ENODEV;
-	}
-
-	initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
-					      &vreg->desc);
-	if (!initdata)
-		return -EINVAL;
-
-	key = "reg";
-	ret = of_property_read_u32(pdev->dev.of_node, key, &val);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to read %s\n", key);
-		return ret;
-	}
-	vreg->resource = val;
+	vreg->resource = rpm_desc->resource;
+	initdata = match->init_data;
 
 	if ((vreg->parts->uV.mask || vreg->parts->mV.mask) &&
 	    (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) {
-		dev_err(&pdev->dev, "no voltage specified for regulator\n");
+		dev_err(&pdev->dev, "no voltage specified for regulator %s\n",
+				vreg->desc.name);
 		return -EINVAL;
 	}
 
 	key = "bias-pull-down";
-	if (of_property_read_bool(pdev->dev.of_node, key)) {
+	if (of_property_read_bool(of_node, key)) {
 		ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
 		if (ret) {
-			dev_err(&pdev->dev, "%s is invalid", key);
+			dev_err(&pdev->dev, "%s is invalid (%s)", key,
+					vreg->desc.name);
 			return ret;
 		}
 	}
 
 	if (vreg->parts->freq.mask) {
-		ret = rpm_reg_of_parse_freq(&pdev->dev, vreg);
+		ret = rpm_reg_of_parse_freq(&pdev->dev, vreg, of_node);
 		if (ret < 0)
 			return ret;
 	}
 
 	if (vreg->parts->pm.mask) {
 		key = "qcom,power-mode-hysteretic";
-		pwm = !of_property_read_bool(pdev->dev.of_node, key);
+		pwm = !of_property_read_bool(of_node, key);
 
 		ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to set power mode\n");
+			dev_err(&pdev->dev, "failed to set power mode (%s)\n",
+					vreg->desc.name);
 			return ret;
 		}
 	}
@@ -736,11 +1044,12 @@ static int rpm_reg_probe(struct platform_device *pdev)
 		force_mode = -1;
 
 		key = "qcom,force-mode";
-		ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+		ret = of_property_read_u32(of_node, key, &val);
 		if (ret == -EINVAL) {
 			val = QCOM_RPM_FORCE_MODE_NONE;
 		} else if (ret < 0) {
-			dev_err(&pdev->dev, "failed to read %s\n", key);
+			dev_err(&pdev->dev, "failed to read %s (%s)\n", key,
+					vreg->desc.name);
 			return ret;
 		}
 
@@ -775,13 +1084,15 @@ static int rpm_reg_probe(struct platform_device *pdev)
 		}
 
 		if (force_mode == -1) {
-			dev_err(&pdev->dev, "invalid force mode\n");
+			dev_err(&pdev->dev, "invalid force mode (%s)\n",
+					vreg->desc.name);
 			return -EINVAL;
 		}
 
 		ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to set force mode\n");
+			dev_err(&pdev->dev, "failed to set force mode (%s)\n",
+					vreg->desc.name);
 			return ret;
 		}
 	}
@@ -789,11 +1100,48 @@ static int rpm_reg_probe(struct platform_device *pdev)
 	config.dev = &pdev->dev;
 	config.init_data = initdata;
 	config.driver_data = vreg;
-	config.of_node = pdev->dev.of_node;
+	config.of_node = of_node;
+
 	rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
-	if (IS_ERR(rdev)) {
-		dev_err(&pdev->dev, "can't register regulator\n");
-		return PTR_ERR(rdev);
+
+	return PTR_ERR_OR_ZERO(rdev);
+}
+
+static int rpm_reg_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	const struct qcom_rpm_of_match *rpm_match;
+	struct of_regulator_match *of_match;
+	struct qcom_rpm *rpm;
+	int ret;
+
+	rpm = dev_get_drvdata(pdev->dev.parent);
+	if (!rpm) {
+		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
+		return -ENODEV;
+	}
+
+	match = of_match_device(rpm_of_match, &pdev->dev);
+	rpm_match = match->data;
+	of_match = rpm_match->of_match;
+
+	ret = of_regulator_match(&pdev->dev, pdev->dev.of_node,
+				 of_match,
+				 rpm_match->size);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Error parsing regulator init data: %d\n", ret);
+		return ret;
+	}
+
+	for (; of_match < rpm_match->of_match + rpm_match->size; of_match++) {
+		if (!of_match->of_node)
+			continue;
+		ret = rpm_regulator_register(pdev, of_match, rpm);
+		if (ret) {
+			dev_err(&pdev->dev, "can't register regulator\n");
+			return ret;
+		}
 	}
 
 	return 0;
