rockchip/rk3399: Change PLL configuration to match Linux kernel

The Kevin project has been too smooth and boring for our tastes in the
last last few weeks, so we've decided to stir the pot a little bit and
reshuffle all our PLL settings at the last minute. The new settings
match exactly what the Linux kernel expects on boot, so it doesn't need
to reinitialize anything and risk a glitch.

Naturally, changing PLL rates will affect child clocks, so this patch
changes vop_aclk (192MHz -> 200MHz, 400MHz in the kernel), pmu_pclk
(99MHz -> 96.57MHz) and i2c0_src (198MHz -> 338MHz, leading to an
effective I2C0 change 399193Hz -> 398584Hz).

BRANCH=gru
BUG=chrome-os-partner:59139
TEST=Booted Kevin, sanity checking display and beep. Instrumented
rockchip_rk3399_pll_set_params() in the kernel and confirmed that GPLL,
PPLL and CPLL do not get reinitialized anymore (with additional kernel
patch to ignore frac divider when it's not used). Also confirmed that
/sys/kernel/debug/clk_summary now shows pclk_pmu_src 96571429 because
the kernel doesn't even bother to reinitialize the divisor.

Change-Id: Ib44d872a7b7f177fb2e60ccc6992f888835365eb
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 9b82056037be5a5aebf146784ffb246780013c96
Original-Change-Id: Ie112104035b01166217a8c5b5586972b4d7ca6ec
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/405785
Original-Commit-Ready: Xing Zheng <zhengxing@rock-chips.com>
Original-Tested-by: Xing Zheng <zhengxing@rock-chips.com>
Original-Reviewed-by: Xing Zheng <zhengxing@rock-chips.com>
Original-Reviewed-by: Douglas Anderson <dianders@chromium.org>
Reviewed-on: https://review.coreboot.org/17378
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
diff --git a/src/soc/rockchip/rk3399/clock.c b/src/soc/rockchip/rk3399/clock.c
index 2596853..ced78b3 100644
--- a/src/soc/rockchip/rk3399/clock.c
+++ b/src/soc/rockchip/rk3399/clock.c
@@ -40,12 +40,12 @@
 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2, .freq = hz};\
 	_Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
 			 OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
-			 #hz "Hz cannot be hit with PLL "\
+			 STRINGIFY(hz) " Hz cannot be hit with PLL "\
 			 "divisors on line " STRINGIFY(__LINE__))
 
-static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
-static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2, 2);
-static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 2, 2, 1);
+static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
+static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 3, 1);
+static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 3, 2, 1);
 
 static const struct pll_div apll_1512_cfg = PLL_DIVISORS(1512*MHz, 1, 1, 1);
 static const struct pll_div apll_600_cfg = PLL_DIVISORS(600*MHz, 1, 3, 1);
@@ -402,7 +402,8 @@
 
 	/* configure pmu pclk */
 	pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
-	assert((pclk_div + 1) * PMU_PCLK_HZ == PPLL_HZ && pclk_div <= 0x1f);
+	assert((unsigned int)(PPLL_HZ - (pclk_div + 1) * PMU_PCLK_HZ) <= pclk_div
+	       && pclk_div <= 0x1f);
 	write32(&pmucru_ptr->pmucru_clksel[0],
 		RK_CLRSETBITS(PMU_PCLK_DIV_CON_MASK << PMU_PCLK_DIV_CON_SHIFT,
 			      pclk_div << PMU_PCLK_DIV_CON_SHIFT));
@@ -631,15 +632,20 @@
 		RK_CLRSETBITS(I2C_DIV_CON_MASK << I2C ##bus## _DIV_CON_SHIFT, \
 			      (clk_div - 1) << I2C ##bus## _DIV_CON_SHIFT)
 
-static void rkclk_configure_i2c(unsigned int bus, unsigned int hz)
+uint32_t rkclk_i2c_clock_for_bus(unsigned int bus)
 {
-	int src_clk_div;
-	int pll;
+	int src_clk_div, pll, freq;
 
-	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
-	pll = (bus == 0 || bus == 4 || bus == 8) ? PPLL_HZ : GPLL_HZ;
-	src_clk_div = pll / hz;
-	assert((src_clk_div - 1 <= 127) && (src_clk_div * hz == pll));
+	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll */
+	if (bus == 0 || bus == 4 || bus == 8) {
+		pll = PPLL_HZ;
+		freq = 338*MHz;
+	} else {
+		pll = GPLL_HZ;
+		freq = 198*MHz;
+	}
+	src_clk_div = pll / freq;
+	assert((src_clk_div - 1 <= 127) && (src_clk_div * freq == pll));
 
 	switch (bus) {
 	case 0:
@@ -679,15 +685,8 @@
 			PMU_I2C_CLK_REG_VALUE(8, src_clk_div));
 		break;
 	default:
-		printk(BIOS_ERR, "do not support this i2c bus\n");
+		die("unknown i2c bus\n");
 	}
-}
-
-uint32_t rkclk_i2c_clock_for_bus(unsigned bus)
-{
-	uint32_t freq = 198 * 1000 * 1000;
-
-	rkclk_configure_i2c(bus, freq);
 
 	return freq;
 }
@@ -724,7 +723,7 @@
 	v = clk_gcd(CPLL_HZ, hz);
 	n = (CPLL_HZ / v) & (0xffff);
 	d = (hz / v) & (0xffff);
-	assert(hz == CPLL_HZ / n * d);
+	assert(hz == (u64)CPLL_HZ * d / n);
 	write32(&cru_ptr->clksel_con[96], d << 16 | n);
 
 	/**