Broadwell FSP: Add new finalize functions for devices and chips
Merge change from coreboot.org: Add new finalize functions for devices
and chips
BUG=None
TEST=Requires FSP for testing
commit 2a58ecde78
Author: Marc Jones <marc.jones@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
Reviewed-on: http://review.coreboot.org/4012
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Change-Id: I4f918a5908f2016f6e57f954284f9f8856bd8301
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/213694
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/229572
Reviewed-by: Erik C Bjorge <erik.c.bjorge@intel.com>
This commit is contained in:
parent
9cf5bc2844
commit
d6b5fb06a5
3 changed files with 83 additions and 0 deletions
|
|
@ -74,6 +74,26 @@ void dev_initialize_chips(void)
|
|||
post_log_clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
@ -1182,3 +1202,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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ struct smbus_bus_operations;
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
@ -31,6 +33,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);
|
||||
|
|
@ -134,6 +137,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);
|
||||
|
|
|
|||
|
|
@ -178,6 +178,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);
|
||||
|
||||
return BS_OS_RESUME_CHECK;
|
||||
|
|
@ -217,6 +218,8 @@ static boot_state_t bs_write_tables(void *arg)
|
|||
*/
|
||||
write_tables();
|
||||
|
||||
dev_finalize_chips();
|
||||
|
||||
return BS_PAYLOAD_LOAD;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue