// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc.
 * Copyright 2017~2018 NXP
 *
 * Author: Dong Aisheng <aisheng.dong@nxp.com>
 *
 */

#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>

#include "clk.h"

/**
 * struct clk_pfdv2 - IMX PFD clock
 * @hw:		clock source
 * @reg:	PFD register address
 * @gate_bit:	Gate bit offset
 * @vld_bit:	Valid bit offset
 * @frac_off:	PLL Fractional Divider offset
 */

struct clk_pfdv2 {
	struct clk_hw	hw;
	void __iomem	*reg;
	u8		gate_bit;
	u8		vld_bit;
	u8		frac_off;
};

#define to_clk_pfdv2(_hw) container_of(_hw, struct clk_pfdv2, hw)

#define CLK_PFDV2_FRAC_MASK 0x3f

#define LOCK_TIMEOUT_US		USEC_PER_MSEC

static DEFINE_SPINLOCK(pfd_lock);

static int clk_pfdv2_wait(struct clk_pfdv2 *pfd)
{
	u32 val;

	return readl_poll_timeout(pfd->reg, val, val & (1 << pfd->vld_bit),
				  0, LOCK_TIMEOUT_US);
}

static int clk_pfdv2_enable(struct clk_hw *hw)
{
	struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&pfd_lock, flags);
	val = readl_relaxed(pfd->reg);
	val &= ~(1 << pfd->gate_bit);
	writel_relaxed(val, pfd->reg);
	spin_unlock_irqrestore(&pfd_lock, flags);

	return clk_pfdv2_wait(pfd);
}

static void clk_pfdv2_disable(struct clk_hw *hw)
{
	struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&pfd_lock, flags);
	val = readl_relaxed(pfd->reg);
	val |= (1 << pfd->gate_bit);
	writel_relaxed(val, pfd->reg);
	spin_unlock_irqrestore(&pfd_lock, flags);
}

static unsigned long clk_pfdv2_recalc_rate(struct clk_hw *hw,
					   unsigned long parent_rate)
{
	struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
	u64 tmp = parent_rate;
	u8 frac;

	frac = (readl_relaxed(pfd->reg) >> pfd->frac_off)
		& CLK_PFDV2_FRAC_MASK;

	if (!frac) {
		pr_debug("clk_pfdv2: %s invalid pfd frac value 0\n",
			 clk_hw_get_name(hw));
		return 0;
	}

	tmp *= 18;
	do_div(tmp, frac);

	return tmp;
}

static int clk_pfdv2_determine_rate(struct clk_hw *hw,
				    struct clk_rate_request *req)
{
	unsigned long parent_rates[] = {
					480000000,
					528000000,
					req->best_parent_rate
				       };
	unsigned long best_rate = -1UL, rate = req->rate;
	unsigned long best_parent_rate = req->best_parent_rate;
	u64 tmp;
	u8 frac;
	int i;

	for (i = 0; i < ARRAY_SIZE(parent_rates); i++) {
		tmp = parent_rates[i];
		tmp = tmp * 18 + rate / 2;
		do_div(tmp, rate);
		frac = tmp;

		if (frac < 12)
			frac = 12;
		else if (frac > 35)
			frac = 35;

		tmp = parent_rates[i];
		tmp *= 18;
		do_div(tmp, frac);

		if (abs(tmp - req->rate) < abs(best_rate - req->rate)) {
			best_rate = tmp;
			best_parent_rate = parent_rates[i];
		}
	}

	req->best_parent_rate = best_parent_rate;
	req->rate = best_rate;

	return 0;
}

static int clk_pfdv2_is_enabled(struct clk_hw *hw)
{
	struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);

	if (readl_relaxed(pfd->reg) & (1 << pfd->gate_bit))
		return 0;

	return 1;
}

static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate,
			      unsigned long parent_rate)
{
	struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
	unsigned long flags;
	u64 tmp = parent_rate;
	u32 val;
	u8 frac;

	if (!rate)
		return -EINVAL;

	/* PFD can NOT change rate without gating */
	WARN_ON(clk_pfdv2_is_enabled(hw));

	tmp = tmp * 18 + rate / 2;
	do_div(tmp, rate);
	frac = tmp;
	if (frac < 12)
		frac = 12;
	else if (frac > 35)
		frac = 35;

	spin_lock_irqsave(&pfd_lock, flags);
	val = readl_relaxed(pfd->reg);
	val &= ~(CLK_PFDV2_FRAC_MASK << pfd->frac_off);
	val |= frac << pfd->frac_off;
	writel_relaxed(val, pfd->reg);
	spin_unlock_irqrestore(&pfd_lock, flags);

	return 0;
}

static const struct clk_ops clk_pfdv2_ops = {
	.enable		= clk_pfdv2_enable,
	.disable	= clk_pfdv2_disable,
	.recalc_rate	= clk_pfdv2_recalc_rate,
	.determine_rate	= clk_pfdv2_determine_rate,
	.set_rate	= clk_pfdv2_set_rate,
	.is_enabled     = clk_pfdv2_is_enabled,
};

struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name,
			     void __iomem *reg, u8 idx)
{
	struct clk_init_data init;
	struct clk_pfdv2 *pfd;
	struct clk_hw *hw;
	int ret;

	WARN_ON(idx > 3);

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

	pfd->reg = reg;
	pfd->gate_bit = (idx + 1) * 8 - 1;
	pfd->vld_bit = pfd->gate_bit - 1;
	pfd->frac_off = idx * 8;

	init.name = name;
	init.ops = &clk_pfdv2_ops;
	init.parent_names = &parent_name;
	init.num_parents = 1;
	init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;

	pfd->hw.init = &init;

	hw = &pfd->hw;
	ret = clk_hw_register(NULL, hw);
	if (ret) {
		kfree(pfd);
		hw = ERR_PTR(ret);
	}

	return hw;
}
