// SPDX-License-Identifier: GPL-2.0
/*
 * Cortina Gemini SoC Clock Controller driver
 * Copyright (c) 2017 Linus Walleij <linus.walleij@linaro.org>
 */

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

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <linux/reset-controller.h>
#include <dt-bindings/reset/cortina,gemini-reset.h>
#include <dt-bindings/clock/cortina,gemini-clock.h>

/* Globally visible clocks */
static DEFINE_SPINLOCK(gemini_clk_lock);

#define GEMINI_GLOBAL_STATUS		0x04
#define PLL_OSC_SEL			BIT(30)
#define AHBSPEED_SHIFT			(15)
#define AHBSPEED_MASK			0x07
#define CPU_AHB_RATIO_SHIFT		(18)
#define CPU_AHB_RATIO_MASK		0x03

#define GEMINI_GLOBAL_PLL_CONTROL	0x08

#define GEMINI_GLOBAL_SOFT_RESET	0x0c

#define GEMINI_GLOBAL_MISC_CONTROL	0x30
#define PCI_CLK_66MHZ			BIT(18)

#define GEMINI_GLOBAL_CLOCK_CONTROL	0x34
#define PCI_CLKRUN_EN			BIT(16)
#define TVC_HALFDIV_SHIFT		(24)
#define TVC_HALFDIV_MASK		0x1f
#define SECURITY_CLK_SEL		BIT(29)

#define GEMINI_GLOBAL_PCI_DLL_CONTROL	0x44
#define PCI_DLL_BYPASS			BIT(31)
#define PCI_DLL_TAP_SEL_MASK		0x1f

/**
 * struct gemini_gate_data - Gemini gated clocks
 * @bit_idx: the bit used to gate this clock in the clock register
 * @name: the clock name
 * @parent_name: the name of the parent clock
 * @flags: standard clock framework flags
 */
struct gemini_gate_data {
	u8 bit_idx;
	const char *name;
	const char *parent_name;
	unsigned long flags;
};

/**
 * struct clk_gemini_pci - Gemini PCI clock
 * @hw: corresponding clock hardware entry
 * @map: regmap to access the registers
 */
struct clk_gemini_pci {
	struct clk_hw hw;
	struct regmap *map;
};

/**
 * struct gemini_reset - gemini reset controller
 * @map: regmap to access the containing system controller
 * @rcdev: reset controller device
 */
struct gemini_reset {
	struct regmap *map;
	struct reset_controller_dev rcdev;
};

/* Keeps track of all clocks */
static struct clk_hw_onecell_data *gemini_clk_data;

static const struct gemini_gate_data gemini_gates[] = {
	{ 1, "security-gate", "secdiv", 0 },
	{ 2, "gmac0-gate", "ahb", 0 },
	{ 3, "gmac1-gate", "ahb", 0 },
	{ 4, "sata0-gate", "ahb", 0 },
	{ 5, "sata1-gate", "ahb", 0 },
	{ 6, "usb0-gate", "ahb", 0 },
	{ 7, "usb1-gate", "ahb", 0 },
	{ 8, "ide-gate", "ahb", 0 },
	{ 9, "pci-gate", "ahb", 0 },
	/*
	 * The DDR controller may never have a driver, but certainly must
	 * not be gated off.
	 */
	{ 10, "ddr-gate", "ahb", CLK_IS_CRITICAL },
	/*
	 * The flash controller must be on to access NOR flash through the
	 * memory map.
	 */
	{ 11, "flash-gate", "ahb", CLK_IGNORE_UNUSED },
	{ 12, "tvc-gate", "ahb", 0 },
	{ 13, "boot-gate", "apb", 0 },
};

#define to_pciclk(_hw) container_of(_hw, struct clk_gemini_pci, hw)

#define to_gemini_reset(p) container_of((p), struct gemini_reset, rcdev)

static unsigned long gemini_pci_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct clk_gemini_pci *pciclk = to_pciclk(hw);
	u32 val;

	regmap_read(pciclk->map, GEMINI_GLOBAL_MISC_CONTROL, &val);
	if (val & PCI_CLK_66MHZ)
		return 66000000;
	return 33000000;
}

static long gemini_pci_round_rate(struct clk_hw *hw, unsigned long rate,
				  unsigned long *prate)
{
	/* We support 33 and 66 MHz */
	if (rate < 48000000)
		return 33000000;
	return 66000000;
}

static int gemini_pci_set_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long parent_rate)
{
	struct clk_gemini_pci *pciclk = to_pciclk(hw);

	if (rate == 33000000)
		return regmap_update_bits(pciclk->map,
					  GEMINI_GLOBAL_MISC_CONTROL,
					  PCI_CLK_66MHZ, 0);
	if (rate == 66000000)
		return regmap_update_bits(pciclk->map,
					  GEMINI_GLOBAL_MISC_CONTROL,
					  0, PCI_CLK_66MHZ);
	return -EINVAL;
}

