[coreboot-gerrit] Patch set updated for coreboot: 320eed0 urara: Configure clocks and MFIOs

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Tue Apr 14 12:07:32 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9662

-gerrit

commit 320eed09bd2c555d63e25492cc828985bb2384d3
Author: Ionela Voinescu <ionela.voinescu at imgtec.com>
Date:   Sun Jan 18 22:37:11 2015 +0000

    urara: Configure clocks and MFIOs
    
    Set elements:
    	- UART1 clock dividers and MFIOs
    	- SPIM1 clock dividers and MFIOs
    	- USB clock dividers
    	- System clock divider
    	- System PLL
    	- MIPS CPU PLL
    
    BUG=chrome-os-partner:31438
    TEST=tested on Pisachio bring up board; UART, SPI NOR, SPI NAND, and USB
    have proper functionality.
    BRANCH=none
    
    Change-Id: Ib01186a652fd59295a4cafc3ca99b94aa9564f74
    Signed-off-by: Stefan Reinauer <reinauer at chromium.org>
    Original-Commit-Id: 65e68d82f34bb40ef3cfb397ecf5df0c83201151
    Original-Change-Id: Ia2c31bbbfc020dc4fd71c72b877414adfdfc42a8
    Original-Signed-off-by: Ionela Voinescu <ionela.voinescu at imgtec.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/241423
    Original-Reviewed-by: David Hendricks <dhendrix at chromium.org>
---
 src/mainboard/google/urara/Kconfig            |   4 +
 src/mainboard/google/urara/bootblock.c        | 142 +++++++++++
 src/soc/imgtec/pistachio/Makefile.inc         |   1 +
 src/soc/imgtec/pistachio/clocks.c             | 344 ++++++++++++++++++++++++++
 src/soc/imgtec/pistachio/include/soc/clocks.h |  39 +++
 5 files changed, 530 insertions(+)

diff --git a/src/mainboard/google/urara/Kconfig b/src/mainboard/google/urara/Kconfig
index 1386bc8..20cd118 100644
--- a/src/mainboard/google/urara/Kconfig
+++ b/src/mainboard/google/urara/Kconfig
@@ -40,6 +40,10 @@ config MAINBOARD_PART_NUMBER
 	string
 	default "ImgTec Pistachio Virtual Platform"
 
+config BOOTBLOCK_MAINBOARD_INIT
+	string
+	default "mainboard/google/urara/bootblock.c"
+
 config DRAM_SIZE_MB
 	int
 	default 256
