/*
 * 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 = (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,
                                       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);
}
