/*
 * 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 "qemu/cutils.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));
}

Clock *clock_new(Object *parent, const char *name)
{
    Object *obj;
    Clock *clk;

    obj = object_new(TYPE_CLOCK);
    object_property_add_child(parent, name, obj);
    object_unref(obj);

    clk = CLOCK(obj);
    clock_setup_canonical_path(clk);

    return clk;
}

void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque,
                        unsigned int events)
{
    clk->callback = cb;
    clk->callback_opaque = opaque;
    clk->callback_events = events;
}

void clock_clear_callback(Clock *clk)
{
    clock_set_callback(clk, NULL, NULL, 0);
}

bool clock_set(Clock *clk, uint64_t period)
{
    if (clk->period == period) {
        return false;
    }
    trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_HZ(clk->period),
                    CLOCK_PERIOD_TO_HZ(period));
    clk->period = period;

    return true;
}

static uint64_t clock_get_child_period(Clock *clk)
{
    /*
     * Return the period to be used for child clocks, which is the parent
     * clock period adjusted for multiplier and divider effects.
     */
    return muldiv64(clk->period, clk->multiplier, clk->divider);
}

static void clock_call_callback(Clock *clk, ClockEvent event)
{
    /*
     * Call the Clock's callback for this event, if it has one and
     * is interested in this event.
     */
    if (clk->callback && (clk->callback_events & event)) {
        clk->callback(clk->callback_opaque, event);
    }
}

static void clock_propagate_period(Clock *clk, bool call_callbacks)
{
    Clock *child;
    uint64_t child_period = clock_get_child_period(clk);

    QLIST_FOREACH(child, &clk->children, sibling) {
        if (child->period != child_period) {
            if (call_callbacks) {
                clock_call_callback(child, ClockPreUpdate);
            }
            child->period = child_period;
            trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
                               CLOCK_PERIOD_TO_HZ(child->period),
                               call_callbacks);
            if (call_callbacks) {
                clock_call_callback(child, ClockUpdate);
            }
            clock_propagate_period(child, call_callbacks);
        }
    }
}

void clock_propagate(Clock *clk)
{
    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 = clock_get_child_period(src);
    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);
}

char *clock_display_freq(Clock *clk)
{
    return freq_to_str(clock_get_hz(clk));
}

bool clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider)
{
    assert(divider != 0);

    if (clk->multiplier == multiplier && clk->divider == divider) {
        return false;
    }

    trace_clock_set_mul_div(CLOCK_PATH(clk), clk->multiplier, multiplier,
                            clk->divider, divider);
    clk->multiplier = multiplier;
    clk->divider = divider;

    return true;
}

static void clock_initfn(Object *obj)
{
    Clock *clk = CLOCK(obj);

    clk->multiplier = 1;
    clk->divider = 1;

    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)