static int gemini_pci_enable(struct clk_hw *hw)
{
	struct clk_gemini_pci *pciclk = to_pciclk(hw);

	regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL,
			   0, PCI_CLKRUN_EN);
	return 0;
}

static void gemini_pci_disable(struct clk_hw *hw)
{
	struct clk_gemini_pci *pciclk = to_pciclk(hw);

	regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL,
			   PCI_CLKRUN_EN, 0);
}

static int gemini_pci_is_enabled(struct clk_hw *hw)
{
	struct clk_gemini_pci *pciclk = to_pciclk(hw);
	unsigned int val;

	regmap_read(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, &val);
	return !!(val & PCI_CLKRUN_EN);
}

static const struct clk_ops gemini_pci_clk_ops = {
	.recalc_rate = gemini_pci_recalc_rate,
	.round_rate = gemini_pci_round_rate,
	.set_rate = gemini_pci_set_rate,
	.enable = gemini_pci_enable,
	.disable = gemini_pci_disable,
	.is_enabled = gemini_pci_is_enabled,
};

static struct clk_hw *gemini_pci_clk_setup(const char *name,
					   const char *parent_name,
					   struct regmap *map)
{
	struct clk_gemini_pci *pciclk;
	struct clk_init_data init;
	int ret;

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

	init.name = name;
	init.ops = &gemini_pci_clk_ops;
	init.flags = 0;
	init.parent_names = &parent_name;
	init.num_parents = 1;
	pciclk->map = map;
	pciclk->hw.init = &init;

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

	return &pciclk->hw;
}

/*
 * This is a self-deasserting reset controller.
 */
static int gemini_reset(struct reset_controller_dev *rcdev,
			unsigned long id)
{
	struct gemini_reset *gr = to_gemini_reset(rcdev);

	/* Manual says to always set BIT 30 (CPU1) to 1 */
	return regmap_write(gr->map,
			    GEMINI_GLOBAL_SOFT_RESET,
			    BIT(GEMINI_RESET_CPU1) | BIT(id));
}

static int gemini_reset_assert(struct reset_controller_dev *rcdev,
			       unsigned long id)
{
	return 0;
}

static int gemini_reset_deassert(struct reset_controller_dev *rcdev,
				 unsigned long id)
{
	return 0;
}

static int gemini_reset_status(struct reset_controller_dev *rcdev,
			     unsigned long id)
{
	struct gemini_reset *gr = to_gemini_reset(rcdev);
	u32 val;
	int ret;

	ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val);
	if (ret)
		return ret;

	return !!(val & BIT(id));
}

static const struct reset_control_ops gemini_reset_ops = {
	.reset = gemini_reset,
	.assert = gemini_reset_assert,
	.deassert = gemini_reset_deassert,
	.status = gemini_reset_status,
};

static int gemini_clk_probe(struct platform_device *pdev)
{
	/* Gives the fracions 1x, 1.5x, 1.85x and 2x */
	unsigned int cpu_ahb_mult[4] = { 1, 3, 24, 2 };
	unsigned int cpu_ahb_div[4] = { 1, 2, 13, 1 };
	void __iomem *base;
	struct gemini_reset *gr;
	struct regmap *map;
	struct clk_hw *hw;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	unsigned int mult, div;
	u32 val;
	int ret;
	int i;

	gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL);
	if (!gr)
		return -ENOMEM;

	/* Remap the system controller for the exclusive register */
	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	map = syscon_node_to_regmap(np);
	if (IS_ERR(map)) {
		dev_err(dev, "no syscon regmap\n");
		return PTR_ERR(map);
	}

	gr->map = map;
	gr->rcdev.owner = THIS_MODULE;
	gr->rcdev.nr_resets = 32;
	gr->rcdev.ops = &gemini_reset_ops;
	gr->rcdev.of_node = np;

	ret = devm_reset_controller_register(dev, &gr->rcdev);
	if (ret) {
		dev_err(dev, "could not register reset controller\n");
		return ret;
	}

	/* RTC clock 32768 Hz */
	hw = clk_hw_register_fixed_rate(NULL, "rtc", NULL, 0, 32768);
	gemini_clk_data->hws[GEMINI_CLK_RTC] = hw;

	/* CPU clock derived as a fixed ratio from the AHB clock */
	regmap_read(map, GEMINI_GLOBAL_STATUS, &val);
	val >>= CPU_AHB_RATIO_SHIFT;
	val &= CPU_AHB_RATIO_MASK;
	hw = clk_hw_register_fixed_factor(NULL, "cpu", "ahb", 0,
					  cpu_ahb_mult[val],
					  cpu_ahb_div[val]);
	gemini_clk_data->hws[GEMINI_CLK_CPU] = hw;

	/* Security clock is 1:1 or 0.75 of APB */
	regmap_read(map, GEMINI_GLOBAL_CLOCK_CONTROL, &val);
	if (val & SECURITY_CLK_SEL) {
		mult = 1;
		div = 1;
	} else {
		mult = 3;
		div = 4;
	}
	hw = clk_hw_register_fixed_factor(NULL, "secdiv", "ahb", 0, mult, div);

	/*
	 * These are the leaf gates, at boot no clocks are gated.
	 */
	for (i = 0; i < ARRAY_SIZE(gemini_gates); i++) {
		const struct gemini_gate_data *gd;

		gd = &gemini_gates[i];
		gemini_clk_data->hws[GEMINI_CLK_GATES + i] =
			clk_hw_register_gate(NULL, gd->name,
					     gd->parent_name,
					     gd->flags,
					     base + GEMINI_GLOBAL_CLOCK_CONTROL,
					     gd->bit_idx,
					     CLK_GATE_SET_TO_DISABLE,
					     &gemini_clk_lock);
	}

	/*
	 * The TV Interface Controller has a 5-bit half divider register.
	 * This clock is supposed to be 27MHz as this is an exact multiple
	 * of PAL and NTSC frequencies. The register is undocumented :(
	 * FIXME: figure out the parent and how the divider works.
	 */
	mult = 1;
	div = ((val >> TVC_HALFDIV_SHIFT) & TVC_HALFDIV_MASK);
	dev_dbg(dev, "TVC half divider value = %d\n", div);
	div += 1;
	hw = clk_hw_register_fixed_rate(NULL, "tvcdiv", "xtal", 0, 27000000);
	gemini_clk_data->hws[GEMINI_CLK_TVC] = hw;

	/* FIXME: very unclear what the parent is */
	hw = gemini_pci_clk_setup("PCI", "xtal", map);
	gemini_clk_data->hws[GEMINI_CLK_PCI] = hw;

	/* FIXME: very unclear what the parent is */
	hw = clk_hw_register_fixed_rate(NULL, "uart", "xtal", 0, 48000000);
	gemini_clk_data->hws[GEMINI_CLK_UART] = hw;

	return 0;
}

