#define pr_fmt(fmt) "PM: " fmt
 
 #include <linux/delay.h>
+#include <linux/idr.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
 #include <linux/debugfs.h>
 
+/* Provides a unique ID for each genpd device */
+static DEFINE_IDA(genpd_ida);
+
 #define GENPD_RETRY_MAX_MS     250             /* Approximate */
 
 #define GENPD_DEV_CALLBACK(genpd, type, callback, dev)         \
 #define genpd_is_cpu_domain(genpd)     (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
 #define genpd_is_rpm_always_on(genpd)  (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
 #define genpd_is_opp_table_fw(genpd)   (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
+#define genpd_is_dev_name_fw(genpd)    (genpd->flags & GENPD_FLAG_DEV_NAME_FW)
 
 static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
                const struct generic_pm_domain *genpd)
 
        if (ret)
                dev_warn_once(dev, "PM domain %s will not be powered off\n",
-                               genpd->name);
+                             dev_name(&genpd->dev));
 
        return ret;
 }
        if (!genpd_debugfs_dir)
                return;
 
-       debugfs_lookup_and_remove(genpd->name, genpd_debugfs_dir);
+       debugfs_lookup_and_remove(dev_name(&genpd->dev), genpd_debugfs_dir);
 }
 
 static void genpd_update_accounting(struct generic_pm_domain *genpd)
        genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
        genpd->gd->max_off_time_changed = true;
        pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
-                genpd->name, "on", elapsed_ns);
+                dev_name(&genpd->dev), "on", elapsed_ns);
 
 out:
        raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
        genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
        genpd->gd->max_off_time_changed = true;
        pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
-                genpd->name, "off", elapsed_ns);
+                dev_name(&genpd->dev), "off", elapsed_ns);
 
 out:
        raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
 
        if (ret) {
                dev_warn(dev, "failed to add notifier for PM domain %s\n",
-                        genpd->name);
+                        dev_name(&genpd->dev));
                return ret;
        }
 
 
        if (ret) {
                dev_warn(dev, "failed to remove notifier for PM domain %s\n",
-                        genpd->name);
+                        dev_name(&genpd->dev));
                return ret;
        }
 
         */
        if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) {
                WARN(1, "Parent %s of subdomain %s must be IRQ safe\n",
-                               genpd->name, subdomain->name);
+                    dev_name(&genpd->dev), subdomain->name);
                return -EINVAL;
        }
 
 
        if (!list_empty(&subdomain->parent_links) || subdomain->device_count) {
                pr_warn("%s: unable to remove subdomain %s\n",
-                       genpd->name, subdomain->name);
+                       dev_name(&genpd->dev), subdomain->name);
                ret = -EBUSY;
                goto out;
        }
        genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON;
        genpd->device_count = 0;
        genpd->provider = NULL;
+       genpd->device_id = -ENXIO;
        genpd->has_provider = false;
        genpd->accounting_time = ktime_get_mono_fast_ns();
        genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
                return ret;
 
        device_initialize(&genpd->dev);
-       dev_set_name(&genpd->dev, "%s", genpd->name);
+
+       if (!genpd_is_dev_name_fw(genpd)) {
+               dev_set_name(&genpd->dev, "%s", genpd->name);
+       } else {
+               ret = ida_alloc(&genpd_ida, GFP_KERNEL);
+               if (ret < 0) {
+                       put_device(&genpd->dev);
+                       return ret;
+               }
+               genpd->device_id = ret;
+               dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id);
+       }
 
        mutex_lock(&gpd_list_lock);
        list_add(&genpd->gpd_list_node, &gpd_list);
 
        if (genpd->has_provider) {
                genpd_unlock(genpd);
-               pr_err("Provider present, unable to remove %s\n", genpd->name);
+               pr_err("Provider present, unable to remove %s\n", dev_name(&genpd->dev));
                return -EBUSY;
        }
 
        if (!list_empty(&genpd->parent_links) || genpd->device_count) {
                genpd_unlock(genpd);
-               pr_err("%s: unable to remove %s\n", __func__, genpd->name);
+               pr_err("%s: unable to remove %s\n", __func__, dev_name(&genpd->dev));
                return -EBUSY;
        }
 
        genpd_unlock(genpd);
        genpd_debug_remove(genpd);
        cancel_work_sync(&genpd->power_off_work);
+       if (genpd->device_id != -ENXIO)
+               ida_free(&genpd_ida, genpd->device_id);
        genpd_free_data(genpd);
 
-       pr_debug("%s: removed %s\n", __func__, genpd->name);
+       pr_debug("%s: removed %s\n", __func__, dev_name(&genpd->dev));
 
        return 0;
 }
        else
                snprintf(state, sizeof(state), "%s",
                         status_lookup[genpd->status]);
-       seq_printf(s, "%-30s  %-30s  %u", genpd->name, state, genpd->performance_state);
+       seq_printf(s, "%-30s  %-30s  %u", dev_name(&genpd->dev), state, genpd->performance_state);
 
        /*
         * Modifications on the list require holding locks on both
         * parent and child, so we are safe.
-        * Also genpd->name is immutable.
+        * Also the device name is immutable.
         */
        list_for_each_entry(link, &genpd->parent_links, parent_node) {
                if (list_is_first(&link->parent_node, &genpd->parent_links))
        if (!genpd_debugfs_dir)
                return;
 
-       d = debugfs_create_dir(genpd->name, genpd_debugfs_dir);
+       d = debugfs_create_dir(dev_name(&genpd->dev), genpd_debugfs_dir);
 
        debugfs_create_file("current_state", 0444,
                            d, genpd, &status_fops);