/*
 * Clock drivers for Qualcomm APQ8016
 *
 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
 *
 * Based on Little Kernel driver, simplified
 *
 * SPDX-License-Identifier:	BSD-3-Clause
 */

#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <errno.h>
#include <asm/io.h>
#include <linux/bitops.h>

/* GPLL0 clock control registers */
#define GPLL0_STATUS        0x2101C
#define GPLL0_STATUS_ACTIVE BIT(17)

#define APCS_GPLL_ENA_VOTE  0x45000
#define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0)

/* vote reg for blsp1 clock */
#define APCS_CLOCK_BRANCH_ENA_VOTE  0x45004
#define APCS_CLOCK_BRANCH_ENA_VOTE_BLSP1 BIT(10)

/* SDC(n) clock control registers; n=1,2 */

/* block control register */
#define SDCC_BCR(n)                 ((n * 0x1000) + 0x41000)
/* cmd */
#define SDCC_CMD_RCGR(n)            ((n * 0x1000) + 0x41004)
/* cfg */
#define SDCC_CFG_RCGR(n)            ((n * 0x1000) + 0x41008)
/* m */
#define SDCC_M(n)                   ((n * 0x1000) + 0x4100C)
/* n */
#define SDCC_N(n)                   ((n * 0x1000) + 0x41010)
/* d */
#define SDCC_D(n)                   ((n * 0x1000) + 0x41014)
/* branch control */
#define SDCC_APPS_CBCR(n)           ((n * 0x1000) + 0x41018)
#define SDCC_AHB_CBCR(n)            ((n * 0x1000) + 0x4101C)

/* BLSP1 AHB clock (root clock for BLSP) */
#define BLSP1_AHB_CBCR              0x1008

/* Uart clock control registers */
#define BLSP1_UART2_BCR             0x3028
#define BLSP1_UART2_APPS_CBCR       0x302C
#define BLSP1_UART2_APPS_CMD_RCGR   0x3034
#define BLSP1_UART2_APPS_CFG_RCGR   0x3038
#define BLSP1_UART2_APPS_M          0x303C
#define BLSP1_UART2_APPS_N          0x3040
#define BLSP1_UART2_APPS_D          0x3044

/* CBCR register fields */
#define CBCR_BRANCH_ENABLE_BIT  BIT(0)
#define CBCR_BRANCH_OFF_BIT     BIT(31)

struct msm_clk_priv {
	phys_addr_t base;
};

/* Enable clock controlled by CBC soft macro */
static void clk_enable_cbc(phys_addr_t cbcr)
{
	setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT);

	while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
		;
}

/* clock has 800MHz */
static void clk_enable_gpll0(phys_addr_t base)
{
	if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE)
		return; /* clock already enabled */

	setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0);

	while ((readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) == 0)
		;
}

#define APPS_CMD_RGCR_UPDATE BIT(0)

/* Update clock command via CMD_RGCR */
static void clk_bcr_update(phys_addr_t apps_cmd_rgcr)
{
	setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE);

	/* Wait for frequency to be updated. */
	while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE)
		;
}

struct bcr_regs {
	uintptr_t cfg_rcgr;
	uintptr_t cmd_rcgr;
	uintptr_t M;
	uintptr_t N;
	uintptr_t D;
};

/* RCGR_CFG register fields */
#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */

/* sources */
#define CFG_CLK_SRC_CXO   (0 << 8)
#define CFG_CLK_SRC_GPLL0 (1 << 8)
#define CFG_CLK_SRC_MASK  (7 << 8)

/* Mask for supported fields */
#define CFG_MASK 0x3FFF

#define CFG_DIVIDER_MASK 0x1F