diff --git a/src/mainboard/google/urara/bootblock.c b/src/mainboard/google/urara/bootblock.c
new file mode 100644
index 0000000..56177da
--- /dev/null
+++ b/src/mainboard/google/urara/bootblock.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Imagination Technologies
+ *
+ * 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 <arch/io.h>
+#include <stdint.h>
+#include <soc/clocks.h>
+#include <console/console.h>
+
+#define GPIO_BIT_EN_ADDR(bank)		(0xB8101C00 + 0x200 + (0x24 * (bank)))
+
+/* MFIO definitions for UART0/1 */
+#define UART1_RXD_MFIO			59
+#define UART1_TXD_MFIO			60
+#define UART0_RXD_MFIO			55
+#define UART0_TXD_MFIO			56
+#define UART0_RTS_MFIO			57
+#define UART0_CTS_MFIO			58
+
+/* MFIO definitions for SPIM */
+#define SPIM1_D0_TXD_MFIO		5
+#define SPIM1_D1_RXD_MFIO		4
+#define SPIM1_MCLK_MFIO			3
+#define SPIM1_D2_MFIO			6
+#define SPIM1_D3_MFIO			7
+#define SPIM1_CS0_MFIO			0
+
+static void uart1_mfio_setup(void)
+{
+	u32 reg, mfio_mask;
+
+	/*
+	 * Disable GPIO for UART1 MFIOs
+	 * All UART MFIOs have MFIO/16 = 3, therefore we use GPIO pad 3
+	 * This is the primary function (0) of these MFIOs and therfore there
+	 * is no need to set up a function number in the corresponding
+	 * function select register.
+	 */
+	reg = read32(GPIO_BIT_EN_ADDR(3));
+	mfio_mask =  1 << (UART1_RXD_MFIO % 16);
+	mfio_mask |= 1 << (UART1_TXD_MFIO % 16);
+	/* Clear relevant bits */
+	reg &= ~mfio_mask;
+	/*
+	 * Set corresponding bits in the upper half word
+	 * in order to be able to modify the chosen pins
+	 */
+	reg |= mfio_mask << 16;
+	write32(GPIO_BIT_EN_ADDR(3), reg);
+}
+
+static void spim1_mfio_setup(void)
+{
+	u32 reg, mfio_mask;
+	/*
+	 * Disable GPIO for SPIM1 MFIOs
+	 * All SPFI1 MFIOs have MFIO/16 = 0, therefore we use GPIO pad 0
+	 * This is the primary function (0) of these MFIOs and therfore there
+	 * is no need to set up a function number in the corresponding
+	 * function select register.
+	 */
+	reg = read32(GPIO_BIT_EN_ADDR(0));
+
+	/* Disable GPIO for UART0 MFIOs */
+	mfio_mask = 1 << (SPIM1_D0_TXD_MFIO % 16);
+	mfio_mask |= 1 << (SPIM1_D1_RXD_MFIO % 16);
+	mfio_mask |= 1 << (SPIM1_MCLK_MFIO % 16);
+	mfio_mask |= 1 << (SPIM1_D2_MFIO % 16);
+	mfio_mask |= 1 << (SPIM1_D3_MFIO % 16);
+
+	/* TODO: for the moment it only sets up CS0 (NOR) */
+	/* There is no need for other CS lines in Coreboot */
+	mfio_mask |= 1 << (SPIM1_CS0_MFIO % 16);
+
+	/* Clear relevant bits */
+	reg &= ~mfio_mask;
+	/*
+	 * Set corresponding bits in the upper half word
+	 * in order to be able to modify the chosen pins
+	 */
+	reg |= mfio_mask << 16;
+	write32(GPIO_BIT_EN_ADDR(0), reg);
+}
+
+static int init_clocks(void)
+{
+	int ret;
+
+	/*
+	 * Set up dividers for peripherals before setting up PLLs
+	 * in order to not over-clock them when enabling PLLs
+	*/
+
+	/* System PLL divided by 2 -> 400 MHz */
+	/* The same frequency will be the input frequency for the SPFI block */
+	system_clk_setup(1);
+	/* System clock divided by 8 -> 50 MHz */
+	ret = usb_clk_setup(7, 2, 7);
+	if (ret != CLOCKS_OK)
+		return ret;
+	/* System PLL divided by 7 divided by 62 -> 1.8433 Mhz */
+	uart1_clk_setup(6, 61);
+
+	/* Setup system PLL at 800 MHz */
+	ret = sys_pll_setup(2, 1);
+	if (ret != CLOCKS_OK)
+		return ret;
+	/* Setup MIPS PLL at 550 MHz */
+	ret = mips_pll_setup(2, 1, 13, 275);
+	if (ret != CLOCKS_OK)
+		return ret;
+	return CLOCKS_OK;
+}
+
+static void bootblock_mainboard_init(void)
+{
+	if (!init_clocks()) {
+		/* Disable GPIO on the peripheral lines */
+		uart1_mfio_setup();
+		printk(BIOS_INFO, "Urara board: UART initialized!\n");
+
+		spim1_mfio_setup();
+	}
+
+}
diff --git a/src/soc/imgtec/pistachio/Makefile.inc b/src/soc/imgtec/pistachio/Makefile.inc
index fdeba0c..6dc18f3 100644
--- a/src/soc/imgtec/pistachio/Makefile.inc
+++ b/src/soc/imgtec/pistachio/Makefile.inc
@@ -20,6 +20,7 @@
 #
 
 # We enable CBFS_SPI_WRAPPER for Pistachio targets.
+bootblock-y += clocks.c
 bootblock-y += spi.c
 romstage-y += spi.c
 ramstage-y += spi.c
