/*
 * Copyright (C) 2016-2017 Imagination Technologies
 * Author: Paul Burton <paul.burton@mips.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#define pr_fmt(fmt) "clk-boston: " fmt

#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/mfd/syscon.h>

#include <dt-bindings/clock/boston-clock.h>

#define BOSTON_PLAT_MMCMDIV		0x30
# define BOSTON_PLAT_MMCMDIV_CLK0DIV	(0xff << 0)
# define BOSTON_PLAT_MMCMDIV_INPUT	(0xff << 8)
# define BOSTON_PLAT_MMCMDIV_MUL	(0xff << 16)
# define BOSTON_PLAT_MMCMDIV_CLK1DIV	(0xff << 24)

#define BOSTON_CLK_COUNT 3

static u32 ext_field(u32 val, u32 mask)
{
	return (val & mask) >> (ffs(mask) - 1);
}

static void __init clk_boston_setup(struct device_node *np)
{
	unsigned long in_freq, cpu_freq, sys_freq;
	uint mmcmdiv, mul, cpu_div, sys_div;
	struct clk_hw_onecell_data *onecell;
	struct regmap *regmap;
	struct clk_hw *hw;
	int err;

	regmap = syscon_node_to_regmap(np->parent);
	if (IS_ERR(regmap)) {
		pr_err("failed to find regmap\n");
		return;
	}

	err = regmap_read(regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
	if (err) {
		pr_err("failed to read mmcm_div register: %d\n", err);
		return;
	}

	in_freq = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT) * 1000000;
	mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL);

	sys_div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV);
	sys_freq = mult_frac(in_freq, mul, sys_div);

	cpu_div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV);
	cpu_freq = mult_frac(in_freq, mul, cpu_div);

	onecell = kzalloc(sizeof(*onecell) +
			  (BOSTON_CLK_COUNT * sizeof(struct clk_hw *)),
			  GFP_KERNEL);
	if (!onecell)
		return;

	onecell->num = BOSTON_CLK_COUNT;

	hw = clk_hw_register_fixed_rate(NULL, "input", NULL, 0, in_freq);
	if (IS_ERR(hw)) {
		pr_err("failed to register input clock: %ld\n", PTR_ERR(hw));
		goto fail_input;
	}
	onecell->hws[BOSTON_CLK_INPUT] = hw;

	hw = clk_hw_register_fixed_rate(NULL, "sys", "input", 0, sys_freq);
	if (IS_ERR(hw)) {
		pr_err("failed to register sys clock: %ld\n", PTR_ERR(hw));
		goto fail_sys;
	}
	onecell->hws[BOSTON_CLK_SYS] = hw;

	hw = clk_hw_register_fixed_rate(NULL, "cpu", "input", 0, cpu_freq);
	if (IS_ERR(hw)) {
		pr_err("failed to register cpu clock: %ld\n", PTR_ERR(hw));
		goto fail_cpu;
	}
	onecell->hws[BOSTON_CLK_CPU] = hw;

	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
	if (err) {
		pr_err("failed to add DT provider: %d\n", err);
		goto fail_clk_add;
	}

	return;

fail_clk_add:
	clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_CPU]);
fail_cpu:
	clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_SYS]);
fail_sys:
	clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_INPUT]);
fail_input:
	kfree(onecell);
}

/*
 * Use CLK_OF_DECLARE so that this driver is probed early enough to provide the
 * CPU frequency for use with the GIC or cop0 counters/timers.
 */
CLK_OF_DECLARE(clk_boston, "img,boston-clock", clk_boston_setup);