/* root set rate for clocks with half integer and MND divider */
static void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
				 int div, int m, int n, int source)
{
	uint32_t cfg;
	/* M value for MND divider. */
	uint32_t m_val = m;
	/* NOT(N-M) value for MND divider. */
	uint32_t n_val = ~((n)-(m)) * !!(n);
	/* NOT 2D value for MND divider. */
	uint32_t d_val = ~(n);

	/* Program MND values */
	writel(m_val, base + regs->M);
	writel(n_val, base + regs->N);
	writel(d_val, base + regs->D);

	/* setup src select and divider */
	cfg  = readl(base + regs->cfg_rcgr);
	cfg &= ~CFG_MASK;
	cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */

	/* Set the divider; HW permits fraction dividers (+0.5), but
	   for simplicity, we will support integers only */
	if (div)
		cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;

	if (n_val)
		cfg |= CFG_MODE_DUAL_EDGE;

	writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */

	/* Inform h/w to start using the new config. */
	clk_bcr_update(base + regs->cmd_rcgr);
}

static const struct bcr_regs sdc_regs[] = {
	{
	.cfg_rcgr = SDCC_CFG_RCGR(1),
	.cmd_rcgr = SDCC_CMD_RCGR(1),
	.M = SDCC_M(1),
	.N = SDCC_N(1),
	.D = SDCC_D(1),
	},
	{
	.cfg_rcgr = SDCC_CFG_RCGR(2),
	.cmd_rcgr = SDCC_CMD_RCGR(2),
	.M = SDCC_M(2),
	.N = SDCC_N(2),
	.D = SDCC_D(2),
	}
};

/* Init clock for SDHCI controller */
static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
{
	int div = 8; /* 100MHz default */

	if (rate == 200000000)
		div = 4;

	clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot));
	/* 800Mhz/div, gpll0 */
	clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0,
			     CFG_CLK_SRC_GPLL0);
	clk_enable_gpll0(priv->base);
	clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot));

	return rate;
}

static const struct bcr_regs uart2_regs = {
	.cfg_rcgr = BLSP1_UART2_APPS_CFG_RCGR,
	.cmd_rcgr = BLSP1_UART2_APPS_CMD_RCGR,
	.M = BLSP1_UART2_APPS_M,
	.N = BLSP1_UART2_APPS_N,
	.D = BLSP1_UART2_APPS_D,
};

/* Init UART clock, 115200 */
static int clk_init_uart(struct msm_clk_priv *priv)
{
	/* Enable iface clk */
	clk_enable_cbc(priv->base + BLSP1_AHB_CBCR);
	/* 7372800 uart block clock @ GPLL0 */
	clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625,
			     CFG_CLK_SRC_GPLL0);
	clk_enable_gpll0(priv->base);
	/* Enable core clk */
	clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR);

	return 0;
}

ulong msm_set_rate(struct clk *clk, ulong rate)
{
	struct msm_clk_priv *priv = dev_get_priv(clk->dev);

	switch (clk->id) {
	case 0: /* SDC1 */
		return clk_init_sdc(priv, 0, rate);
		break;
	case 1: /* SDC2 */
		return clk_init_sdc(priv, 1, rate);
		break;
	case 4: /* UART2 */
		return clk_init_uart(priv);
		break;
	default:
		return 0;
	}
}

static int msm_clk_probe(struct udevice *dev)
{
	struct msm_clk_priv *priv = dev_get_priv(dev);

	priv->base = dev_get_addr(dev);
	if (priv->base == FDT_ADDR_T_NONE)
		return -EINVAL;

	return 0;
}

static struct clk_ops msm_clk_ops = {
	.set_rate = msm_set_rate,
};

static const struct udevice_id msm_clk_ids[] = {
	{ .compatible = "qcom,gcc-msm8916" },
	{ .compatible = "qcom,gcc-apq8016" },
	{ }
};

U_BOOT_DRIVER(clk_msm) = {
	.name		= "clk_msm",
	.id		= UCLASS_CLK,
	.of_match	= msm_clk_ids,
	.ops		= &msm_clk_ops,
	.priv_auto_alloc_size = sizeof(struct msm_clk_priv),
	.probe		= msm_clk_probe,
};
