/*
 * 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 "qemu/error-report.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));
        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);
        /*
         * Since the link property has the OBJ_PROP_LINK_STRONG flag, the clk
         * object reference count gets decremented on property deletion.
         * However object_property_add_link does not increment it since it
         * doesn't know the linked object. Increment it here to ensure the
         * aliased clock stays alive during this device life-time.
         */
        object_ref(OBJECT(clk));
    }

    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,
                          unsigned int events)
{
    NamedClockList *ncl;

    assert(name);

    ncl = qdev_init_clocklist(dev, name, false, NULL);

    if (callback) {
        clock_set_callback(ncl->clock, callback, opaque, events);
    }
    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 = ((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,
                                       elem->callback_events);
        }
    }
}

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);
    if (!ncl) {
        error_report("Can not find clock-in '%s' for device type '%s'",
                     name, object_get_typename(OBJECT(dev)));
        abort();
    }
    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);
    if (!ncl) {
        error_report("Can not find clock-out '%s' for device type '%s'",
                     name, object_get_typename(OBJECT(dev)));
        abort();
    }
    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;
}

void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source)
{
    assert(!dev->realized);
    clock_set_source(qdev_get_clock_in(dev, name), source);
}
