[coreboot-gerrit] Change in coreboot[master]: sifive/fu540: PLL + clock initialization

Philipp Hug (Code Review) gerrit at coreboot.org
Thu Jul 12 00:17:20 CEST 2018


Philipp Hug has uploaded this change for review. ( https://review.coreboot.org/27439


Change subject: sifive/fu540: PLL + clock initialization
......................................................................

sifive/fu540: PLL + clock initialization

Change-Id: Iba0669e08940e373aaf42cbba3a1ceffd68a4f52
---
A src/soc/sifive/fu540/clock.c
A src/soc/sifive/fu540/include/soc/clock.h
2 files changed, 198 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/39/27439/1

diff --git a/src/soc/sifive/fu540/clock.c b/src/soc/sifive/fu540/clock.c
new file mode 100644
index 0000000..1fa850c
--- /dev/null
+++ b/src/soc/sifive/fu540/clock.c
@@ -0,0 +1,174 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 Philipp Hug <philipp at hug.cx>
+ *
+ * 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.
+ */
+
+#include <arch/barrier.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <soc/clock.h>
+#include <soc/addressmap.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct prci_ctlr {
+	u32 hfxosccfg;		/* offset 0x00 */
+	u32 corepllcfg0;	/* offset 0x04 */
+	u32 reserved08;		/* offset 0x08 */
+	u32 ddrpllcfg0;		/* offset 0x0c */
+	u32 ddrpllcfg1;		/* offset 0x10 */
+	u32 reserved14;		/* offset 0x14 */
+	u32 reserved18;		/* offset 0x18 */
+	u32 gemgxlpllcfg0;	/* offset 0x1c */
+	u32 gemgxlpllcfg1;	/* offset 0x20 */
+	u32 coreclksel;		/* offset 0x24 */
+	u32 devicesresetreg;	/* offset 0x28 */
+};
+
+static struct prci_ctlr *prci = (void *)FU540_PRCI;
+
+#define PRCI_CORECLK_MASK 1
+#define PRCI_CORECLK_CORE_PLL 0
+#define PRCI_CORECLK_HFCLK 1
+
+#define PRCI_COREPLLCFG0_LOCK (1u << 31)
+#define PRCI_COREPLLCFG0_DIVR_SHIFT 0
+#define PRCI_COREPLLCFG0_DIVF_SHIFT 6
+#define PRCI_COREPLLCFG0_DIVQ_SHIFT 15
+#define PRCI_COREPLLCFG0_RANGE_SHIFT 18
+#define PRCI_COREPLLCFG0_BYPASS_SHIFT 24
+#define PRCI_COREPLLCFG0_DIVR_MASK (0x03f << PRCI_COREPLLCFG0_DIVR_SHIFT)
+#define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
+#define PRCI_COREPLLCFG0_DIVQ_MASK (0x007 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
+#define PRCI_COREPLLCFG0_RANGE_MASK (0x07 << PRCI_COREPLLCFG0_RANGE_SHIFT)
+#define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
+
+#define PRCI_DDRPLLCFG0_LOCK (1u << 31)
+#define PRCI_DDRPLLCFG0_DIVR_SHIFT 0
+#define PRCI_DDRPLLCFG0_DIVF_SHIFT 6
+#define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15
+#define PRCI_DDRPLLCFG0_RANGE_SHIFT 18
+#define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24
+#define PRCI_DDRPLLCFG0_DIVR_MASK (0x03f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
+#define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
+#define PRCI_DDRPLLCFG0_DIVQ_MASK (0x007 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
+#define PRCI_DDRPLLCFG0_RANGE_MASK (0x07 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
+#define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
+#define PRCI_DDRPLLCFG1_MASK (1u << 31)
+
+#define PRCI_CORECLK_DIVR 0
+#define PRCI_CORECLK_DIVF 59
+#define PRCI_CORECLK_DIVQ 2
+#define PRCI_CORECLK_RANGE 4
+
+#define PRCI_DDRCLK_DIVR 0
+#define PRCI_DDRCLK_DIVF 59
+#define PRCI_DDRCLK_DIVQ 5
+#define PRCI_DDRCLK_RANGE 4
+
+#define PRCI_RESET_DDR_CTRL_RST_N (1 << 0)
+#define PRCI_RESET_DDR_AXI_RST_N  (1 << 1)
+#define PRCI_RESET_DDR_AHB_RST_N  (1 << 2)
+#define PRCI_RESET_DDR_PHY_RST_N  (1 << 3)
+#define PRCI_RESET_GEMGXL_RST_N   (1 << 5)
+
+// 33.33 Mhz after reset
+#define FU540_BASE_FQY 33330
+
+static void init_pll_core(void)
+{
+        clrsetbits_le32(&prci->coreclksel, PRCI_CORECLK_MASK, PRCI_CORECLK_HFCLK);
+
+	u32 c = read32(&prci->corepllcfg0);
+	clrsetbits_le32(&c, PRCI_COREPLLCFG0_DIVR_MASK
+		| PRCI_COREPLLCFG0_DIVF_MASK | PRCI_COREPLLCFG0_DIVQ_MASK
+		| PRCI_COREPLLCFG0_RANGE_MASK | PRCI_COREPLLCFG0_BYPASS_MASK,
+		(PRCI_CORECLK_DIVR << PRCI_COREPLLCFG0_DIVR_SHIFT)
+		& (PRCI_CORECLK_DIVF << PRCI_COREPLLCFG0_DIVF_SHIFT)
+		& (PRCI_CORECLK_DIVQ << PRCI_COREPLLCFG0_DIVQ_SHIFT)
+		& (PRCI_CORECLK_RANGE << PRCI_COREPLLCFG0_RANGE_SHIFT));
+	write32(&prci->corepllcfg0, c);
+
+	// wait for PLL lock
+        while (!(read32(&prci->corepllcfg0) & PRCI_COREPLLCFG0_LOCK))
+        ; /* TODO: implement a timeout */
+
+        clrsetbits_le32(&prci->coreclksel, PRCI_CORECLK_MASK, PRCI_CORECLK_CORE_PLL);
+}
+
+static void init_pll_ddr(void)
+{
+	u32 cfg1 = read32(&prci->ddrpllcfg1);
+        clrbits_le32(&cfg1, PRCI_DDRPLLCFG1_MASK);
+	write32(&prci->ddrpllcfg1, cfg1);
+
+	u32 c = read32(&prci->ddrpllcfg0);
+	clrsetbits_le32(&c, PRCI_DDRPLLCFG0_DIVR_MASK
+		| PRCI_DDRPLLCFG0_DIVF_MASK | PRCI_DDRPLLCFG0_DIVQ_MASK
+		| PRCI_DDRPLLCFG0_RANGE_MASK | PRCI_DDRPLLCFG0_BYPASS_MASK,
+		(PRCI_DDRCLK_DIVR << PRCI_DDRPLLCFG0_DIVR_SHIFT)
+		& (PRCI_DDRCLK_DIVF << PRCI_DDRPLLCFG0_DIVF_SHIFT)
+		& (PRCI_DDRCLK_DIVQ << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
+		& (PRCI_DDRCLK_RANGE << PRCI_DDRPLLCFG0_RANGE_SHIFT));
+	write32(&prci->ddrpllcfg0, c);
+
+	// wait for PLL lock
+        while (!(read32(&prci->ddrpllcfg0) & PRCI_DDRPLLCFG0_LOCK))
+        ; /* TODO: implement a timeout */
+
+        setbits_le32(&cfg1, PRCI_DDRPLLCFG1_MASK);
+	write32(&prci->ddrpllcfg1, cfg1);
+}
+
+int clock_get_coreclk_khz(void)
+{
+	if (read32(&prci->coreclksel) & PRCI_CORECLK_MASK) {
+		return FU540_BASE_FQY;
+	} else {
+		u32 cfg  = read32(&prci->corepllcfg0);
+		u32 divr = (cfg & PRCI_COREPLLCFG0_DIVR_MASK)
+			>> PRCI_COREPLLCFG0_DIVR_SHIFT;
+		u32 divf = (cfg & PRCI_COREPLLCFG0_DIVF_MASK)
+			>> PRCI_COREPLLCFG0_DIVF_SHIFT;
+		u32 divq = (cfg & PRCI_COREPLLCFG0_DIVQ_MASK)
+			>> PRCI_COREPLLCFG0_DIVQ_SHIFT;
+
+		printk(BIOS_SPEW, "clk: r=%d f=%d q=%d\n", divr, divf, divq);
+		return FU540_BASE_FQY
+			* 2 * (divf + 1)
+			/ (divr + 1)
+			/ (1 << divq);
+	}
+}
+
+static void my_sdram_init(void)
+{
+	setbits_le32(&prci->devicesresetreg, PRCI_RESET_DDR_CTRL_RST_N);
+	mb();
+	setbits_le32(&prci->devicesresetreg, PRCI_RESET_DDR_AXI_RST_N);
+	setbits_le32(&prci->devicesresetreg, PRCI_RESET_DDR_AHB_RST_N);
+	setbits_le32(&prci->devicesresetreg, PRCI_RESET_DDR_PHY_RST_N);
+	for(int i = 0; i<256; i++)
+		mb();
+}
+
+void clock_init(void)
+{
+	init_pll_core();
+
+	// put all peripherals in reset
+	write32(&prci->devicesresetreg, 0);
+	init_pll_ddr();
+
+	my_sdram_init();
+}
diff --git a/src/soc/sifive/fu540/include/soc/clock.h b/src/soc/sifive/fu540/include/soc/clock.h
new file mode 100644
index 0000000..cc868e3
--- /dev/null
+++ b/src/soc/sifive/fu540/include/soc/clock.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 Philipp Hug <philipp at hug.cx>
+ *
+ * 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.
+ */
+
+#ifndef __SOC_SIFIVE_HIFIVE_U_CLOCK_H__
+#define __SOC_SIFIVE_HIFIVE_U_CLOCK_H__
+
+#define PRCI_CORECLKSEL_CORECLKSEL 1
+
+void clock_init(void);
+int clock_get_coreclk_khz(void);
+
+#endif /* __SOC_SIFIVE_HIFIFE_U_CLOCK_H__ */

-- 
To view, visit https://review.coreboot.org/27439
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iba0669e08940e373aaf42cbba3a1ceffd68a4f52
Gerrit-Change-Number: 27439
Gerrit-PatchSet: 1
Gerrit-Owner: Philipp Hug <philipp at hug.cx>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180711/4f8c67b3/attachment-0001.html>


More information about the coreboot-gerrit mailing list