// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
 */

#include <common.h>
#include <dm.h>
#include <init.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
#include <dm/root.h>
#include <clk.h>
#include <errno.h>
#include <timer.h>
#include <linux/err.h>

DECLARE_GLOBAL_DATA_PTR;

/*
 * Implement a timer uclass to work with lib/time.c. The timer is usually
 * a 32/64 bits free-running up counter. The get_rate() method is used to get
 * the input clock frequency of the timer. The get_count() method is used
 * to get the current 64 bits count value. If the hardware is counting down,
 * the value should be inversed inside the method. There may be no real
 * tick, and no timer interrupt.
 */

int notrace timer_get_count(struct udevice *dev, u64 *count)
{
	const struct timer_ops *ops = device_get_ops(dev);

	if (!ops->get_count)
		return -ENOSYS;

	return ops->get_count(dev, count);
}

unsigned long notrace timer_get_rate(struct udevice *dev)
{
	struct timer_dev_priv *uc_priv = dev->uclass_priv;

	return uc_priv->clock_rate;
}

static int timer_pre_probe(struct udevice *dev)
{
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
	struct clk timer_clk;
	int err;
	ulong ret;

	/* It is possible that a timer device has a null ofnode */
	if (!dev_of_valid(dev))
		return 0;

	err = clk_get_by_index(dev, 0, &timer_clk);
	if (!err) {
		ret = clk_get_rate(&timer_clk);
		if (IS_ERR_VALUE(ret))
			return ret;
		uc_priv->clock_rate = ret;
	} else {
		uc_priv->clock_rate =
			dev_read_u32_default(dev, "clock-frequency", 0);
	}
#endif

	return 0;
}

static int timer_post_probe(struct udevice *dev)
{
	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);

	if (!uc_priv->clock_rate)
		return -EINVAL;

	return 0;
}

u64 timer_conv_64(u32 count)
{
	/* increment tbh if tbl has rolled over */
	if (count < gd->timebase_l)
		gd->timebase_h++;
	gd->timebase_l = count;
	return ((u64)gd->timebase_h << 32) | gd->timebase_l;
}

int notrace dm_timer_init(void)
{
	struct udevice *dev = NULL;
	__maybe_unused ofnode node;
	int ret;

	if (gd->timer)
		return 0;

	/*
	 * Directly access gd->dm_root to suppress error messages, if the
	 * virtual root driver does not yet exist.
	 */
	if (gd->dm_root == NULL)
		return -EAGAIN;

#if !CONFIG_IS_ENABLED(OF_PLATDATA)
	/* Check for a chosen timer to be used for tick */
	node = ofnode_get_chosen_node("tick-timer");

	if (ofnode_valid(node) &&
	    uclass_get_device_by_ofnode(UCLASS_TIMER, node, &dev)) {
		/*
		 * If the timer is not marked to be bound before
		 * relocation, bind it anyway.
		 */
		if (!lists_bind_fdt(dm_root(), node, &dev, false)) {
			ret = device_probe(dev);
			if (ret)
				return ret;
		}
	}
#endif

	if (!dev) {
		/* Fall back to the first available timer */
		ret = uclass_first_device_err(UCLASS_TIMER, &dev);
		if (ret)
			return ret;
	}

	if (dev) {
		gd->timer = dev;
		return 0;
	}

	return -ENODEV;
}

UCLASS_DRIVER(timer) = {
	.id		= UCLASS_TIMER,
	.name		= "timer",
	.pre_probe	= timer_pre_probe,
	.flags		= DM_UC_FLAG_SEQ_ALIAS,
	.post_probe	= timer_post_probe,
	.per_device_auto_alloc_size = sizeof(struct timer_dev_priv),
};
