/*
 * Copyright (c) 2015 Endless Mobile, Inc.
 * Author: Carlo Caione <carlo@endlessm.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

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

#include "clkc.h"

static DEFINE_SPINLOCK(clk_lock);

static struct clk **clks;
static struct clk_onecell_data clk_data;

struct clk ** __init meson_clk_init(struct device_node *np,
				   unsigned long nr_clks)
{
	clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
	if (!clks)
		return ERR_PTR(-ENOMEM);

	clk_data.clks = clks;
	clk_data.clk_num = nr_clks;
	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);

	return clks;
}

static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
{
	if (clks && id)
		clks[id] = clk;
}

static struct clk * __init
meson_clk_register_composite(const struct clk_conf *clk_conf,
			     void __iomem *clk_base)
{
	struct clk *clk;
	struct clk_mux *mux = NULL;
	struct clk_divider *div = NULL;
	struct clk_gate *gate = NULL;
	const struct clk_ops *mux_ops = NULL;
	const struct composite_conf *composite_conf;

	composite_conf = clk_conf->conf.composite;

	if (clk_conf->num_parents > 1) {
		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
		if (!mux)
			return ERR_PTR(-ENOMEM);

		mux->reg = clk_base + clk_conf->reg_off
				+ composite_conf->mux_parm.reg_off;
		mux->shift = composite_conf->mux_parm.shift;
		mux->mask = BIT(composite_conf->mux_parm.width) - 1;
		mux->flags = composite_conf->mux_flags;
		mux->lock = &clk_lock;
		mux->table = composite_conf->mux_table;
		mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
			  &clk_mux_ro_ops : &clk_mux_ops;
	}

	if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
		div = kzalloc(sizeof(*div), GFP_KERNEL);
		if (!div) {
			clk = ERR_PTR(-ENOMEM);
			goto error;
		}

		div->reg = clk_base + clk_conf->reg_off
				+ composite_conf->div_parm.reg_off;
		div->shift = composite_conf->div_parm.shift;
		div->width = composite_conf->div_parm.width;
		div->lock = &clk_lock;
		div->flags = composite_conf->div_flags;
		div->table = composite_conf->div_table;
	}

	if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
		if (!gate) {
			clk = ERR_PTR(-ENOMEM);
			goto error;
		}

		gate->reg = clk_base + clk_conf->reg_off
				+ composite_conf->div_parm.reg_off;
		gate->bit_idx = composite_conf->gate_parm.shift;
		gate->flags = composite_conf->gate_flags;
		gate->lock = &clk_lock;
	}

	clk = clk_register_composite(NULL, clk_conf->clk_name,
				    clk_conf->clks_parent,
				    clk_conf->num_parents,
				    mux ? &mux->hw : NULL, mux_ops,
				    div ? &div->hw : NULL, &clk_divider_ops,
				    gate ? &gate->hw : NULL, &clk_gate_ops,
				    clk_conf->flags);
	if (IS_ERR(clk))
		goto error;

	return clk;

error:
	kfree(gate);
	kfree(div);
	kfree(mux);

	return clk;
}

static struct clk * __init
meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
				void __iomem *clk_base)
{
	struct clk *clk;
	const struct fixed_fact_conf *fixed_fact_conf;
	const struct parm *p;
	unsigned int mult, div;
	u32 reg;

	fixed_fact_conf = &clk_conf->conf.fixed_fact;

	mult = clk_conf->conf.fixed_fact.mult;
	div = clk_conf->conf.fixed_fact.div;

	if (!mult) {
		mult = 1;
		p = &fixed_fact_conf->mult_parm;
		if (MESON_PARM_APPLICABLE(p)) {
			reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
			mult = PARM_GET(p->width, p->shift, reg);
		}
	}

	if (!div) {
		div = 1;
		p = &fixed_fact_conf->div_parm;
		if (MESON_PARM_APPLICABLE(p)) {
			reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
			mult = PARM_GET(p->width, p->shift, reg);
		}
	}

	clk = clk_register_fixed_factor(NULL,
			clk_conf->clk_name,
			clk_conf->clks_parent[0],
			clk_conf->flags,
			mult, div);

	return clk;
}

static struct clk * __init
meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
			      void __iomem *clk_base)
{
	struct clk *clk;
	const struct fixed_rate_conf *fixed_rate_conf;
	const struct parm *r;
	unsigned long rate;
	u32 reg;

	fixed_rate_conf = &clk_conf->conf.fixed_rate;
	rate = fixed_rate_conf->rate;

	if (!rate) {
		r = &fixed_rate_conf->rate_parm;
		reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
		rate = PARM_GET(r->width, r->shift, reg);
	}

	rate *= 1000000;

	clk = clk_register_fixed_rate(NULL,
			clk_conf->clk_name,
			clk_conf->num_parents
				? clk_conf->clks_parent[0] : NULL,
			clk_conf->flags, rate);

	return clk;
}

void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
				    size_t nr_confs,
				    void __iomem *clk_base)
{
	unsigned int i;
	struct clk *clk = NULL;

	for (i = 0; i < nr_confs; i++) {
		const struct clk_conf *clk_conf = &clk_confs[i];

		switch (clk_conf->clk_type) {
		case CLK_FIXED_RATE:
			clk = meson_clk_register_fixed_rate(clk_conf,
							    clk_base);
			break;
		case CLK_FIXED_FACTOR:
			clk = meson_clk_register_fixed_factor(clk_conf,
							      clk_base);
			break;
		case CLK_COMPOSITE:
			clk = meson_clk_register_composite(clk_conf,
							   clk_base);
			break;
		case CLK_CPU:
			clk = meson_clk_register_cpu(clk_conf, clk_base,
						     &clk_lock);
			break;
		case CLK_PLL:
			clk = meson_clk_register_pll(clk_conf, clk_base,
						     &clk_lock);
			break;
		default:
			clk = NULL;
		}

		if (!clk) {
			pr_err("%s: unknown clock type %d\n", __func__,
			       clk_conf->clk_type);
			continue;
		}

		if (IS_ERR(clk)) {
			pr_warn("%s: Unable to create %s clock\n", __func__,
				clk_conf->clk_name);
			continue;
		}

		meson_clk_add_lookup(clk, clk_conf->clk_id);
	}
}
