[coreboot-gerrit] Patch set updated for coreboot: bca72ea Add new finalize functions for devices and chips

Paul Menzel (paulepanter@users.sourceforge.net) gerrit at coreboot.org
Fri Nov 1 23:49:45 CET 2013


Paul Menzel (paulepanter at users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4012

-gerrit

commit bca72ea7949633361e4f32ad6b47e1a82d9c97c2
Author: Marc Jones <marc.jones at se-eng.com>
Date:   Tue Oct 29 17:32:00 2013 -0600

    Add new finalize functions for devices and chips
    
    Many chipset devices require additional configuration after
    device init. It is not uncommmon for a device early in the devicetree
    list to need to change a setting after a device later in the tree does
    PCI init. A final function call has been added to device ops to handle
    this case. It is called prior to coreboot table setup.
    
    Another problem that is often seen is that the chipset or mainboard
    need to do some final cleanup just before loading the OS. The chip
    finalize has been added for this case. It is call after all coreboot
    tables are setup and the payload is ready to be called.
    
    Similar functionality could be implemented with the hardwaremain
    states, but those don't fit well in the device tree function pointer
    structure and should be used sparingly.
    
    Change-Id: Ib37cce104ae41ec225a8502942d85e54d99ea75f
    Signed-off-by: Marc Jones <marc.jones at se-eng.com>
---
 src/device/device.c         | 76 +++++++++++++++++++++++++++++++++++++++++++++
 src/include/device/device.h |  5 +++
 src/lib/hardwaremain.c      |  3 ++
 3 files changed, 84 insertions(+)

diff --git a/src/device/device.c b/src/device/device.c
index 3837928..91cb4fa 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,59 @@ 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");
+	show_all_devs(BIOS_SPEW, "After finalize.");
+}
diff --git a/src/include/device/device.h b/src/include/device/device.h
index c0e6e0f..fec0497 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -22,7 +22,9 @@ struct pnp_mode_ops;
 struct chip_operations {
 	void (*enable_dev)(struct device *dev);
 	void (*init)(void *chip_info);
+	void (*final)(void *chip_info);
 	unsigned int initialized : 1;
+	unsigned int finalized : 1;
 	const char *name;
 };
 
@@ -35,6 +37,7 @@ struct device_operations {
 	void (*set_resources)(device_t dev);
 	void (*enable_resources)(device_t dev);
 	void (*init)(device_t dev);
+	void (*final)(device_t dev);
 	unsigned int (*scan_bus)(device_t bus, unsigned int max);
 	void (*enable)(device_t dev);
 	void (*disable)(device_t dev);
@@ -140,6 +143,8 @@ void dev_configure(void);
 void dev_enable(void);
 void dev_initialize(void);
 void dev_optimize(void);
+void dev_finalize(void);
+void dev_finalize_chips(void);
 
 /* Generic device helper functions */
 int reset_bus(struct bus *bus);
diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c
index a5993c4..501591f 100644
--- a/src/lib/hardwaremain.c
+++ b/src/lib/hardwaremain.c
@@ -175,6 +175,7 @@ static boot_state_t bs_dev_init(void *arg)
 
 static boot_state_t bs_post_device(void *arg)
 {
+	dev_finalize();
 	timestamp_add_now(TS_DEVICE_DONE);
 
 	timestamp_reinit();
@@ -217,6 +218,8 @@ static boot_state_t bs_write_tables(void *arg)
 	 */
 	write_tables();
 
+	dev_finalize_chips();
+
 	return BS_PAYLOAD_LOAD;
 }
 



More information about the coreboot-gerrit mailing list