mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-23 21:44:15 +00:00

Signed-off-by: Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com> Change-Id: Ib2ad2068abdf0b204c5cb021ea919581adaca4ef
293 lines
8.3 KiB
C
293 lines
8.3 KiB
C
/*
|
|
* Copyright (c) 2019, Intel Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <common/debug.h>
|
|
#include <drivers/delay_timer.h>
|
|
#include <errno.h>
|
|
#include <lib/mmio.h>
|
|
|
|
#include "agilex_clock_manager.h"
|
|
#include "agilex_handoff.h"
|
|
|
|
static const CLOCK_SOURCE_CONFIG clk_source = {
|
|
/* clk_freq_of_eosc1 */
|
|
(uint32_t) 25000000,
|
|
/* clk_freq_of_f2h_free */
|
|
(uint32_t) 400000000,
|
|
/* clk_freq_of_cb_intosc_ls */
|
|
(uint32_t) 50000000,
|
|
};
|
|
|
|
uint32_t wait_pll_lock(void)
|
|
{
|
|
uint32_t data;
|
|
uint32_t count = 0;
|
|
|
|
do {
|
|
data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
|
|
count++;
|
|
if (count >= 1000)
|
|
return -ETIMEDOUT;
|
|
|
|
} while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
|
|
(CLKMGR_STAT_PERPLLLOCKED(data) == 0));
|
|
return 0;
|
|
}
|
|
|
|
uint32_t wait_fsm(void)
|
|
{
|
|
uint32_t data;
|
|
uint32_t count = 0;
|
|
|
|
do {
|
|
data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
|
|
count++;
|
|
if (count >= 1000)
|
|
return -ETIMEDOUT;
|
|
|
|
} while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t pll_source_sync_config(uint32_t pll_mem_offset)
|
|
{
|
|
uint32_t val = 0;
|
|
uint32_t count = 0;
|
|
uint32_t req_status = 0;
|
|
|
|
val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ |
|
|
CLKMGR_MEM_WDAT << CLKMGR_MEM_WDAT_OFFSET | CLKMGR_MEM_ADDR);
|
|
mmio_write_32(pll_mem_offset, val);
|
|
|
|
do {
|
|
req_status = mmio_read_32(pll_mem_offset);
|
|
count++;
|
|
} while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
|
|
|
|
if (count >= 100)
|
|
return -ETIMEDOUT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t pll_source_sync_read(uint32_t pll_mem_offset)
|
|
{
|
|
uint32_t val = 0;
|
|
uint32_t rdata = 0;
|
|
uint32_t count = 0;
|
|
uint32_t req_status = 0;
|
|
|
|
val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR);
|
|
mmio_write_32(pll_mem_offset, val);
|
|
|
|
do {
|
|
req_status = mmio_read_32(pll_mem_offset);
|
|
count++;
|
|
} while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
|
|
|
|
if (count >= 100)
|
|
return -ETIMEDOUT;
|
|
|
|
rdata = mmio_read_32(pll_mem_offset + 0x4);
|
|
INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void config_clkmgr_handoff(handoff *hoff_ptr)
|
|
{
|
|
uint32_t mdiv, mscnt, hscnt;
|
|
uint32_t arefclk_div, drefclk_div;
|
|
|
|
/* Bypass all mainpllgrp's clocks */
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7);
|
|
wait_fsm();
|
|
|
|
/* Bypass all perpllgrp's clocks */
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f);
|
|
wait_fsm();
|
|
|
|
/* Put both PLL in reset and power down */
|
|
mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
|
|
CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK |
|
|
CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK);
|
|
mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
|
|
CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK |
|
|
CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK);
|
|
|
|
/* Setup main PLL dividers */
|
|
mdiv = CLKMGR_MAINPLL_PLLM_MDIV(hoff_ptr->main_pll_pllm);
|
|
|
|
arefclk_div = CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(
|
|
hoff_ptr->main_pll_pllglob);
|
|
drefclk_div = CLKMGR_MAINPLL_PLLGLOB_DREFCLKDIV(
|
|
hoff_ptr->main_pll_pllglob);
|
|
|
|
mscnt = 100 / (mdiv / BIT(drefclk_div));
|
|
if (!mscnt)
|
|
mscnt = 1;
|
|
hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
|
|
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB,
|
|
CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) |
|
|
CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt));
|
|
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
|
|
hoff_ptr->main_pll_nocdiv);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
|
|
hoff_ptr->main_pll_pllglob);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK,
|
|
hoff_ptr->main_pll_fdbck);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0,
|
|
hoff_ptr->main_pll_pllc0);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1,
|
|
hoff_ptr->main_pll_pllc1);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2,
|
|
hoff_ptr->main_pll_pllc2);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3,
|
|
hoff_ptr->main_pll_pllc3);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM,
|
|
hoff_ptr->main_pll_pllm);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK,
|
|
hoff_ptr->main_pll_mpuclk);
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK,
|
|
hoff_ptr->main_pll_nocclk);
|
|
|
|
/* Setup peripheral PLL dividers */
|
|
mdiv = CLKMGR_PERPLL_PLLM_MDIV(hoff_ptr->per_pll_pllm);
|
|
|
|
arefclk_div = CLKMGR_PERPLL_PLLGLOB_AREFCLKDIV(
|
|
hoff_ptr->per_pll_pllglob);
|
|
drefclk_div = CLKMGR_PERPLL_PLLGLOB_DREFCLKDIV(
|
|
hoff_ptr->per_pll_pllglob);
|
|
|
|
mscnt = 100 / (mdiv / BIT(drefclk_div));
|
|
if (!mscnt)
|
|
mscnt = 1;
|
|
hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
|
|
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB,
|
|
CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) |
|
|
CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt));
|
|
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
|
|
hoff_ptr->per_pll_emacctl);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV,
|
|
CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(
|
|
hoff_ptr->per_pll_gpiodiv));
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
|
|
hoff_ptr->per_pll_pllglob);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK,
|
|
hoff_ptr->per_pll_fdbck);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0,
|
|
hoff_ptr->per_pll_pllc0);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1,
|
|
hoff_ptr->per_pll_pllc1);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2,
|
|
hoff_ptr->per_pll_pllc2);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3,
|
|
hoff_ptr->per_pll_pllc3);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM,
|
|
hoff_ptr->per_pll_pllm);
|
|
|
|
/* Take both PLL out of reset and power up */
|
|
mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
|
|
CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK |
|
|
CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK);
|
|
mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
|
|
CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK |
|
|
CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK);
|
|
|
|
wait_pll_lock();
|
|
|
|
pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM);
|
|
pll_source_sync_read(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM);
|
|
|
|
pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
|
|
pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
|
|
|
|
/*Configure Ping Pong counters in altera group */
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR,
|
|
hoff_ptr->alt_emacactr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR,
|
|
hoff_ptr->alt_emacbctr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR,
|
|
hoff_ptr->alt_emacptpctr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR,
|
|
hoff_ptr->alt_gpiodbctr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR,
|
|
hoff_ptr->alt_sdmmcctr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR,
|
|
hoff_ptr->alt_s2fuser0ctr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR,
|
|
hoff_ptr->alt_s2fuser1ctr);
|
|
mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR,
|
|
hoff_ptr->alt_psirefctr);
|
|
|
|
/* Take all PLLs out of bypass */
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0);
|
|
wait_fsm();
|
|
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0);
|
|
wait_fsm();
|
|
|
|
/* Clear loss lock interrupt status register that */
|
|
/* might be set during configuration */
|
|
mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR,
|
|
CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
|
|
CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
|
|
|
|
/* Take all ping pong counters out of reset */
|
|
mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST,
|
|
CLKMGR_ALTERA_EXTCNTRST_RESET);
|
|
|
|
/* Set safe mode / out of boot mode */
|
|
mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
|
|
CLKMGR_CTRL_BOOTMODE_SET_MSK);
|
|
wait_fsm();
|
|
|
|
/* Enable mainpllgrp's software-managed clock */
|
|
mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN,
|
|
CLKMGR_MAINPLL_EN_RESET);
|
|
mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
|
|
CLKMGR_PERPLL_EN_RESET);
|
|
}
|
|
|
|
int get_wdt_clk(handoff *hoff_ptr)
|
|
{
|
|
int main_noc_base_clk, l3_main_free_clk, l4_sys_free_clk;
|
|
int data32, mdiv, arefclkdiv, ref_clk;
|
|
|
|
data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB);
|
|
|
|
switch (CLKMGR_MAINPLL_PLLGLOB_PSRC(data32)) {
|
|
case CLKMGR_MAINPLL_PLLGLOB_PSRC_EOSC1:
|
|
ref_clk = clk_source.clk_freq_of_eosc1;
|
|
break;
|
|
case CLKMGR_MAINPLL_PLLGLOB_PSRC_INTOSC:
|
|
ref_clk = clk_source.clk_freq_of_cb_intosc_ls;
|
|
break;
|
|
case CLKMGR_MAINPLL_PLLGLOB_PSRC_F2S:
|
|
ref_clk = clk_source.clk_freq_of_f2h_free;
|
|
break;
|
|
default:
|
|
ref_clk = 0;
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
arefclkdiv = CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(data32);
|
|
mdiv = CLKMGR_MAINPLL_PLLM_MDIV(hoff_ptr->main_pll_pllm);
|
|
|
|
ref_clk = (ref_clk / arefclkdiv) * mdiv;
|
|
main_noc_base_clk = ref_clk / (hoff_ptr->main_pll_pllc1 & 0x7ff);
|
|
l3_main_free_clk = main_noc_base_clk / (hoff_ptr->main_pll_nocclk + 1);
|
|
l4_sys_free_clk = l3_main_free_clk / 4;
|
|
|
|
return l4_sys_free_clk;
|
|
}
|