static const struct of_device_id gemini_clk_dt_ids[] = {
	{ .compatible = "cortina,gemini-syscon", },
	{ /* sentinel */ },
};

static struct platform_driver gemini_clk_driver = {
	.probe  = gemini_clk_probe,
	.driver = {
		.name = "gemini-clk",
		.of_match_table = gemini_clk_dt_ids,
		.suppress_bind_attrs = true,
	},
};
builtin_platform_driver(gemini_clk_driver);

static void __init gemini_cc_init(struct device_node *np)
{
	struct regmap *map;
	struct clk_hw *hw;
	unsigned long freq;
	unsigned int mult, div;
	u32 val;
	int ret;
	int i;

	gemini_clk_data = kzalloc(struct_size(gemini_clk_data, hws,
					      GEMINI_NUM_CLKS),
				  GFP_KERNEL);
	if (!gemini_clk_data)
		return;
	gemini_clk_data->num = GEMINI_NUM_CLKS;

	/*
	 * This way all clock fetched before the platform device probes,
	 * except those we assign here for early use, will be deferred.
	 */
	for (i = 0; i < GEMINI_NUM_CLKS; i++)
		gemini_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);

	map = syscon_node_to_regmap(np);
	if (IS_ERR(map)) {
		pr_err("no syscon regmap\n");
		return;
	}
	/*
	 * We check that the regmap works on this very first access,
	 * but as this is an MMIO-backed regmap, subsequent regmap
	 * access is not going to fail and we skip error checks from
	 * this point.
	 */
	ret = regmap_read(map, GEMINI_GLOBAL_STATUS, &val);
	if (ret) {
		pr_err("failed to read global status register\n");
		return;
	}

	/*
	 * XTAL is the crystal oscillator, 60 or 30 MHz selected from
	 * strap pin E6
	 */
	if (val & PLL_OSC_SEL)
		freq = 30000000;
	else
		freq = 60000000;
	hw = clk_hw_register_fixed_rate(NULL, "xtal", NULL, 0, freq);
	pr_debug("main crystal @%lu MHz\n", freq / 1000000);

	/* VCO clock derived from the crystal */
	mult = 13 + ((val >> AHBSPEED_SHIFT) & AHBSPEED_MASK);
	div = 2;
	/* If we run on 30 MHz crystal we have to multiply with two */
	if (val & PLL_OSC_SEL)
		mult *= 2;
	hw = clk_hw_register_fixed_factor(NULL, "vco", "xtal", 0, mult, div);

	/* The AHB clock is always 1/3 of the VCO */
	hw = clk_hw_register_fixed_factor(NULL, "ahb", "vco", 0, 1, 3);
	gemini_clk_data->hws[GEMINI_CLK_AHB] = hw;

	/* The APB clock is always 1/6 of the AHB */
	hw = clk_hw_register_fixed_factor(NULL, "apb", "ahb", 0, 1, 6);
	gemini_clk_data->hws[GEMINI_CLK_APB] = hw;

	/* Register the clocks to be accessed by the device tree */
	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, gemini_clk_data);
}
CLK_OF_DECLARE_DRIVER(gemini_cc, "cortina,gemini-syscon", gemini_cc_init);
