[coreboot-gerrit] New patch to review for coreboot: 61c06e8 rockchip: support pwm regulator

Aaron Durbin (adurbin@google.com) gerrit at coreboot.org
Thu Apr 2 20:47:44 CEST 2015


Aaron Durbin (adurbin at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9240

-gerrit

commit 61c06e88ff4ee590f24756cf85d2145dffb5f088
Author: huang lin <hl at rock-chips.com>
Date:   Thu Sep 25 16:33:38 2014 +0800

    rockchip: support pwm regulator
    
    BUG=None
    TEST=Boot Veyron Pinky and test the VDD_LOG
    
    Original-Change-Id: Ie2eef918e04ba0e13879e915b0b0bef44aef550e
    Original-Signed-off-by: huang lin <hl at rock-chips.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/219753
    Original-Reviewed-by: Julius Werner <jwerner at chromium.org>
    Original-Commit-Queue: Julius Werner <jwerner at chromium.org>
    
    Change-Id: I444b47564d90b3480b351fdd8460e5b94e71927c
    (cherry picked from commit 4491d9c4037161fd8c4cc40856167bf73182fda6)
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/mainboard/google/veyron_pinky/romstage.c | 23 +++++++
 src/soc/rockchip/rk3288/Makefile.inc         |  2 +
 src/soc/rockchip/rk3288/clock.c              | 95 ++++++++++++++++++++++++++--
 src/soc/rockchip/rk3288/clock.h              |  8 +++
 src/soc/rockchip/rk3288/grf.h                |  2 +
 src/soc/rockchip/rk3288/pwm.c                | 90 ++++++++++++++++++++++++++
 src/soc/rockchip/rk3288/pwm.h                | 26 ++++++++
 7 files changed, 240 insertions(+), 6 deletions(-)

diff --git a/src/mainboard/google/veyron_pinky/romstage.c b/src/mainboard/google/veyron_pinky/romstage.c
index 31317a0..f972ee2 100644
--- a/src/mainboard/google/veyron_pinky/romstage.c
+++ b/src/mainboard/google/veyron_pinky/romstage.c
@@ -28,11 +28,32 @@
 #include <timestamp.h>
 #include <arch/cache.h>
 #include <arch/exception.h>
+#include <stdlib.h>
+#include <assert.h>
 #include <vendorcode/google/chromeos/chromeos.h>
 #include <soc/rockchip/rk3288/sdram.h>
 #include <soc/rockchip/rk3288/clock.h>
+#include <soc/rockchip/rk3288/pwm.h>
+#include <soc/rockchip/rk3288/grf.h>
 #include "timer.h"
 
+static void regulate_vdd_log(unsigned int mv)
+{
+	unsigned int duty_ns;
+	const u32 period_ns = 2000;	/* pwm period: 2000ns */
+	const u32 max_regulator_mv = 1350;	/* 1.35V */
+	const u32 min_regulator_mv = 870;	/* 0.87V */
+
+	writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1);
+
+	assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv));
+
+	duty_ns = (max_regulator_mv - mv) * period_ns /
+			(max_regulator_mv - min_regulator_mv);
+
+	pwm_init(1, period_ns, duty_ns);
+}
+
 void main(void)
 {
 #if CONFIG_COLLECT_TIMESTAMPS
@@ -49,6 +70,8 @@ void main(void)
 
 	console_init();
 
+	/* vdd_log 1200mv is enough for ddr run 666Mhz */
+	regulate_vdd_log(1200);
 #if CONFIG_COLLECT_TIMESTAMPS
 	before_dram_time = timestamp_get();
 #endif
diff --git a/src/soc/rockchip/rk3288/Makefile.inc b/src/soc/rockchip/rk3288/Makefile.inc
index 095c555..37abe57 100644
--- a/src/soc/rockchip/rk3288/Makefile.inc
+++ b/src/soc/rockchip/rk3288/Makefile.inc
@@ -50,6 +50,7 @@ romstage-y += gpio.c
 romstage-y += spi.c
 romstage-y += media.c
 romstage-y += sdram.c
+romstage-y += pwm.c
 
 ramstage-y += soc.c
 ramstage-y += cbmem.c
@@ -61,6 +62,7 @@ ramstage-y += spi.c
 ramstage-y += gpio.c
 ramstage-y += media.c
 ramstage-y += rk808.c
+ramstage-y += pwm.c
 ramstage-$(CONFIG_DRIVERS_UART) += uart.c
 
 $(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf
diff --git a/src/soc/rockchip/rk3288/clock.c b/src/soc/rockchip/rk3288/clock.c
index 6d62628..d106245 100644
--- a/src/soc/rockchip/rk3288/clock.c
+++ b/src/soc/rockchip/rk3288/clock.c
@@ -109,6 +109,32 @@ static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 4);
 /* m0 core axi clock div: clk = clk_src / (div_con + 1) */
 #define M0_DIV_MSK	(0xF)
 
+/*******************CLKSEL1 BITS***************************/
+/* pd bus clk pll sel: codec or general */
+#define PD_BUS_SEL_PLL_MSK	(1 << 15)
+#define PD_BUS_SEL_CPLL	(0 << 15)
+#define PD_BUS_SEL_GPLL	(1 << 15)
+
+/* pd bus pclk div:
+ * pclk = pd_bus_aclk /(div + 1)
+ */
+#define PD_BUS_PCLK_DIV_SHIFT	(12)
+#define PD_BUS_PCLK_DIV_MSK	(0x7 << 12)
+
+/* pd bus hclk div:
+ * aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1
+ */
+#define PD_BUS_HCLK_DIV_SHIFT	(8)
+#define PD_BUS_HCLK_DIV_MSK	(0x3 << 8)
+
+/* pd bus aclk div:
+ * pd_bus_aclk = pd_bus_src_clk /(div0 * div1)
+ */
+#define PD_BUS_ACLK_DIV0_SHIFT	(3)
+#define PD_BUS_ACLK_DIV0_MASK	(0x1f << 3)
+#define PD_BUS_ACLK_DIV1_SHIFT	(0)
+#define PD_BUS_ACLK_DIV1_MASK	(0x7 << 0)
+
 /*******************CLKSEL10 BITS***************************/
 /* peripheral bus clk pll sel: codec or general */
 #define PERI_SEL_PLL_MSK	(1 << 15)
@@ -132,6 +158,7 @@ static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 4);
  * periph_clk_src / (peri_aclk_div_con + 1)
  */
 #define PERI_ACLK_DIV_MSK	(0x1F)
