/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that 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.
 */

#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/types.h>

#define REG_DIV_CTL1			0x43
#define DIV_CTL1_DIV_FACTOR_MASK	GENMASK(2, 0)

#define REG_EN_CTL			0x46
#define REG_EN_MASK			BIT(7)

struct clkdiv {
	struct regmap		*regmap;
	u16			base;
	spinlock_t		lock;

	struct clk_hw		hw;
	unsigned int		cxo_period_ns;
};

static inline struct clkdiv *to_clkdiv(struct clk_hw *hw)
{
	return container_of(hw, struct clkdiv, hw);
}

static inline unsigned int div_factor_to_div(unsigned int div_factor)
{
	if (!div_factor)
		div_factor = 1;

	return 1 << (div_factor - 1);
}

static inline unsigned int div_to_div_factor(unsigned int div)
{
	return min(ilog2(div) + 1, 7);
}

static bool is_spmi_pmic_clkdiv_enabled(struct clkdiv *clkdiv)
{
	unsigned int val = 0;

	regmap_read(clkdiv->regmap, clkdiv->base + REG_EN_CTL, &val);

	return val & REG_EN_MASK;
}

static int
__spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool enable,
				    unsigned int div_factor)
{
	int ret;
	unsigned int ns = clkdiv->cxo_period_ns;
	unsigned int div = div_factor_to_div(div_factor);

	ret = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_EN_CTL,
				 REG_EN_MASK, enable ? REG_EN_MASK : 0);
	if (ret)
		return ret;

	if (enable)
		ndelay((2 + 3 * div) * ns);
	else
		ndelay(3 * div * ns);

	return 0;
}

static int spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool enable)
{
	unsigned int div_factor;

	regmap_read(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1, &div_factor);
	div_factor &= DIV_CTL1_DIV_FACTOR_MASK;

	return __spmi_pmic_clkdiv_set_enable_state(clkdiv, enable, div_factor);
}

static int clk_spmi_pmic_div_enable(struct clk_hw *hw)
{
	struct clkdiv *clkdiv = to_clkdiv(hw);
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&clkdiv->lock, flags);
	ret = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);
	spin_unlock_irqrestore(&clkdiv->lock, flags);

	return ret;
}

static void clk_spmi_pmic_div_disable(struct clk_hw *hw)
{
	struct clkdiv *clkdiv = to_clkdiv(hw);
	unsigned long flags;

	spin_lock_irqsave(&clkdiv->lock, flags);
	spmi_pmic_clkdiv_set_enable_state(clkdiv, false);
	spin_unlock_irqrestore(&clkdiv->lock, flags);
}

static long clk_spmi_pmic_div_round_rate(struct clk_hw *hw, unsigned long rate,
					 unsigned long *parent_rate)
{
	unsigned int div, div_factor;

	div = DIV_ROUND_UP(*parent_rate, rate);
	div_factor = div_to_div_factor(div);
	div = div_factor_to_div(div_factor);

	return *parent_rate / div;
}

static unsigned long
clk_spmi_pmic_div_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
	struct clkdiv *clkdiv = to_clkdiv(hw);
	unsigned int div_factor;

	regmap_read(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1, &div_factor);
	div_factor &= DIV_CTL1_DIV_FACTOR_MASK;

	return parent_rate / div_factor_to_div(div_factor);
}

static int clk_spmi_pmic_div_set_rate(struct clk_hw *hw, unsigned long rate,
				      unsigned long parent_rate)
{
	struct clkdiv *clkdiv = to_clkdiv(hw);
	unsigned int div_factor = div_to_div_factor(parent_rate / rate);
	unsigned long flags;
	bool enabled;
	int ret;

	spin_lock_irqsave(&clkdiv->lock, flags);
	enabled = is_spmi_pmic_clkdiv_enabled(clkdiv);
	if (enabled) {
		ret = spmi_pmic_clkdiv_set_enable_state(clkdiv, false);
		if (ret)
			goto unlock;
	}

	ret = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1,
				 DIV_CTL1_DIV_FACTOR_MASK, div_factor);
	if (ret)
		goto unlock;

	if (enabled)
		ret = __spmi_pmic_clkdiv_set_enable_state(clkdiv, true,
							  div_factor);

unlock:
	spin_unlock_irqrestore(&clkdiv->lock, flags);

	return ret;
}

