bbade24241
chip_instance structure currently uses a ref_count to determine how many devices hold reference to that instance. If the count drops to zero, then it is assumed that the chip instance is a duplicate in override tree and has a similar instance that is already overriden in base device tree. ref_count is currently decremented whenever a device in override tree matches the one in base device tree and the registers from the override tree instance are copied over to the base tree instance. On the other hand, if a device in override tree does not match any device in base tree under a given parent, then the device is added to base tree and all the devices in its subtree that hold pointers to its parent chip instance are updated to point to the parent's chip instance in base tree. This is done as part of update_chip_pointers. However, there are a couple of issues that this suffers from: a) If a device is present only in override tree and it does not have its own chip (i.e. pointing to parent's chip instance), then it results in sconfig emiiting parent's chip instance (which can be the SoC chip instance) in static.c even though it is unused. This is because update_chip_pointers() does not call delete_chip_instance() before reassigning the chip instance pointer. b) If a device is added under root device only in the override tree and it does not have its own chip instance (i.e. uses SoC chip instance), then it results in sconfig emitting a copy of the SoC chip instance and setting that as chip_ops for this new device in the override tree. In order to fix the above issues, this change drops the ref_count field from chip_instance structure and instead adds a forwarding pointer `base_chip_instance`. This is setup as per the following rules: 1. If the instance belongs to base devicetree, base_chip_instance is set to NULL. 2. If the instance belongs to override tree, then it is set to its corresponding chip instance in base tree (if present), else set to NULL. State of base_chip_instance is then used when emitting chips and devices using the following rules: 1. If a chip_instance has non-NULL base_chip_instance, then that chip instance is not emitted to static.c 2. When emitting chip_ops for a device, base_chip_instance is used to determine the correct chip instance name to emit. BUG=b:155549176 TEST=Verified that the static.c file generated for base/override tree combination is correct when new devices without chips are added only to override tree. Change-Id: Idbb5b34f49bf874da3f30ebb6a6a0e2d8d091fe5 Signed-off-by: Furquan Shaikh <furquan@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41007 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
186 lines
4.5 KiB
C
186 lines
4.5 KiB
C
/*
|
|
* sconfig, coreboot device tree compiler
|
|
*
|
|
* Copyright (C) 2010 coresystems GmbH
|
|
* written by Patrick Georgi <patrick@georgi-clan.de>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
struct resource;
|
|
struct resource {
|
|
int type;
|
|
int index;
|
|
int base;
|
|
struct resource *next;
|
|
};
|
|
|
|
struct reg;
|
|
struct reg {
|
|
char *key;
|
|
char *value;
|
|
struct reg *next;
|
|
};
|
|
|
|
struct pci_irq_info {
|
|
int ioapic_irq_pin;
|
|
int ioapic_dst_id;
|
|
};
|
|
|
|
struct chip;
|
|
struct chip_instance {
|
|
/* Monotonically increasing ID for each chip instance. */
|
|
int id;
|
|
|
|
/* Pointer to registers for this chip. */
|
|
struct reg *reg;
|
|
|
|
/* Pointer to chip of which this is instance. */
|
|
struct chip *chip;
|
|
|
|
/* Pointer to next instance of the same chip. */
|
|
struct chip_instance *next;
|
|
|
|
/*
|
|
* Pointer to corresponding chip instance in base devicetree.
|
|
* a) If the chip instance belongs to the base devicetree, then this pointer is set to
|
|
* NULL.
|
|
* b) If the chip instance belongs to override tree, then this pointer is set to its
|
|
* corresponding chip instance in base devicetree (if it exists), else to NULL.
|
|
*
|
|
* This is useful when generating chip instances and chip_ops for a device to determine
|
|
* if this is the instance to emit or if there is a base chip instance to use instead.
|
|
*/
|
|
struct chip_instance *base_chip_instance;
|
|
};
|
|
|
|
struct chip {
|
|
/* Indicates if chip header exists for this chip. */
|
|
int chiph_exists;
|
|
|
|
/* Name of current chip. */
|
|
char *name;
|
|
|
|
/* Name of current chip normalized to _. */
|
|
char *name_underscore;
|
|
|
|
/* Pointer to first instance of this chip. */
|
|
struct chip_instance *instance;
|
|
|
|
/* Pointer to next chip. */
|
|
struct chip *next;
|
|
};
|
|
|
|
struct device;
|
|
struct bus {
|
|
/* Instance/ID of the bus under the device. */
|
|
int id;
|
|
|
|
/* Pointer to device to which this bus belongs. */
|
|
struct device *dev;
|
|
|
|
/* Pointer to list of children. */
|
|
struct device *children;
|
|
|
|
/* Pointer to next bus for the device. */
|
|
struct bus *next_bus;
|
|
};
|
|
|
|
struct device {
|
|
/* Indicates device status (enabled / hidden or not). */
|
|
int enabled;
|
|
int hidden;
|
|
/* non-zero if the device should be included in all cases */
|
|
int mandatory;
|
|
|
|
/* Subsystem IDs for the device. */
|
|
int subsystem_vendor;
|
|
int subsystem_device;
|
|
int inherit_subsystem;
|
|
|
|
/* Name of this device. */
|
|
char *name;
|
|
|
|
/* Path of this device. */
|
|
char *path;
|
|
int path_a;
|
|
int path_b;
|
|
|
|
/* Type of bus that exists under this device. */
|
|
int bustype;
|
|
|
|
/* PCI IRQ info. */
|
|
struct pci_irq_info pci_irq_info[4];
|
|
|
|
/* Pointer to bus of parent on which this device resides. */
|
|
struct bus *parent;
|
|
|
|
/* Pointer to next child under the same parent. */
|
|
struct device *sibling;
|
|
|
|
/* Pointer to resources for this device. */
|
|
struct resource *res;
|
|
|
|
/* Pointer to chip instance for this device. */
|
|
struct chip_instance *chip_instance;
|
|
|
|
/* Pointer to list of buses under this device. */
|
|
struct bus *bus;
|
|
/* Pointer to last bus under this device. */
|
|
struct bus *last_bus;
|
|
|
|
/* SMBIOS slot type */
|
|
char *smbios_slot_type;
|
|
|
|
/* SMBIOS slot data width */
|
|
char *smbios_slot_data_width;
|
|
|
|
/* SMBIOS slot description for reference designation */
|
|
char *smbios_slot_designation;
|
|
|
|
/* SMBIOS slot length */
|
|
char *smbios_slot_length;
|
|
};
|
|
|
|
extern struct bus *root_parent;
|
|
|
|
struct device *new_device(struct bus *parent,
|
|
struct chip_instance *chip_instance,
|
|
const int bustype, const char *devnum,
|
|
int status);
|
|
|
|
void add_resource(struct bus *bus, int type, int index, int base);
|
|
|
|
void add_pci_subsystem_ids(struct bus *bus, int vendor, int device,
|
|
int inherit);
|
|
|
|
void add_ioapic_info(struct bus *bus, int apicid, const char *_srcpin,
|
|
int irqpin);
|
|
|
|
void add_slot_desc(struct bus *bus, char *type, char *length, char *designation,
|
|
char *data_width);
|
|
|
|
void yyrestart(FILE *input_file);
|
|
|
|
/* Add chip data to tail of queue. */
|
|
void chip_enqueue_tail(void *data);
|
|
|
|
/* Retrieve chip data from tail of queue. */
|
|
void *chip_dequeue_tail(void);
|
|
|
|
struct chip_instance *new_chip_instance(char *path);
|
|
void add_register(struct chip_instance *chip, char *name, char *val);
|