// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Freescale FlexTimer Module (FTM) timer driver.
 *
 * Copyright 2014 Freescale Semiconductor, Inc.
 */

#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/sched_clock.h>
#include <linux/slab.h>
#include <linux/fsl/ftm.h>

#define FTM_SC_CLK(c)	((c) << FTM_SC_CLK_MASK_SHIFT)

struct ftm_clock_device {
	void __iomem *clksrc_base;
	void __iomem *clkevt_base;
	unsigned long periodic_cyc;
	unsigned long ps;
	bool big_endian;
};

static struct ftm_clock_device *priv;

static inline u32 ftm_readl(void __iomem *addr)
{
	if (priv->big_endian)
		return ioread32be(addr);
	else
		return ioread32(addr);
}

static inline void ftm_writel(u32 val, void __iomem *addr)
{
	if (priv->big_endian)
		iowrite32be(val, addr);
	else
		iowrite32(val, addr);
}

static inline void ftm_counter_enable(void __iomem *base)
{
	u32 val;

	/* select and enable counter clock source */
	val = ftm_readl(base + FTM_SC);
	val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK);
	val |= priv->ps | FTM_SC_CLK(1);
	ftm_writel(val, base + FTM_SC);
}

static inline void ftm_counter_disable(void __iomem *base)
{
	u32 val;

	/* disable counter clock source */
	val = ftm_readl(base + FTM_SC);
	val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK);
	ftm_writel(val, base + FTM_SC);
}

static inline void ftm_irq_acknowledge(void __iomem *base)
{
	u32 val;

	val = ftm_readl(base + FTM_SC);
	val &= ~FTM_SC_TOF;
	ftm_writel(val, base + FTM_SC);
}

static inline void ftm_irq_enable(void __iomem *base)
{
	u32 val;

	val = ftm_readl(base + FTM_SC);
	val |= FTM_SC_TOIE;
	ftm_writel(val, base + FTM_SC);
}

static inline void ftm_irq_disable(void __iomem *base)
{
	u32 val;

	val = ftm_readl(base + FTM_SC);
	val &= ~FTM_SC_TOIE;
	ftm_writel(val, base + FTM_SC);
}

static inline void ftm_reset_counter(void __iomem *base)
{
	/*
	 * The CNT register contains the FTM counter value.
	 * Reset clears the CNT register. Writing any value to COUNT
	 * updates the counter with its initial value, CNTIN.
	 */
	ftm_writel(0x00, base + FTM_CNT);
}

static u64 notrace ftm_read_sched_clock(void)
{
	return ftm_readl(priv->clksrc_base + FTM_CNT);
}

static int ftm_set_next_event(unsigned long delta,
				struct clock_event_device *unused)
{
	/*
	 * The CNNIN and MOD are all double buffer registers, writing
	 * to the MOD register latches the value into a buffer. The MOD
	 * register is updated with the value of its write buffer with
	 * the following scenario:
	 * a, the counter source clock is disabled.
	 */
	ftm_counter_disable(priv->clkevt_base);

	/* Force the value of CNTIN to be loaded into the FTM counter */
	ftm_reset_counter(priv->clkevt_base);

	/*
	 * The counter increments until the value of MOD is reached,
	 * at which point the counter is reloaded with the value of CNTIN.
	 * The TOF (the overflow flag) bit is set when the FTM counter
	 * changes from MOD to CNTIN. So we should using the delta - 1.
	 */
	ftm_writel(delta - 1, priv->clkevt_base + FTM_MOD);

	ftm_counter_enable(priv->clkevt_base);

	ftm_irq_enable(priv->clkevt_base);

	return 0;
}

static int ftm_set_oneshot(struct clock_event_device *evt)
{
	ftm_counter_disable(priv->clkevt_base);
	return 0;
}

static int ftm_set_periodic(struct clock_event_device *evt)
{
	ftm_set_next_event(priv->periodic_cyc, evt);
	return 0;
}

static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *evt = dev_id;

	ftm_irq_acknowledge(priv->clkevt_base);

	if (likely(clockevent_state_oneshot(evt))) {
		ftm_irq_disable(priv->clkevt_base);
		ftm_counter_disable(priv->clkevt_base);
	}

	evt->event_handler(evt);

	return IRQ_HANDLED;
}

static struct clock_event_device ftm_clockevent = {
	.name			= "Freescale ftm timer",
	.features		= CLOCK_EVT_FEAT_PERIODIC |
				  CLOCK_EVT_FEAT_ONESHOT,
	.set_state_periodic	= ftm_set_periodic,
	.set_state_oneshot	= ftm_set_oneshot,
	.set_next_event		= ftm_set_next_event,
	.rating			= 300,
};