static const struct clk_ops clk_spmi_pmic_div_ops = {
	.enable = clk_spmi_pmic_div_enable,
	.disable = clk_spmi_pmic_div_disable,
	.set_rate = clk_spmi_pmic_div_set_rate,
	.recalc_rate = clk_spmi_pmic_div_recalc_rate,
	.round_rate = clk_spmi_pmic_div_round_rate,
};

struct spmi_pmic_div_clk_cc {
	int		nclks;
	struct clkdiv	clks[];
};

static struct clk_hw *
spmi_pmic_div_clk_hw_get(struct of_phandle_args *clkspec, void *data)
{
	struct spmi_pmic_div_clk_cc *cc = data;
	int idx = clkspec->args[0] - 1; /* Start at 1 instead of 0 */

	if (idx < 0 || idx >= cc->nclks) {
		pr_err("%s: index value %u is invalid; allowed range [1, %d]\n",
		       __func__, clkspec->args[0], cc->nclks);
		return ERR_PTR(-EINVAL);
	}

	return &cc->clks[idx].hw;
}

static int spmi_pmic_clkdiv_probe(struct platform_device *pdev)
{
	struct spmi_pmic_div_clk_cc *cc;
	struct clk_init_data init = {};
	struct clkdiv *clkdiv;
	struct clk *cxo;
	struct regmap *regmap;
	struct device *dev = &pdev->dev;
	struct device_node *of_node = dev->of_node;
	const char *parent_name;
	int nclks, i, ret, cxo_hz;
	char name[20];
	u32 start;

	ret = of_property_read_u32(of_node, "reg", &start);
	if (ret < 0) {
		dev_err(dev, "reg property reading failed\n");
		return ret;
	}

	regmap = dev_get_regmap(dev->parent, NULL);
	if (!regmap) {
		dev_err(dev, "Couldn't get parent's regmap\n");
		return -EINVAL;
	}

	ret = of_property_read_u32(of_node, "qcom,num-clkdivs", &nclks);
	if (ret < 0) {
		dev_err(dev, "qcom,num-clkdivs property reading failed, ret=%d\n",
			ret);
		return ret;
	}

	if (!nclks)
		return -EINVAL;

	cc = devm_kzalloc(dev, struct_size(cc, clks, nclks), GFP_KERNEL);
	if (!cc)
		return -ENOMEM;
	cc->nclks = nclks;

	cxo = clk_get(dev, "xo");
	if (IS_ERR(cxo)) {
		ret = PTR_ERR(cxo);
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "failed to get xo clock\n");
		return ret;
	}
	cxo_hz = clk_get_rate(cxo);
	clk_put(cxo);

	parent_name = of_clk_get_parent_name(of_node, 0);
	if (!parent_name) {
		dev_err(dev, "missing parent clock\n");
		return -ENODEV;
	}

	init.name = name;
	init.parent_names = &parent_name;
	init.num_parents = 1;
	init.ops = &clk_spmi_pmic_div_ops;

	for (i = 0, clkdiv = cc->clks; i < nclks; i++) {
		snprintf(name, sizeof(name), "div_clk%d", i + 1);

		spin_lock_init(&clkdiv[i].lock);
		clkdiv[i].base = start + i * 0x100;
		clkdiv[i].regmap = regmap;
		clkdiv[i].cxo_period_ns = NSEC_PER_SEC / cxo_hz;
		clkdiv[i].hw.init = &init;

		ret = devm_clk_hw_register(dev, &clkdiv[i].hw);
		if (ret)
			return ret;
	}

	return devm_of_clk_add_hw_provider(dev, spmi_pmic_div_clk_hw_get, cc);
}

static const struct of_device_id spmi_pmic_clkdiv_match_table[] = {
	{ .compatible = "qcom,spmi-clkdiv" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spmi_pmic_clkdiv_match_table);

static struct platform_driver spmi_pmic_clkdiv_driver = {
	.driver		= {
		.name	= "qcom,spmi-pmic-clkdiv",
		.of_match_table = spmi_pmic_clkdiv_match_table,
	},
	.probe		= spmi_pmic_clkdiv_probe,
};
module_platform_driver(spmi_pmic_clkdiv_driver);

MODULE_DESCRIPTION("QCOM SPMI PMIC clkdiv driver");
MODULE_LICENSE("GPL v2");
