mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-25 12:40:08 +00:00
hw/arm/sysbus-fdt: helpers for clock node generation
Some passthrough'ed devices depend on clock nodes. Those need to be generated in the guest device tree. This patch introduces some helpers to build a clock node from information retrieved in the host device tree. - copy_properties_from_host copies properties from a host device tree node to a guest device tree node - fdt_build_clock_node builds a guest clock node and checks the host fellow clock is a fixed one. fdt_build_clock_node will become static as soon as it gets used. A dummy pre-declaration is needed for compilation of this patch. Signed-off-by: Eric Auger <eric.auger@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
58e71097ce
commit
9481cf2e5f
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <libfdt.h>
|
||||
#include "hw/arm/sysbus-fdt.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
@ -57,6 +58,125 @@ typedef struct NodeCreationPair {
|
||||
int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
|
||||
} NodeCreationPair;
|
||||
|
||||
/* helpers */
|
||||
|
||||
typedef struct HostProperty {
|
||||
const char *name;
|
||||
bool optional;
|
||||
} HostProperty;
|
||||
|
||||
/**
|
||||
* copy_properties_from_host
|
||||
*
|
||||
* copies properties listed in an array from host device tree to
|
||||
* guest device tree. If a non optional property is not found, the
|
||||
* function asserts. An optional property is ignored if not found
|
||||
* in the host device tree.
|
||||
* @props: array of HostProperty to copy
|
||||
* @nb_props: number of properties in the array
|
||||
* @host_dt: host device tree blob
|
||||
* @guest_dt: guest device tree blob
|
||||
* @node_path: host dt node path where the property is supposed to be
|
||||
found
|
||||
* @nodename: guest node name the properties should be added to
|
||||
*/
|
||||
static void copy_properties_from_host(HostProperty *props, int nb_props,
|
||||
void *host_fdt, void *guest_fdt,
|
||||
char *node_path, char *nodename)
|
||||
{
|
||||
int i, prop_len;
|
||||
const void *r;
|
||||
Error *err = NULL;
|
||||
|
||||
for (i = 0; i < nb_props; i++) {
|
||||
r = qemu_fdt_getprop(host_fdt, node_path,
|
||||
props[i].name,
|
||||
&prop_len,
|
||||
props[i].optional ? &err : &error_fatal);
|
||||
if (r) {
|
||||
qemu_fdt_setprop(guest_fdt, nodename,
|
||||
props[i].name, r, prop_len);
|
||||
} else {
|
||||
if (prop_len != -FDT_ERR_NOTFOUND) {
|
||||
/* optional property not returned although property exists */
|
||||
error_report_err(err);
|
||||
} else {
|
||||
error_free(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* clock properties whose values are copied/pasted from host */
|
||||
static HostProperty clock_copied_properties[] = {
|
||||
{"compatible", false},
|
||||
{"#clock-cells", false},
|
||||
{"clock-frequency", true},
|
||||
{"clock-output-names", true},
|
||||
};
|
||||
|
||||
/**
|
||||
* fdt_build_clock_node
|
||||
*
|
||||
* Build a guest clock node, used as a dependency from a passthrough'ed
|
||||
* device. Most information are retrieved from the host clock node.
|
||||
* Also check the host clock is a fixed one.
|
||||
*
|
||||
* @host_fdt: host device tree blob from which info are retrieved
|
||||
* @guest_fdt: guest device tree blob where the clock node is added
|
||||
* @host_phandle: phandle of the clock in host device tree
|
||||
* @guest_phandle: phandle to assign to the guest node
|
||||
*/
|
||||
void fdt_build_clock_node(void *host_fdt, void *guest_fdt,
|
||||
uint32_t host_phandle,
|
||||
uint32_t guest_phandle);
|
||||
void fdt_build_clock_node(void *host_fdt, void *guest_fdt,
|
||||
uint32_t host_phandle,
|
||||
uint32_t guest_phandle)
|
||||
{
|
||||
char *node_path = NULL;
|
||||
char *nodename;
|
||||
const void *r;
|
||||
int ret, node_offset, prop_len, path_len = 16;
|
||||
|
||||
node_offset = fdt_node_offset_by_phandle(host_fdt, host_phandle);
|
||||
if (node_offset <= 0) {
|
||||
error_setg(&error_fatal,
|
||||
"not able to locate clock handle %d in host device tree",
|
||||
host_phandle);
|
||||
}
|
||||
node_path = g_malloc(path_len);
|
||||
while ((ret = fdt_get_path(host_fdt, node_offset, node_path, path_len))
|
||||
== -FDT_ERR_NOSPACE) {
|
||||
path_len += 16;
|
||||
node_path = g_realloc(node_path, path_len);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(&error_fatal,
|
||||
"not able to retrieve node path for clock handle %d",
|
||||
host_phandle);
|
||||
}
|
||||
|
||||
r = qemu_fdt_getprop(host_fdt, node_path, "compatible", &prop_len,
|
||||
&error_fatal);
|
||||
if (strcmp(r, "fixed-clock")) {
|
||||
error_setg(&error_fatal,
|
||||
"clock handle %d is not a fixed clock", host_phandle);
|
||||
}
|
||||
|
||||
nodename = strrchr(node_path, '/');
|
||||
qemu_fdt_add_subnode(guest_fdt, nodename);
|
||||
|
||||
copy_properties_from_host(clock_copied_properties,
|
||||
ARRAY_SIZE(clock_copied_properties),
|
||||
host_fdt, guest_fdt,
|
||||
node_path, nodename);
|
||||
|
||||
qemu_fdt_setprop_cell(guest_fdt, nodename, "phandle", guest_phandle);
|
||||
|
||||
g_free(node_path);
|
||||
}
|
||||
|
||||
/* Device Specific Code */
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user