mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
target-arm queue:
* xlnx-zdma: Fix endianness handling of descriptor loading * nrf51: Fix last GPIO CNF address * gicv3: Use gicr_typer in arm_gicv3_icc_reset * msf2: Add EMAC block to SmartFusion2 SoC * New clock modelling framework * hw/arm: versal: Setup the ADMA with 128bit bus-width * Cadence: gem: fix wraparound in 64bit descriptors * cadence_gem: clear RX control descriptor * target/arm: Vectorize integer comparison vs zero * hw/arm/virt: dt: add kaslr-seed property * hw/arm: xlnx-zcu102: Disable unsupported FDT firmware nodes -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl6q5CoZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3pWPD/9zjcV3TlOUWg/2aRQOYWB1 I/h2AGTI09Y/nGMmwvHEyQKyAg6mL8KfJwCUDHr1pE3DeTt4Z7dA+3rhk1uy+gKA Ot/7e4IVSMiNh28xkBiSPviBXjYtgmVjvSlgKn4fty6g+30wdGV8ymNz1wXO8II0 5cuGlaz0VQ4N+W4qz9kuaJNEAsMSnmrJ9fUzZDllRsNy4li3aSR4sQ9CymsJ23+3 9CdStk/ibA7tExDX5qkj4lKozENEAU/jethA91CQCMLnK/7aGfHbLqVyWu6xDuQ7 oTdyXr7nrGIUjod+Cx7mLyUQKXVfsiw0x4kmjvOnaVZHh5oIgDj83vWXQ28nC6P4 wVYCRWpg68GPuaEru8VeocdoATMa1ONjrv5/gFGOxlma4AjD07WQ53hTp2pL0HT2 +uYPwm2iSYgYKX7QV/rbNzWHK1nYq6/3LDeVQc6nr/3jVewpZngnf2pMxChRUUoT qtdLwJL/om9hqV4lsU7cxHKSNnkocfDhjkwRy6wg0L/iXDftt1sKbZO+G78vvsow S+NqjpAo4m+P7ExS8DGiSsgvQIQIHvcjjpeym4fWmBxPaXep6oUIewzBuExcYWK8 XogFZEnW6PNyr/CKLh7GYH9C0F6FI36+yPUZFxvdBpz4w5QBADYKyyG0/53P0uKa ez3ixFfplzcx8RIiy+nIsQ== =9plU -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200430-1' into staging target-arm queue: * xlnx-zdma: Fix endianness handling of descriptor loading * nrf51: Fix last GPIO CNF address * gicv3: Use gicr_typer in arm_gicv3_icc_reset * msf2: Add EMAC block to SmartFusion2 SoC * New clock modelling framework * hw/arm: versal: Setup the ADMA with 128bit bus-width * Cadence: gem: fix wraparound in 64bit descriptors * cadence_gem: clear RX control descriptor * target/arm: Vectorize integer comparison vs zero * hw/arm/virt: dt: add kaslr-seed property * hw/arm: xlnx-zcu102: Disable unsupported FDT firmware nodes # gpg: Signature made Thu 30 Apr 2020 15:43:54 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20200430-1: (30 commits) hw/arm: xlnx-zcu102: Disable unsupported FDT firmware nodes hw/arm: xlnx-zcu102: Move arm_boot_info into XlnxZCU102 device_tree: Constify compat in qemu_fdt_node_path() device_tree: Allow name wildcards in qemu_fdt_node_path() target/arm/cpu: Update coding style to make checkpatch.pl happy target/arm: Make cpu_register() available for other files target/arm: Restrict the Address Translate write operation to TCG accel hw/arm/virt: dt: add kaslr-seed property hw/arm/virt: dt: move creation of /secure-chosen to create_fdt() target/arm: Vectorize integer comparison vs zero net: cadence_gem: clear RX control descriptor Cadence: gem: fix wraparound in 64bit descriptors hw/arm: versal: Setup the ADMA with 128bit bus-width qdev-monitor: print the device's clock with info qtree hw/arm/xilinx_zynq: connect uart clocks to slcr hw/char/cadence_uart: add clock support hw/misc/zynq_slcr: add clock generation for uarts docs/clocks: add device's clock documentation qdev-clock: introduce an init array to ease the device construction qdev: add clock input&output support to devices. ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
126eeee6c7
45 changed files with 2533 additions and 193 deletions
|
@ -7,6 +7,7 @@ common-obj-y += hotplug.o
|
|||
common-obj-y += vmstate-if.o
|
||||
# irq.o needed for qdev GPIO handling:
|
||||
common-obj-y += irq.o
|
||||
common-obj-y += clock.o qdev-clock.o
|
||||
|
||||
common-obj-$(CONFIG_SOFTMMU) += reset.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
|
||||
|
@ -20,6 +21,7 @@ common-obj-$(CONFIG_SOFTMMU) += null-machine.o
|
|||
common-obj-$(CONFIG_SOFTMMU) += loader.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += machine-hmp-cmds.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += numa.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += clock-vmstate.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o
|
||||
|
||||
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
|
||||
|
|
25
hw/core/clock-vmstate.c
Normal file
25
hw/core/clock-vmstate.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Clock migration structure
|
||||
*
|
||||
* Copyright GreenSocs 2019-2020
|
||||
*
|
||||
* Authors:
|
||||
* Damien Hedde
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/clock.h"
|
||||
|
||||
const VMStateDescription vmstate_clock = {
|
||||
.name = "clock",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(period, Clock),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
130
hw/core/clock.c
Normal file
130
hw/core/clock.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Hardware Clocks
|
||||
*
|
||||
* Copyright GreenSocs 2016-2020
|
||||
*
|
||||
* Authors:
|
||||
* Frederic Konrad
|
||||
* Damien Hedde
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/clock.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define CLOCK_PATH(_clk) (_clk->canonical_path)
|
||||
|
||||
void clock_setup_canonical_path(Clock *clk)
|
||||
{
|
||||
g_free(clk->canonical_path);
|
||||
clk->canonical_path = object_get_canonical_path(OBJECT(clk));
|
||||
}
|
||||
|
||||
void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque)
|
||||
{
|
||||
clk->callback = cb;
|
||||
clk->callback_opaque = opaque;
|
||||
}
|
||||
|
||||
void clock_clear_callback(Clock *clk)
|
||||
{
|
||||
clock_set_callback(clk, NULL, NULL);
|
||||
}
|
||||
|
||||
void clock_set(Clock *clk, uint64_t period)
|
||||
{
|
||||
trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_NS(clk->period),
|
||||
CLOCK_PERIOD_TO_NS(period));
|
||||
clk->period = period;
|
||||
}
|
||||
|
||||
static void clock_propagate_period(Clock *clk, bool call_callbacks)
|
||||
{
|
||||
Clock *child;
|
||||
|
||||
QLIST_FOREACH(child, &clk->children, sibling) {
|
||||
if (child->period != clk->period) {
|
||||
child->period = clk->period;
|
||||
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
|
||||
CLOCK_PERIOD_TO_NS(clk->period),
|
||||
call_callbacks);
|
||||
if (call_callbacks && child->callback) {
|
||||
child->callback(child->callback_opaque);
|
||||
}
|
||||
clock_propagate_period(child, call_callbacks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clock_propagate(Clock *clk)
|
||||
{
|
||||
assert(clk->source == NULL);
|
||||
trace_clock_propagate(CLOCK_PATH(clk));
|
||||
clock_propagate_period(clk, true);
|
||||
}
|
||||
|
||||
void clock_set_source(Clock *clk, Clock *src)
|
||||
{
|
||||
/* changing clock source is not supported */
|
||||
assert(!clk->source);
|
||||
|
||||
trace_clock_set_source(CLOCK_PATH(clk), CLOCK_PATH(src));
|
||||
|
||||
clk->period = src->period;
|
||||
QLIST_INSERT_HEAD(&src->children, clk, sibling);
|
||||
clk->source = src;
|
||||
clock_propagate_period(clk, false);
|
||||
}
|
||||
|
||||
static void clock_disconnect(Clock *clk)
|
||||
{
|
||||
if (clk->source == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_clock_disconnect(CLOCK_PATH(clk));
|
||||
|
||||
clk->source = NULL;
|
||||
QLIST_REMOVE(clk, sibling);
|
||||
}
|
||||
|
||||
static void clock_initfn(Object *obj)
|
||||
{
|
||||
Clock *clk = CLOCK(obj);
|
||||
|
||||
QLIST_INIT(&clk->children);
|
||||
}
|
||||
|
||||
static void clock_finalizefn(Object *obj)
|
||||
{
|
||||
Clock *clk = CLOCK(obj);
|
||||
Clock *child, *next;
|
||||
|
||||
/* clear our list of children */
|
||||
QLIST_FOREACH_SAFE(child, &clk->children, sibling, next) {
|
||||
clock_disconnect(child);
|
||||
}
|
||||
|
||||
/* remove us from source's children list */
|
||||
clock_disconnect(clk);
|
||||
|
||||
g_free(clk->canonical_path);
|
||||
}
|
||||
|
||||
static const TypeInfo clock_info = {
|
||||
.name = TYPE_CLOCK,
|
||||
.parent = TYPE_OBJECT,
|
||||
.instance_size = sizeof(Clock),
|
||||
.instance_init = clock_initfn,
|
||||
.instance_finalize = clock_finalizefn,
|
||||
};
|
||||
|
||||
static void clock_register_types(void)
|
||||
{
|
||||
type_register_static(&clock_info);
|
||||
}
|
||||
|
||||
type_init(clock_register_types)
|
185
hw/core/qdev-clock.c
Normal file
185
hw/core/qdev-clock.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Device's clock input and output
|
||||
*
|
||||
* Copyright GreenSocs 2016-2020
|
||||
*
|
||||
* Authors:
|
||||
* Frederic Konrad
|
||||
* Damien Hedde
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
/*
|
||||
* qdev_init_clocklist:
|
||||
* Add a new clock in a device
|
||||
*/
|
||||
static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name,
|
||||
bool output, Clock *clk)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
/*
|
||||
* Clock must be added before realize() so that we can compute the
|
||||
* clock's canonical path during device_realize().
|
||||
*/
|
||||
assert(!dev->realized);
|
||||
|
||||
/*
|
||||
* The ncl structure is freed by qdev_finalize_clocklist() which will
|
||||
* be called during @dev's device_finalize().
|
||||
*/
|
||||
ncl = g_new0(NamedClockList, 1);
|
||||
ncl->name = g_strdup(name);
|
||||
ncl->output = output;
|
||||
ncl->alias = (clk != NULL);
|
||||
|
||||
/*
|
||||
* Trying to create a clock whose name clashes with some other
|
||||
* clock or property is a bug in the caller and we will abort().
|
||||
*/
|
||||
if (clk == NULL) {
|
||||
clk = CLOCK(object_new(TYPE_CLOCK));
|
||||
object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort);
|
||||
if (output) {
|
||||
/*
|
||||
* Remove object_new()'s initial reference.
|
||||
* Note that for inputs, the reference created by object_new()
|
||||
* will be deleted in qdev_finalize_clocklist().
|
||||
*/
|
||||
object_unref(OBJECT(clk));
|
||||
}
|
||||
} else {
|
||||
object_property_add_link(OBJECT(dev), name,
|
||||
object_get_typename(OBJECT(clk)),
|
||||
(Object **) &ncl->clock,
|
||||
NULL, OBJ_PROP_LINK_STRONG, &error_abort);
|
||||
}
|
||||
|
||||
ncl->clock = clk;
|
||||
|
||||
QLIST_INSERT_HEAD(&dev->clocks, ncl, node);
|
||||
return ncl;
|
||||
}
|
||||
|
||||
void qdev_finalize_clocklist(DeviceState *dev)
|
||||
{
|
||||
/* called by @dev's device_finalize() */
|
||||
NamedClockList *ncl, *ncl_next;
|
||||
|
||||
QLIST_FOREACH_SAFE(ncl, &dev->clocks, node, ncl_next) {
|
||||
QLIST_REMOVE(ncl, node);
|
||||
if (!ncl->output && !ncl->alias) {
|
||||
/*
|
||||
* We kept a reference on the input clock to ensure it lives up to
|
||||
* this point so we can safely remove the callback.
|
||||
* It avoids having a callback to a deleted object if ncl->clock
|
||||
* is still referenced somewhere else (eg: by a clock output).
|
||||
*/
|
||||
clock_clear_callback(ncl->clock);
|
||||
object_unref(OBJECT(ncl->clock));
|
||||
}
|
||||
g_free(ncl->name);
|
||||
g_free(ncl);
|
||||
}
|
||||
}
|
||||
|
||||
Clock *qdev_init_clock_out(DeviceState *dev, const char *name)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
assert(name);
|
||||
|
||||
ncl = qdev_init_clocklist(dev, name, true, NULL);
|
||||
|
||||
return ncl->clock;
|
||||
}
|
||||
|
||||
Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
|
||||
ClockCallback *callback, void *opaque)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
assert(name);
|
||||
|
||||
ncl = qdev_init_clocklist(dev, name, false, NULL);
|
||||
|
||||
if (callback) {
|
||||
clock_set_callback(ncl->clock, callback, opaque);
|
||||
}
|
||||
return ncl->clock;
|
||||
}
|
||||
|
||||
void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks)
|
||||
{
|
||||
const struct ClockPortInitElem *elem;
|
||||
|
||||
for (elem = &clocks[0]; elem->name != NULL; elem++) {
|
||||
Clock **clkp;
|
||||
/* offset cannot be inside the DeviceState part */
|
||||
assert(elem->offset > sizeof(DeviceState));
|
||||
clkp = (Clock **)(((void *) dev) + elem->offset);
|
||||
if (elem->is_output) {
|
||||
*clkp = qdev_init_clock_out(dev, elem->name);
|
||||
} else {
|
||||
*clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
QLIST_FOREACH(ncl, &dev->clocks, node) {
|
||||
if (strcmp(name, ncl->name) == 0) {
|
||||
return ncl;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Clock *qdev_get_clock_in(DeviceState *dev, const char *name)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
assert(name);
|
||||
|
||||
ncl = qdev_get_clocklist(dev, name);
|
||||
assert(!ncl->output);
|
||||
|
||||
return ncl->clock;
|
||||
}
|
||||
|
||||
Clock *qdev_get_clock_out(DeviceState *dev, const char *name)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
assert(name);
|
||||
|
||||
ncl = qdev_get_clocklist(dev, name);
|
||||
assert(ncl->output);
|
||||
|
||||
return ncl->clock;
|
||||
}
|
||||
|
||||
Clock *qdev_alias_clock(DeviceState *dev, const char *name,
|
||||
DeviceState *alias_dev, const char *alias_name)
|
||||
{
|
||||
NamedClockList *ncl;
|
||||
|
||||
assert(name && alias_name);
|
||||
|
||||
ncl = qdev_get_clocklist(dev, name);
|
||||
|
||||
qdev_init_clocklist(alias_dev, alias_name, ncl->output, ncl->clock);
|
||||
|
||||
return ncl->clock;
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
#include "hw/qdev-properties.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
@ -855,6 +856,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
|||
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
||||
HotplugHandler *hotplug_ctrl;
|
||||
BusState *bus;
|
||||
NamedClockList *ncl;
|
||||
Error *local_err = NULL;
|
||||
bool unattached_parent = false;
|
||||
static int unattached_count;
|
||||
|
@ -902,6 +904,13 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
|||
*/
|
||||
g_free(dev->canonical_path);
|
||||
dev->canonical_path = object_get_canonical_path(OBJECT(dev));
|
||||
QLIST_FOREACH(ncl, &dev->clocks, node) {
|
||||
if (ncl->alias) {
|
||||
continue;
|
||||
} else {
|
||||
clock_setup_canonical_path(ncl->clock);
|
||||
}
|
||||
}
|
||||
|
||||
if (qdev_get_vmsd(dev)) {
|
||||
if (vmstate_register_with_alias_id(VMSTATE_IF(dev),
|
||||
|
@ -1025,6 +1034,7 @@ static void device_initfn(Object *obj)
|
|||
dev->allow_unplug_during_migration = false;
|
||||
|
||||
QLIST_INIT(&dev->gpios);
|
||||
QLIST_INIT(&dev->clocks);
|
||||
}
|
||||
|
||||
static void device_post_init(Object *obj)
|
||||
|
@ -1054,6 +1064,8 @@ static void device_finalize(Object *obj)
|
|||
*/
|
||||
}
|
||||
|
||||
qdev_finalize_clocklist(dev);
|
||||
|
||||
/* Only send event if the device had been completely realized */
|
||||
if (dev->pending_deleted_event) {
|
||||
g_assert(dev->canonical_path);
|
||||
|
|
|
@ -27,3 +27,10 @@ resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int
|
|||
resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
|
||||
resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
|
||||
resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
|
||||
|
||||
# clock.c
|
||||
clock_set_source(const char *clk, const char *src) "'%s', src='%s'"
|
||||
clock_disconnect(const char *clk) "'%s'"
|
||||
clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', ns=%"PRIu64"->%"PRIu64
|
||||
clock_propagate(const char *clk) "'%s'"
|
||||
clock_update(const char *clk, const char *src, uint64_t val, int cb) "'%s', src='%s', ns=%"PRIu64", cb=%d"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue