/*
 * Copyright 2012 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs
 */
#include <subdev/clk.h>
#include "pll.h"

#include <core/device.h>
#include <subdev/bios.h>
#include <subdev/bios/pll.h>

struct nv40_clk_priv {
	struct nvkm_clk base;
	u32 ctrl;
	u32 npll_ctrl;
	u32 npll_coef;
	u32 spll;
};

static struct nvkm_domain
nv40_domain[] = {
	{ nv_clk_src_crystal, 0xff },
	{ nv_clk_src_href   , 0xff },
	{ nv_clk_src_core   , 0xff, 0, "core", 1000 },
	{ nv_clk_src_shader , 0xff, 0, "shader", 1000 },
	{ nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
	{ nv_clk_src_max }
};

static u32
read_pll_1(struct nv40_clk_priv *priv, u32 reg)
{
	u32 ctrl = nv_rd32(priv, reg + 0x00);
	int P = (ctrl & 0x00070000) >> 16;
	int N = (ctrl & 0x0000ff00) >> 8;
	int M = (ctrl & 0x000000ff) >> 0;
	u32 ref = 27000, clk = 0;

	if (ctrl & 0x80000000)
		clk = ref * N / M;

	return clk >> P;
}

static u32
read_pll_2(struct nv40_clk_priv *priv, u32 reg)
{
	u32 ctrl = nv_rd32(priv, reg + 0x00);
	u32 coef = nv_rd32(priv, reg + 0x04);
	int N2 = (coef & 0xff000000) >> 24;
	int M2 = (coef & 0x00ff0000) >> 16;
	int N1 = (coef & 0x0000ff00) >> 8;
	int M1 = (coef & 0x000000ff) >> 0;
	int P = (ctrl & 0x00070000) >> 16;
	u32 ref = 27000, clk = 0;

	if ((ctrl & 0x80000000) && M1) {
		clk = ref * N1 / M1;
		if ((ctrl & 0x40000100) == 0x40000000) {
			if (M2)
				clk = clk * N2 / M2;
			else
				clk = 0;
		}
	}

	return clk >> P;
}

static u32
read_clk(struct nv40_clk_priv *priv, u32 src)
{
	switch (src) {
	case 3:
		return read_pll_2(priv, 0x004000);
	case 2:
		return read_pll_1(priv, 0x004008);
	default:
		break;
	}

	return 0;
}

static int
nv40_clk_read(struct nvkm_clk *clk, enum nv_clk_src src)
{
	struct nv40_clk_priv *priv = (void *)clk;
	u32 mast = nv_rd32(priv, 0x00c040);

	switch (src) {
	case nv_clk_src_crystal:
		return nv_device(priv)->crystal;
	case nv_clk_src_href:
		return 100000; /*XXX: PCIE/AGP differ*/
	case nv_clk_src_core:
		return read_clk(priv, (mast & 0x00000003) >> 0);
	case nv_clk_src_shader:
		return read_clk(priv, (mast & 0x00000030) >> 4);
	case nv_clk_src_mem:
		return read_pll_2(priv, 0x4020);
	default:
		break;
	}

	nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
	return -EINVAL;
}

static int
nv40_clk_calc_pll(struct nv40_clk_priv *priv, u32 reg, u32 clk,
		  int *N1, int *M1, int *N2, int *M2, int *log2P)
{
	struct nvkm_bios *bios = nvkm_bios(priv);
	struct nvbios_pll pll;
	int ret;

	ret = nvbios_pll_parse(bios, reg, &pll);
	if (ret)
		return ret;

	if (clk < pll.vco1.max_freq)
		pll.vco2.max_freq = 0;

	ret = nv04_pll_calc(nv_subdev(priv), &pll, clk, N1, M1, N2, M2, log2P);
	if (ret == 0)
		return -ERANGE;

	return ret;
}

static int
nv40_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate)
{
	struct nv40_clk_priv *priv = (void *)clk;
	int gclk = cstate->domain[nv_clk_src_core];
	int sclk = cstate->domain[nv_clk_src_shader];
	int N1, M1, N2, M2, log2P;
	int ret;

	/* core/geometric clock */
	ret = nv40_clk_calc_pll(priv, 0x004000, gclk,
				&N1, &M1, &N2, &M2, &log2P);
	if (ret < 0)
		return ret;

	if (N2 == M2) {
		priv->npll_ctrl = 0x80000100 | (log2P << 16);
		priv->npll_coef = (N1 << 8) | M1;
	} else {
		priv->npll_ctrl = 0xc0000000 | (log2P << 16);
		priv->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
	}

	/* use the second pll for shader/rop clock, if it differs from core */
	if (sclk && sclk != gclk) {
		ret = nv40_clk_calc_pll(priv, 0x004008, sclk,
					&N1, &M1, NULL, NULL, &log2P);
		if (ret < 0)
			return ret;

		priv->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
		priv->ctrl = 0x00000223;
	} else {
		priv->spll = 0x00000000;
		priv->ctrl = 0x00000333;
	}

	return 0;
}

static int
nv40_clk_prog(struct nvkm_clk *clk)
{
	struct nv40_clk_priv *priv = (void *)clk;
	nv_mask(priv, 0x00c040, 0x00000333, 0x00000000);
	nv_wr32(priv, 0x004004, priv->npll_coef);
	nv_mask(priv, 0x004000, 0xc0070100, priv->npll_ctrl);
	nv_mask(priv, 0x004008, 0xc007ffff, priv->spll);
	mdelay(5);
	nv_mask(priv, 0x00c040, 0x00000333, priv->ctrl);
	return 0;
}

static void
nv40_clk_tidy(struct nvkm_clk *clk)
{
}

static int
nv40_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
	      struct nvkm_oclass *oclass, void *data, u32 size,
	      struct nvkm_object **pobject)
{
	struct nv40_clk_priv *priv;
	int ret;

	ret = nvkm_clk_create(parent, engine, oclass, nv40_domain,
			      NULL, 0, true, &priv);
	*pobject = nv_object(priv);
	if (ret)
		return ret;

	priv->base.pll_calc = nv04_clk_pll_calc;
	priv->base.pll_prog = nv04_clk_pll_prog;
	priv->base.read = nv40_clk_read;
	priv->base.calc = nv40_clk_calc;
	priv->base.prog = nv40_clk_prog;
	priv->base.tidy = nv40_clk_tidy;
	return 0;
}

struct nvkm_oclass
nv40_clk_oclass = {
	.handle = NV_SUBDEV(CLK, 0x40),
	.ofuncs = &(struct nvkm_ofuncs) {
		.ctor = nv40_clk_ctor,
		.dtor = _nvkm_clk_dtor,
		.init = _nvkm_clk_init,
		.fini = _nvkm_clk_fini,
	},
};