static int __init ftm_clockevent_init(unsigned long freq, int irq)
{
	int err;

	ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN);
	ftm_writel(~0u, priv->clkevt_base + FTM_MOD);

	ftm_reset_counter(priv->clkevt_base);

	err = request_irq(irq, ftm_evt_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
			  "Freescale ftm timer", &ftm_clockevent);
	if (err) {
		pr_err("ftm: setup irq failed: %d\n", err);
		return err;
	}

	ftm_clockevent.cpumask = cpumask_of(0);
	ftm_clockevent.irq = irq;

	clockevents_config_and_register(&ftm_clockevent,
					freq / (1 << priv->ps),
					1, 0xffff);

	ftm_counter_enable(priv->clkevt_base);

	return 0;
}

static int __init ftm_clocksource_init(unsigned long freq)
{
	int err;

	ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN);
	ftm_writel(~0u, priv->clksrc_base + FTM_MOD);

	ftm_reset_counter(priv->clksrc_base);

	sched_clock_register(ftm_read_sched_clock, 16, freq / (1 << priv->ps));
	err = clocksource_mmio_init(priv->clksrc_base + FTM_CNT, "fsl-ftm",
				    freq / (1 << priv->ps), 300, 16,
				    clocksource_mmio_readl_up);
	if (err) {
		pr_err("ftm: init clock source mmio failed: %d\n", err);
		return err;
	}

	ftm_counter_enable(priv->clksrc_base);

	return 0;
}

static int __init __ftm_clk_init(struct device_node *np, char *cnt_name,
				 char *ftm_name)
{
	struct clk *clk;
	int err;

	clk = of_clk_get_by_name(np, cnt_name);
	if (IS_ERR(clk)) {
		pr_err("ftm: Cannot get \"%s\": %ld\n", cnt_name, PTR_ERR(clk));
		return PTR_ERR(clk);
	}
	err = clk_prepare_enable(clk);
	if (err) {
		pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n",
			cnt_name, err);
		return err;
	}

	clk = of_clk_get_by_name(np, ftm_name);
	if (IS_ERR(clk)) {
		pr_err("ftm: Cannot get \"%s\": %ld\n", ftm_name, PTR_ERR(clk));
		return PTR_ERR(clk);
	}
	err = clk_prepare_enable(clk);
	if (err)
		pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n",
			ftm_name, err);

	return clk_get_rate(clk);
}

static unsigned long __init ftm_clk_init(struct device_node *np)
{
	long freq;

	freq = __ftm_clk_init(np, "ftm-evt-counter-en", "ftm-evt");
	if (freq <= 0)
		return 0;

	freq = __ftm_clk_init(np, "ftm-src-counter-en", "ftm-src");
	if (freq <= 0)
		return 0;

	return freq;
}

static int __init ftm_calc_closest_round_cyc(unsigned long freq)
{
	priv->ps = 0;

	/* The counter register is only using the lower 16 bits, and
	 * if the 'freq' value is to big here, then the periodic_cyc
	 * may exceed 0xFFFF.
	 */
	do {
		priv->periodic_cyc = DIV_ROUND_CLOSEST(freq,
						HZ * (1 << priv->ps++));
	} while (priv->periodic_cyc > 0xFFFF);

	if (priv->ps > FTM_PS_MAX) {
		pr_err("ftm: the prescaler is %lu > %d\n",
				priv->ps, FTM_PS_MAX);
		return -EINVAL;
	}

	return 0;
}

static int __init ftm_timer_init(struct device_node *np)
{
	unsigned long freq;
	int ret, irq;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	ret = -ENXIO;
	priv->clkevt_base = of_iomap(np, 0);
	if (!priv->clkevt_base) {
		pr_err("ftm: unable to map event timer registers\n");
		goto err_clkevt;
	}

	priv->clksrc_base = of_iomap(np, 1);
	if (!priv->clksrc_base) {
		pr_err("ftm: unable to map source timer registers\n");
		goto err_clksrc;
	}

	ret = -EINVAL;
	irq = irq_of_parse_and_map(np, 0);
	if (irq <= 0) {
		pr_err("ftm: unable to get IRQ from DT, %d\n", irq);
		goto err;
	}

	priv->big_endian = of_property_read_bool(np, "big-endian");

	freq = ftm_clk_init(np);
	if (!freq)
		goto err;

	ret = ftm_calc_closest_round_cyc(freq);
	if (ret)
		goto err;

	ret = ftm_clocksource_init(freq);
	if (ret)
		goto err;

	ret = ftm_clockevent_init(freq, irq);
	if (ret)
		goto err;

	return 0;

err:
	iounmap(priv->clksrc_base);
err_clksrc:
	iounmap(priv->clkevt_base);
err_clkevt:
	kfree(priv);
	return ret;
}
TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init);