+#define PERI_ACLK_DIV_SHIFT	(0)
 
 /*******************CLKSEL37 BITS***************************/
 #define L2_DIV_MSK	(0x7)
@@ -185,8 +212,28 @@ static int rkclk_set_pll(u32 *pll_con, const struct pll_div *pll_div_cfg)
 	return 0;
 }
 
+/*
+    TODO:
+    it should be replaced by lib.h function
+   'unsigned long log2(unsigned long x)'
+*/
+static unsigned int log2(unsigned int value)
+{
+	unsigned int div = 0;
+
+	while (value != 1) {
+		div++;
+		value = ALIGN_UP(value, 2) / 2;
+	}
+	return div;
+}
+
 void rkclk_init(void)
 {
+	u32 aclk_div;
+	u32 hclk_div;
+	u32 pclk_div;
+
 	/* pll enter slow-mode */
 	writel(RK_CLRSETBITS(APLL_MODE_MSK, APLL_MODE_SLOW)
 		| RK_CLRSETBITS(GPLL_MODE_MSK, GPLL_MODE_SLOW)
@@ -231,15 +278,51 @@ void rkclk_init(void)
 		&cru_ptr->cru_clksel_con[37]);
 
 	/*
+	 * pd_bus clock pll source selection and
+	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+	 */
+	aclk_div = GPLL_HZ / PD_BUS_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PD_BUS_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+	hclk_div = PD_BUS_ACLK_HZ / PD_BUS_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PD_BUS_HCLK_HZ ==
+		PD_BUS_ACLK_HZ && (hclk_div < 0x4) && (hclk_div != 0x2));
+
+	pclk_div = PD_BUS_ACLK_HZ / PD_BUS_PCLK_HZ - 1;
+	assert((pclk_div + 1) * PD_BUS_PCLK_HZ ==
+		PD_BUS_ACLK_HZ && pclk_div < 0x7);
+
+	writel(RK_SETBITS(PD_BUS_SEL_GPLL)
+		| RK_CLRSETBITS(PD_BUS_PCLK_DIV_MSK,
+		pclk_div << PD_BUS_PCLK_DIV_SHIFT)
+		| RK_CLRSETBITS(PD_BUS_HCLK_DIV_MSK,
+		hclk_div << PD_BUS_HCLK_DIV_SHIFT)
+		| RK_CLRSETBITS(PD_BUS_ACLK_DIV0_MASK,
+		aclk_div << PD_BUS_ACLK_DIV0_SHIFT)
+		| RK_CLRSETBITS(PD_BUS_ACLK_DIV1_MASK, 0 << 0),
+		&cru_ptr->cru_clksel_con[1]);
+
+	/*
 	 * peri clock pll source selection and
 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
-	 * peri clock select gpll, gpll clk = 594MHz
-	 * aclk = 148.5MHz, hclk = 148.5Mhz, pclk = 74.25MHz
 	 */
