+#if defined CONFIG_OF && defined CONFIG_REGULATOR
+
+#define SUPPLY_SUFFIX "-supply"
+
+/*
+ * Regulator handling code.
+ *
+ * Here we handle the num-supplies and vin*-supply properties of our
+ * "simple-framebuffer" dt node. This is necessary so that we can make sure
+ * that any regulators needed by the display hardware that the bootloader
+ * set up for us (and for which it provided a simplefb dt node), stay up,
+ * for the life of the simplefb driver.
+ *
+ * When the driver unloads, we cleanly disable, and then release the
+ * regulators.
+ *
+ * We only complain about errors here, no action is taken as the most likely
+ * error can only happen due to a mismatch between the bootloader which set
+ * up simplefb, and the regulator definitions in the device tree. Chances are
+ * that there are no adverse effects, and if there are, a clean teardown of
+ * the fb probe will not help us much either. So just complain and carry on,
+ * and hope that the user actually gets a working fb at the end of things.
+ */
+static int simplefb_regulators_init(struct simplefb_par *par,
+ struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct property *prop;
+ struct regulator *regulator;
+ const char *p;
+ int count = 0, i = 0, ret;
+
+ if (dev_get_platdata(&pdev->dev) || !np)
+ return 0;
+
+ /* Count the number of regulator supplies */
+ for_each_property_of_node(np, prop) {
+ p = strstr(prop->name, SUPPLY_SUFFIX);
+ if (p && p != prop->name)
+ count++;
+ }
+
+ if (!count)
+ return 0;
+
+ par->regulators = devm_kcalloc(&pdev->dev, count,
+ sizeof(struct regulator *), GFP_KERNEL);
+ if (!par->regulators)
+ return -ENOMEM;
+
+ /* Get all the regulators */
+ for_each_property_of_node(np, prop) {
+ char name[32]; /* 32 is max size of property name */
+
+ p = strstr(prop->name, SUPPLY_SUFFIX);
+ if (!p || p == prop->name)
+ continue;
+
+ strlcpy(name, prop->name,
+ strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1);
+ regulator = devm_regulator_get_optional(&pdev->dev, name);
+ if (IS_ERR(regulator)) {
+ if (PTR_ERR(regulator) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "regulator %s not found: %ld\n",
+ name, PTR_ERR(regulator));
+ continue;
+ }
+ par->regulators[i++] = regulator;
+ }
+ par->regulator_count = i;
+
+ /* Enable all the regulators */
+ for (i = 0; i < par->regulator_count; i++) {
+ ret = regulator_enable(par->regulators[i]);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to enable regulator %d: %d\n",
+ i, ret);
+ devm_regulator_put(par->regulators[i]);
+ par->regulators[i] = NULL;
+ }
+ }
+
+ return 0;
+}
+
+static void simplefb_regulators_destroy(struct simplefb_par *par)
+{
+ int i;
+
+ if (!par->regulators)
+ return;
+
+ for (i = 0; i < par->regulator_count; i++)
+ if (par->regulators[i])
+ regulator_disable(par->regulators[i]);
+}
+#else
+static int simplefb_regulators_init(struct simplefb_par *par,
+ struct platform_device *pdev) { return 0; }
+static void simplefb_regulators_destroy(struct simplefb_par *par) { }
+#endif
+