summaryrefslogtreecommitdiffstats
path: root/src/device/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/device/device.c')
-rw-r--r--src/device/device.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/device/device.c b/src/device/device.c
index 383792874366..a2a64b2caeff 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -72,6 +72,26 @@ void dev_initialize_chips(void)
}
}
+/**
+ * Finalize all chips of statically known devices.
+ *
+ * This is the last call before calling the payload. This is a good place
+ * to lock registers or other final cleanup.
+ */
+void dev_finalize_chips(void)
+{
+ struct device *dev;
+
+ for (dev = all_devices; dev; dev = dev->next) {
+ /* Initialize chip if we haven't yet. */
+ if (dev->chip_ops && dev->chip_ops->final &&
+ !dev->chip_ops->finalized) {
+ dev->chip_ops->final(dev->chip_info);
+ dev->chip_ops->finalized = 1;
+ }
+ }
+}
+
DECLARE_SPIN_LOCK(dev_lock)
#if CONFIG_GFXUMA
@@ -1167,3 +1187,58 @@ void dev_initialize(void)
printk(BIOS_INFO, "Devices initialized\n");
show_all_devs(BIOS_SPEW, "After init.");
}
+
+/**
+ * Finalize a specific device.
+ *
+ * The parent should be finalized first to avoid having an ordering problem.
+ * This is done by calling the parent's final() method before its childrens'
+ * final() methods.
+ *
+ * @param dev The device to be initialized.
+ */
+static void final_dev(struct device *dev)
+{
+ if (!dev->enabled)
+ return;
+
+ if (dev->ops && dev->ops->final) {
+ printk(BIOS_DEBUG, "%s final\n", dev_path(dev));
+ dev->ops->final(dev);
+ }
+}
+
+static void final_link(struct bus *link)
+{
+ struct device *dev;
+ struct bus *c_link;
+
+ for (dev = link->children; dev; dev = dev->sibling)
+ final_dev(dev);
+
+ for (dev = link->children; dev; dev = dev->sibling) {
+ for (c_link = dev->link_list; c_link; c_link = c_link->next)
+ final_link(c_link);
+ }
+}
+/**
+ * Finalize all devices in the global device tree.
+ *
+ * Starting at the root device, call the device's final() method to do
+ * device-specific cleanup, then call each child's final() method.
+ */
+void dev_finalize(void)
+{
+ struct bus *link;
+
+ printk(BIOS_INFO, "Finalize devices...\n");
+
+ /* First call the mainboard finalize. */
+ final_dev(&dev_root);
+
+ /* Now finalize everything. */
+ for (link = dev_root.link_list; link; link = link->next)
+ final_link(link);
+
+ printk(BIOS_INFO, "Devices finalized\n");
+}