-	writel(RK_SETBITS(PERI_SEL_PLL_MSK)
-		| RK_CLRSETBITS(PERI_PCLK_DIV_MSK, 1 << PERI_PCLK_DIV_SHIFT)
-		| RK_CLRSETBITS(PERI_HCLK_DIV_MSK, 0 << PERI_HCLK_DIV_SHIFT)
-		| RK_CLRSETBITS(PERI_ACLK_DIV_MSK, 3 << 0),
+	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	hclk_div = log2(PERI_ACLK_HZ / PERI_HCLK_HZ);
+	assert((1 << hclk_div) * PERI_HCLK_HZ ==
+		PERI_ACLK_HZ && (hclk_div < 0x4));
+
+	pclk_div = log2(PERI_ACLK_HZ / PERI_PCLK_HZ);
+	assert((1 << pclk_div) * PERI_PCLK_HZ ==
+		PERI_ACLK_HZ && (pclk_div < 0x4));
+
+	writel(RK_SETBITS(PERI_SEL_GPLL)
+		| RK_CLRSETBITS(PERI_PCLK_DIV_MSK,
+		pclk_div << PERI_PCLK_DIV_SHIFT)
+		| RK_CLRSETBITS(PERI_HCLK_DIV_MSK,
+		hclk_div << PERI_HCLK_DIV_SHIFT)
+		| RK_CLRSETBITS(PERI_ACLK_DIV_MSK,
+		aclk_div << PERI_ACLK_DIV_SHIFT),
 		&cru_ptr->cru_clksel_con[10]);
 
 	/* PLL enter normal-mode */
diff --git a/src/soc/rockchip/rk3288/clock.h b/src/soc/rockchip/rk3288/clock.h
index 4613c72..c28d181 100644
--- a/src/soc/rockchip/rk3288/clock.h
+++ b/src/soc/rockchip/rk3288/clock.h
@@ -26,6 +26,14 @@
 #define GPLL_HZ		594000000
 #define CPLL_HZ		384000000
 
+#define PD_BUS_ACLK_HZ	148500000
+#define PD_BUS_HCLK_HZ	148500000
+#define PD_BUS_PCLK_HZ	74250000
+
+#define PERI_ACLK_HZ	148500000
+#define PERI_HCLK_HZ	148500000
+#define PERI_PCLK_HZ	74250000
+
 void rkclk_init(void);
 void rkclk_configure_spi(unsigned int bus, unsigned int hz);
 void rkclk_ddr_reset(u32 ch, u32 ctl, u32 phy);
diff --git a/src/soc/rockchip/rk3288/grf.h b/src/soc/rockchip/rk3288/grf.h
index e0dfc02..e84359b 100644
--- a/src/soc/rockchip/rk3288/grf.h
+++ b/src/soc/rockchip/rk3288/grf.h
@@ -87,6 +87,7 @@ struct rk3288_grf_regs {
 	union {
 		u32 gpio7a_iomux;
 		u32 iomux_pwm0;
+		u32 iomux_pwm1;
 	};
 	u32 gpio7b_iomux;
 	union {
@@ -215,4 +216,5 @@ static struct rk3288_sgrf_regs * const rk3288_sgrf = (void *)GRF_SECURE_BASE;
 					       2 << 2 | 2 << 0)
 #define IOMUX_EMMCPWREN  RK_CLRSETBITS(0x3 << 2, 0x2 << 2)
 #define IOMUX_EMMCCMD	 RK_CLRSETBITS(0x3f, 2 << 4 | 2 << 2 | 2 << 0)
+#define IOMUX_PWM1	RK_SETBITS(1 << 2)
 #endif
diff --git a/src/soc/rockchip/rk3288/pwm.c b/src/soc/rockchip/rk3288/pwm.c
new file mode 100644
index 0000000..7f659f2
--- /dev/null
+++ b/src/soc/rockchip/rk3288/pwm.c
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Rockchip Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <timer.h>
+#include <delay.h>
+
+#include "addressmap.h"
+#include "grf.h"
+#include "soc.h"
+#include "pwm.h"
+#include "clock.h"
+
+struct pwm_ctl {
+	u32	pwm_cnt;
+	u32	pwm_period_hpr;
+	u32	pwm_duty_lpr;
+	u32	pwm_ctrl;
+};
+
+struct rk3288_pwm_regs {
+	struct pwm_ctl pwm[4];
+	u32	intsts;
+	u32	int_en;
+};
+check_member(rk3288_pwm_regs, int_en, 0x44);
+
+#define RK_PWM_DISABLE                  (0 << 0)
+#define RK_PWM_ENABLE                   (1 << 0)
+
+
+#define PWM_ONE_SHOT                    (0 << 1)
+#define PWM_CONTINUOUS                  (1 << 1)
+#define RK_PWM_CAPTURE                  (1 << 2)
+
+#define PWM_DUTY_POSTIVE                (1 << 3)
+#define PWM_DUTY_NEGATIVE               (0 << 3)
+
+#define PWM_INACTIVE_POSTIVE            (1 << 4)
+#define PWM_INACTIVE_NEGATIVE           (0 << 4)
+
+#define PWM_OUTPUT_LEFT                 (0 << 5)
+#define PWM_OUTPUT_CENTER               (1 << 5)
+
+#define PWM_LP_ENABLE                   (1 << 8)
+#define PWM_LP_DISABLE                  (0 << 8)
+
+#define PWM_SEL_SCALE_CLK			(1 << 9)
+#define PWM_SEL_SRC_CLK				(0 << 9)
+
+struct rk3288_pwm_regs *rk3288_pwm = (void *)RK_PWM0123_BASE;
+
+void pwm_init(u32 id, u32 period_ns, u32 duty_ns)
+{
+	unsigned long period, duty;
+
+	/*use rk pwm*/
+	writel(RK_SETBITS(1 << 0), &rk3288_grf->soc_con2);
+
+	writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE |
+		PWM_CONTINUOUS | PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE |
+		RK_PWM_DISABLE,
+		&rk3288_pwm->pwm[id].pwm_ctrl);
+
+	period = (PD_BUS_PCLK_HZ / 1000) * period_ns / USECS_PER_SEC;
+	duty = (PD_BUS_PCLK_HZ / 1000) * duty_ns / USECS_PER_SEC;
+
+	writel(period, &rk3288_pwm->pwm[id].pwm_period_hpr);
+	writel(duty, &rk3288_pwm->pwm[id].pwm_duty_lpr);
+	setbits_le32(&rk3288_pwm->pwm[id].pwm_ctrl, RK_PWM_ENABLE);
+}
diff --git a/src/soc/rockchip/rk3288/pwm.h b/src/soc/rockchip/rk3288/pwm.h
new file mode 100644
index 0000000..168d8a7
--- /dev/null
+++ b/src/soc/rockchip/rk3288/pwm.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Rockchip Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SOC_ROCKCHIP_RK3288_PWM_H__
+#define __SOC_ROCKCHIP_RK3288_PWM_H__
+
+void pwm_init(u32 id, u32 period_ns, u32 duty_ns);
+
+#endif
+



More information about the coreboot-gerrit mailing list