diff --git a/src/soc/imgtec/pistachio/clocks.c b/src/soc/imgtec/pistachio/clocks.c
new file mode 100644
index 0000000..ec77d65
--- /dev/null
+++ b/src/soc/imgtec/pistachio/clocks.c
@@ -0,0 +1,344 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Imagination Technologies
+ *
+ * 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 <arch/io.h>
+#include <soc/clocks.h>
+#include <timer.h>
+#include <delay.h>
+#include <assert.h>
+
+/* Definitions for PLL enable */
+#define PISTACHIO_CLOCK_SWITCH		0xB8144200
+
+#define SYS_EXTERN_PLL_BYPASS_MASK	0x00002000
+#define SYS_PLL_CTRL4_ADDR		0xB8144048
+#define SYS_INTERNAL_PLL_BYPASS_MASK	0x10000000
+#define SYS_PLL_PD_CTRL_ADDR		0xB8144044
+#define SYS_PLL_PD_CTRL_PD_MASK		0x0000003F
+
+#define MIPS_EXTERN_PLL_BYPASS_MASK	0x00000002
+#define MIPS_PLL_CTRL2_ADDR		0xB8144008
+#define MIPS_INTERNAL_PLL_BYPASS_MASK	0x10000000
+#define MIPS_PLL_PD_CTRL_ADDR		0xB8144004
+#define MIPS_PLL_PD_CTRL_PD_MASK	0x0F000000
+
+/* Definitions for PLL dividers */
+#define SYS_PLL_POSTDIV_ADDR		0xB8144040
+#define SYS_PLL_POSTDIV1_MASK		0x07000000
+#define SYS_PLL_POSTDIV1_SHIFT		24
+#define SYS_PLL_POSTDIV2_MASK		0x38000000
+#define SYS_PLL_POSTDIV2_SHIFT		27
+#define SYS_PLL_STATUS_ADDR		0xB8144038
+#define SYS_PLL_STATUS_LOCK_MASK	0x00000001
+
+#define MIPS_PLL_POSTDIV_ADDR		0xB8144004
+#define MIPS_PLL_POSTDIV1_MASK		0x001C0000
+#define MIPS_PLL_POSTDIV1_SHIFT		18
+#define MIPS_PLL_POSTDIV2_MASK		0x00E00000
+#define MIPS_PLL_POSTDIV2_SHIFT		21
+#define MIPS_PLL_STATUS_ADDR		0xB8144000
+#define MIPS_PLL_STATUS_LOCK_MASK	0x00000001
+
+#define MIPS_REFDIV_ADDR		0xB8144004
+#define MIPS_REFDIV_MASK		0x0000003F
+#define MIPS_REFDIV_SHIFT		0
+#define MIPS_FEEDBACK_ADDR		0xB8144004
+#define MIPS_FEEDBACK_MASK		0x0003FFC0
+#define MIPS_FEEDBACK_SHIFT		6
+
+/* Definitions for system clock setup */
+#define SYSCLKINTERNAL_CTRL_ADDR	0xB8144244
+#define SYSCLKINTERNAL_MASK		0X00000007
+
+/* Definitions for USB clock setup */
+#define USBPHYCLKOUT_CTRL_ADDR		0xB814422C
+#define USBPHYCLKOUT_MASK		0X0000003F
+#define USBPHYCONTROL1_ADDR		0xB8149004
+#define USBPHYCONTROL1_FSEL_SHIFT	2
+#define USBPHYCONTROL1_FSEL_MASK	0x1C
+#define USBPHYSTRAPCTRL_ADDR		0xB8149010
+#define USBPHYSTRAPCTRL_REFCLKSEL_SHIFT	4
+#define USBPHYSTRAPCTRL_REFCLKSEL_MASK	0x30
+#define USBPHYSTATUS_ADDR		0xB8149014
+#define USBPHYSTATUS_RX_PHY_CLK_MASK	0x200
+#define USBPHYSTATUS_RX_UTMI_CLK_MASK	0x100
+#define USBPHYSTATUS_VBUS_FAULT_MASK	0x80
+
+/* Definitions for UART0/1 setup */
+#define UART0CLKINTERNAL_CTRL_ADDR	0xB8144234
+#define UART0CLKINTERNAL_MASK		0x00000007
+#define UART0CLKOUT_CTRL_ADDR		0xB8144238
+#define UART0CLKOUT_MASK		0x000003FF
+#define UART1CLKINTERNAL_CTRL_ADDR	0xB814423C
+#define UART1CLKINTERNAL_MASK		0x00000007
+#define UART1CLKOUT_CTRL_ADDR		0xB8144240
+#define UART1CLKOUT_MASK		0x000003FF
+
+/* Definitions for timeout values */
+#define PLL_TIMEOUT_VALUE_US		20000
+#define USB_TIMEOUT_VALUE_US		200000
+#define SYS_CLK_LOCK_DELAY		3
+
+struct pll_parameters {
+	u32 external_bypass_mask;
+	u32 ctrl_addr;
+	u32 internal_bypass_mask;
+	u32 power_down_ctrl_addr;
+	u32 power_down_ctrl_mask;
+	u32 postdiv_addr;
+	u32 postdiv1_shift;
+	u32 postdiv1_mask;
+	u32 postdiv2_shift;
+	u32 postdiv2_mask;
+	u32 status_addr;
+	u32 status_lock_mask;
+	u32 refdivider;
+	u32 refdiv_addr;
+	u32 refdiv_shift;
+	u32 refdiv_mask;
+	u32 feedback;
+	u32 feedback_addr;
+	u32 feedback_shift;
+	u32 feedback_mask;
+};
+
+enum plls {
+	SYS_PLL = 0,
+	MIPS_PLL = 1
+};
+
+static struct pll_parameters pll_params[] = {
+	[SYS_PLL] = {
+		.external_bypass_mask = SYS_EXTERN_PLL_BYPASS_MASK,
+		.ctrl_addr = SYS_PLL_CTRL4_ADDR,
+		.internal_bypass_mask = SYS_INTERNAL_PLL_BYPASS_MASK,
+		.power_down_ctrl_addr = SYS_PLL_PD_CTRL_ADDR,
+		.power_down_ctrl_mask = SYS_PLL_PD_CTRL_PD_MASK,
+		.postdiv_addr = SYS_PLL_POSTDIV_ADDR,
+		.postdiv1_shift = SYS_PLL_POSTDIV1_SHIFT,
+		.postdiv1_mask = SYS_PLL_POSTDIV1_MASK,
+		.postdiv2_shift = SYS_PLL_POSTDIV2_SHIFT,
+		.postdiv2_mask = SYS_PLL_POSTDIV2_MASK,
+		.status_addr = SYS_PLL_STATUS_ADDR,
+		.status_lock_mask = SYS_PLL_STATUS_LOCK_MASK,
+		.refdivider = 0, /* Not defined yet */
+		.refdiv_addr = 0, /* Not necessary */
+		.refdiv_shift = 0, /* Not necessary */
+		.refdiv_mask = 0, /* Not necessary */
+		.feedback = 0, /* Not necessary */
+		.feedback_addr = 0, /* Not necessary */
+		.feedback_shift = 0, /* Not necessary */
+		.feedback_mask = 0, /* Not necessary */
+	},
+
+	[MIPS_PLL] = {
+		.external_bypass_mask = MIPS_EXTERN_PLL_BYPASS_MASK,
+		.ctrl_addr = MIPS_PLL_CTRL2_ADDR,
+		.internal_bypass_mask = MIPS_INTERNAL_PLL_BYPASS_MASK,
+		.power_down_ctrl_addr = MIPS_PLL_PD_CTRL_ADDR,
+		.power_down_ctrl_mask = MIPS_PLL_PD_CTRL_PD_MASK,
+		.postdiv_addr = MIPS_PLL_POSTDIV_ADDR,
+		.postdiv1_shift = MIPS_PLL_POSTDIV1_SHIFT,
+		.postdiv1_mask = MIPS_PLL_POSTDIV1_MASK,
+		.postdiv2_shift = MIPS_PLL_POSTDIV2_SHIFT,
+		.postdiv2_mask = MIPS_PLL_POSTDIV2_MASK,
+		.status_addr = MIPS_PLL_STATUS_ADDR,
+		.status_lock_mask = MIPS_PLL_STATUS_LOCK_MASK,
+		.refdivider = 0, /* Not defined yet */
+		.refdiv_addr = MIPS_REFDIV_ADDR,
+		.refdiv_shift = MIPS_REFDIV_SHIFT,
+		.refdiv_mask = MIPS_REFDIV_MASK,
+		.feedback = 0, /* Not defined yet */
+		.feedback_addr = MIPS_FEEDBACK_ADDR,
+		.feedback_shift = MIPS_FEEDBACK_SHIFT,
+		.feedback_mask = MIPS_FEEDBACK_MASK
+	}
+};
+
+static int pll_setup(struct pll_parameters *param, u8 divider1, u8 divider2)
+{
+	u32 reg;
+	struct stopwatch sw;
+
+	/* Check input parameters */
+	assert(!(divider1 & ~(param->postdiv1_mask)));
+	assert(!(divider2 & ~(param->postdiv2_mask)));
+
+	/* Temporary bypass PLL (select XTAL as clock input) */
+	reg = read32(PISTACHIO_CLOCK_SWITCH);
+	reg &= ~(param->external_bypass_mask);
+	write32(PISTACHIO_CLOCK_SWITCH, reg);
+
+	/* Un-bypass PLL's internal bypass */
+	reg = read32(param->ctrl_addr);
+	reg &= ~(param->internal_bypass_mask);
+	write32(param->ctrl_addr, reg);
+
+	/* Disable power down */
+	reg = read32(param->power_down_ctrl_addr);
+	reg &= ~(param->power_down_ctrl_mask);
+	write32(param->power_down_ctrl_addr, reg);
+
+	if (param->feedback_addr) {
+		assert(!(param->feedback & ~(param->feedback_mask)));
+		reg = read32(param->feedback_addr);
+		reg &= ~(param->feedback_mask);
+		reg |= (param->feedback << param->feedback_shift) &
+			param->feedback_mask;
+		write32(param->feedback_addr, reg);
+	}
+
+	if (param->refdiv_addr) {
+		assert(!(param->refdivider & ~(param->refdiv_mask)));
+		reg = read32(param->refdiv_addr);
+		reg &= ~(param->refdiv_mask);
+		reg |= (param->refdivider << param->refdiv_shift) &
+			param->refdiv_mask;
+		write32(param->refdiv_addr, reg);
+	}
+
+	/* Read postdivider register value */
+	reg = read32(param->postdiv_addr);
+	/* Set divider 1 */
+	reg &= ~(param->postdiv1_mask);
+	reg |= (divider1 << param->postdiv1_shift) &
+			param->postdiv1_mask;
+	/* Set divider 2 */
+	reg &= ~(param->postdiv2_mask);
+	reg |= (divider2 << param->postdiv2_shift) &
+			param->postdiv2_mask;
+	/* Write back to register */
+	write32(param->postdiv_addr, reg);
+
+	/* Waiting for PLL to lock*/
+	stopwatch_init_usecs_expire(&sw, PLL_TIMEOUT_VALUE_US);
+	while (!(read32(param->status_addr) & param->status_lock_mask)) {
+		if (stopwatch_expired(&sw))
+			return PLL_TIMEOUT;
+	}
+
+	/* Start using PLL */
+	reg = read32(PISTACHIO_CLOCK_SWITCH);
+	reg |= param->external_bypass_mask;
+	write32(PISTACHIO_CLOCK_SWITCH, reg);
+
+	return CLOCKS_OK;
+}
+
+int sys_pll_setup(u8 divider1, u8 divider2)
+{
+	return pll_setup(&(pll_params[SYS_PLL]), divider1, divider2);
+}
+
+int mips_pll_setup(u8 divider1, u8 divider2, u8 refdivider, u32 feedback)
+{
+	pll_params[MIPS_PLL].refdivider = refdivider;
+	pll_params[MIPS_PLL].feedback = feedback;
+	return pll_setup(&(pll_params[MIPS_PLL]), divider1, divider2);
+}
+
+/*
+ * uart1_clk_setup: sets up clocks for UART1
+ * divider1: 3-bit divider value
+ * divider2: 10-bit divider value
+ */
+void uart1_clk_setup(u8 divider1, u16 divider2)
+{
+	u32 reg;
+
+	/* Check input parameters */
+	assert(!(divider1 & ~(UART1CLKINTERNAL_MASK)));
+	assert(!(divider2 & ~(UART1CLKOUT_MASK)));
+
+	/* Set divider 1 */
+	reg = read32(UART1CLKINTERNAL_CTRL_ADDR);
+	reg &= ~UART1CLKINTERNAL_MASK;
+	reg |= divider1 & UART1CLKINTERNAL_MASK;
+	write32(UART1CLKINTERNAL_CTRL_ADDR, reg);
+
+	/* Set divider 2 */
+	reg = read32(UART1CLKOUT_CTRL_ADDR);
+	reg &= ~UART1CLKOUT_MASK;
+	reg |= divider2 & UART1CLKOUT_MASK;
+	write32(UART1CLKOUT_CTRL_ADDR, reg);
+}
+
+/* system_clk_setup: sets up the system (peripheral) clock */
+void system_clk_setup(u8 divider)
+{
+	u32 reg;
+
+	/* Check input parameters */
+	assert(!(divider & ~(SYSCLKINTERNAL_MASK)));
+
+	/* Set system clock divider */
+	reg = read32(SYSCLKINTERNAL_CTRL_ADDR);
+	reg &= ~SYSCLKINTERNAL_MASK;
+	reg |= divider & SYSCLKINTERNAL_MASK;
+	write32(SYSCLKINTERNAL_CTRL_ADDR, reg);
+
+	/* Small delay to cover a maximum lock time of 1500 cycles */
+	udelay(SYS_CLK_LOCK_DELAY);
+}
+
+/* usb_clk_setup: sets up USB clock */
+int usb_clk_setup(u8 divider, u8 refclksel, u8 fsel)
+{
+	u32 reg;
+	struct stopwatch sw;
+
+	/* Check input parameters */
+	assert(!(divider & ~(USBPHYCLKOUT_MASK)));
+	assert(!(refclksel & ~(USBPHYSTRAPCTRL_REFCLKSEL_MASK)));
+	assert(!(fsel & ~(USBPHYCONTROL1_FSEL_MASK)));
+
+	/* Set USB divider */
+	reg = read32(USBPHYCLKOUT_CTRL_ADDR);
+	reg &= ~USBPHYCLKOUT_MASK;
+	reg |= divider & USBPHYCLKOUT_MASK;
+	write32(USBPHYCLKOUT_CTRL_ADDR, reg);
+
+	/* Set REFCLKSEL */
+	reg = read32(USBPHYSTRAPCTRL_ADDR);
+	reg &= ~USBPHYSTRAPCTRL_REFCLKSEL_MASK;
+	reg |= (refclksel << USBPHYSTRAPCTRL_REFCLKSEL_SHIFT) &
+		USBPHYSTRAPCTRL_REFCLKSEL_MASK;
+	write32(USBPHYSTRAPCTRL_ADDR, reg);
+
+	/* Set FSEL */
+	reg = read32(USBPHYCONTROL1_ADDR);
+	reg &= ~USBPHYCONTROL1_FSEL_MASK;
+	reg |= (fsel << USBPHYCONTROL1_FSEL_SHIFT) &
+		USBPHYCONTROL1_FSEL_MASK;
+	write32(USBPHYCONTROL1_ADDR, reg);
+
+	/* Waiting for USB clock status */
+	stopwatch_init_usecs_expire(&sw, USB_TIMEOUT_VALUE_US);
+	while (1) {
+		reg = read32(USBPHYSTATUS_ADDR);
+		if (reg & USBPHYSTATUS_VBUS_FAULT_MASK)
+			return USB_VBUS_FAULT;
+		if (stopwatch_expired(&sw))
+			return USB_TIMEOUT;
+	}
+
+	return CLOCKS_OK;
+}
diff --git a/src/soc/imgtec/pistachio/include/soc/clocks.h b/src/soc/imgtec/pistachio/include/soc/clocks.h
new file mode 100644
index 0000000..95b3585
--- /dev/null
+++ b/src/soc/imgtec/pistachio/include/soc/clocks.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Imagination Technologies
+ *
+ * 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_IMGTEC_PISTACHIO_CLOCKS_H__
+#define __SOC_IMGTEC_PISTACHIO_CLOCKS_H__
+
+#include <stdint.h>
+
+/* Functions for PLL setting */
+int sys_pll_setup(u8 divider1, u8 divider2);
+int mips_pll_setup(u8 divider1, u8 divider2i, u8 predivider, u32 feedback);
+
+/* Peripheral divider setting */
+void uart1_clk_setup(u8 divider1, u16 divider2);
+void system_clk_setup(u8 divider);
+int usb_clk_setup(u8 divider, u8 refclksel, u8 fsel);
+
+enum {
+	CLOCKS_OK = 0,
+	PLL_TIMEOUT = -1,
+	USB_TIMEOUT = -2,
+	USB_VBUS_FAULT = -3
+};
+
+#endif



More information about the coreboot-gerrit mailing list