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@chromium.org> Original-Commit-Id: 65e68d82f34bb40ef3cfb397ecf5df0c83201151 Original-Change-Id: Ia2c31bbbfc020dc4fd71c72b877414adfdfc42a8 Original-Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com> Original-Reviewed-on: https://chromium-review.googlesource.com/241423 Original-Reviewed-by: David Hendricks <dhendrix@chromium.org> Reviewed-on: http://review.coreboot.org/9662 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
parent
95c902261f
commit
b3f666b252
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue