blob: 2c01070284f6884d00e5b3a3d3299b0ea821ea52 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <command.h>
#include <amlogic/cpu_id.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/secure_apb.h>
#include <asm/arch/timer.h>
#include <asm/arch/pll.h>
#define STR_PLL_TEST_ALL "all"
#define STR_PLL_TEST_SYS "sys"
#define STR_PLL_TEST_FIX "fix"
#define STR_PLL_TEST_DDR "ddr"
#define STR_PLL_TEST_HIFI "hifi"
#define STR_PLL_TEST_GP "gp0"
#define STR_PLL_TEST_DDS "dds"
#define STR_PLL_TEST_USBPHY "usbphy"
#define STR_PLL_TEST_ETHPHY "ethphy"
#define PLL_LOCK_CHECK_MAX 10
#define RET_PLL_LOCK_FAIL 0x1000
#define RET_CLK_NOT_MATCH 0x1
#define SYS_PLL_DIV16_CNTL (1<<24)
#define SYS_CLK_DIV16_CNTL (1)
#define SYS_PLL_TEST_DIV 4 /* div16 */
#define HDMI_PLL_DIV_CNTL (1<<18)
#define HDMI_PLL_DIV_GATE (1<<19)
#define PLL_DIV16_OFFSET 4 /* div2/2/4 */
#define gp_PLL_TEST_DIV 0 /* div1 */
#define PLL_DIV8_OFFSET 3
#define Wr(addr, data) writel(data, addr)
#define Rd(addr) readl(addr)
static int sys_pll_init(sys_pll_set_t * sys_pll_set);
static int sys_pll_test(sys_pll_set_t * sys_pll_set);
static int sys_pll_test_all(sys_pll_cfg_t * sys_pll_cfg);
static int fix_pll_test(void);
static int ddr_pll_test(void);
static int gp_pll_test(gp_pll_set_t * gp_pll);
static int gp_pll_test_all(gp0_pll_cfg_t * gp0_pll_cfg);
extern unsigned long clk_util_clk_msr(unsigned long clk_mux);
static void update_bits(size_t reg, size_t mask, unsigned int val)
{
unsigned int tmp, orig;
orig = readl(reg);
tmp = orig & ~mask;
tmp |= val & mask;
writel(tmp, reg);
}
uint32_t sys_pll_clk[PLL_TEST_SYS_TOTAL] = {3216, 1584};
sys_pll_cfg_t sys_pll_cfg = {
.sys_pll[0] = {
.cpu_clk = 3216,
.pll_cntl0 = 0x00300486,
.pll_cntl1 = 0x00021092,
.pll_cntl2 = 0x09023302,
.pll_cntl3 = 0x02008000,
},
.sys_pll[1] = {
.cpu_clk = 1584,
.pll_cntl0 = 0x00000442,
.pll_cntl1 = 0x00021092,
.pll_cntl2 = 0x09023302,
.pll_cntl3 = 0x02008000,
},
};
uint32_t hifi_pll_clk[] = {1560, 744};
hifi_pll_cfg_t hifi_pll_cfg = {
.hifi_pll[0] = {
.pll_clk = 1560,
.pll_cntl0 = 0x00030441,
.pll_cntl1 = 0x802000b1,
.pll_cntl2 = 0x15002320,
.pll_cntl3 = 0xf0005555,
.pll_cntl4 = 0x45004000,
},
.hifi_pll[1] = {
.pll_clk = 744,
.pll_cntl0 = 0x0003041f,
.pll_cntl1 = 0x802000b1,
.pll_cntl2 = 0x12002320,
.pll_cntl3 = 0xf0005555,
.pll_cntl4 = 0x45004000,
},
};
gp0_pll_cfg_t gp0_pll_cfg = {
.gp0_pll[0] = {
.pll_clk = 1560, /* MHz */
.pll_cntl0 = 0x00030441,
.pll_cntl1 = 0x802000b1,
.pll_cntl2 = 0x11002320,
.pll_cntl3 = 0xd0010000,
.pll_cntl4 = 0x45004000,
.pll_cntl5 = 0x51a051a,
.pll_cntl6 = 0x01888585
},
.gp0_pll[1] = {
.pll_clk = 744, /* MHz */
.pll_cntl0 = 0x0003041f,
.pll_cntl1 = 0x802000b1,
.pll_cntl2 = 0x11002320,
.pll_cntl3 = 0xd0010000,
.pll_cntl4 = 0x45004000,
.pll_cntl5 = 0x51a051a,
.pll_cntl6 = 0x01888585
},
};
#define PLL_RATE(_rate, _m, _n, _od) \
{ \
.rate = (_rate), \
.m = (_m), \
.n = (_n), \
.od = (_od), \
}
#define DDSPLL_RATE(_RATE, _CTS, _N) \
{ \
.RATE = (_RATE), \
.CTS= (_CTS), \
.N = (_N), \
}
static void pll_report(unsigned int flag, char * name)
{
if (flag)
printf("%s pll test failed!\n", name);
else
printf("%s pll test pass!\n", name);
return;
}
static int clk_around(unsigned int clk, unsigned int cmp)
{
if (((cmp - 2) <= clk) && (clk <= (cmp + 2)))
return 1;
else
return 0;
}
void clocks_set_sys_cpu_clk(uint32_t src)
{
/*
* src
* 0: use 24M, 1: use SYS PLL
*/
uint32_t control;
uint32_t dyn_pre_mux;
uint32_t dyn_post_mux;
uint32_t dyn_div;
//runtime_info_t info;
// Make sure not busy from last setting and we currently match the last setting
do {
control = readl(CPUCTRL_CLK_CTRL0);
} while( (control & (1 << 28)) );
control = control | (1 << 26);// Enable
dyn_pre_mux = 0; //use oscin
dyn_post_mux = 0;
dyn_div = 0;/* divide by 1 */
// Select Dynamic mux
if (src == 1) {
control = control | (1 << 11);
}
else {
control = control & ~(1 << 11);
if (control & (1 << 10)) {// if using Dyn mux1, set dyn mux 0
// Toggle bit[10] indicating a dynamic mux change
control = (control & ~((1 << 10) | (0x3f << 4) | (1 << 2) | (0x3 << 0)))
| ((0 << 10)
| (dyn_div << 4)
| (dyn_post_mux << 2)
| (dyn_pre_mux << 0));
} else {
// Toggle bit[10] indicating a dynamic mux change
control = (control & ~((1 << 10) | (0x3f << 20) | (1 << 18) | (0x3 << 16)))
| ((1 << 10)
| (dyn_div << 20)
| (dyn_post_mux << 18)
| (dyn_pre_mux << 16));
}
}
writel(control, CPUCTRL_CLK_CTRL0);
return;
}
static int sys_pll_init(sys_pll_set_t * sys_pll_set)
{
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int lock_timeout = 0;
do {
_udelay(5);
writel(sys_pll_set->pll_cntl0 | (1 << 29),
ANACTRL_SYSPLL_CTRL0);
writel(sys_pll_set->pll_cntl1, ANACTRL_SYSPLL_CTRL1);
writel(sys_pll_set->pll_cntl2, ANACTRL_SYSPLL_CTRL2);
writel(sys_pll_set->pll_cntl3, ANACTRL_SYSPLL_CTRL3);
writel(sys_pll_set->pll_cntl0 | (1 << 28) | (1 << 29),
ANACTRL_SYSPLL_CTRL0);
_udelay(5);
writel(sys_pll_set->pll_cntl0 | (1 << 28),
ANACTRL_SYSPLL_CTRL0);
_udelay(10);
writel(sys_pll_set->pll_cntl0 | (1 << 28) | (1 << 27),
ANACTRL_SYSPLL_CTRL0);
lock_timeout = 80;
do {
_udelay(5);
} while ((0 == ((Rd(ANACTRL_SYSPLL_STS) >> 31) & 0x1)) &&
(--lock_timeout));
} while((0 == ((Rd(ANACTRL_SYSPLL_STS) >> 31) & 0x1)) &&
(--lock_check));
if (lock_check != 0)
return 0;
else
return RET_PLL_LOCK_FAIL;
}
static int sys_pll_test_all(sys_pll_cfg_t * sys_pll_cfg)
{
unsigned int i = 0;
int ret = 0;
for (i = 0; i < (sizeof(sys_pll_clk) / sizeof(uint32_t)); i++) {
sys_pll_cfg->sys_pll[0].cpu_clk = sys_pll_clk[i];
ret += sys_pll_test(&(sys_pll_cfg->sys_pll[i]));
}
return ret;
}
static int sys_pll_test(sys_pll_set_t * sys_pll_set)
{
unsigned int clk_msr_val = 0;
unsigned int sys_clk = 0, od = 0;
int ret = 0;
/* switch sys clk to oscillator */
clocks_set_sys_cpu_clk(0);
/* store current sys pll cntl */
sys_pll_set_t sys_pll;
sys_pll.pll_cntl0 = readl(ANACTRL_SYSPLL_CTRL0) & (~(0x7 << 27));
sys_pll.pll_cntl1 = readl(ANACTRL_SYSPLL_CTRL1);
sys_pll.pll_cntl2 = readl(ANACTRL_SYSPLL_CTRL2);
sys_pll.pll_cntl3 = readl(ANACTRL_SYSPLL_CTRL3);
if (sys_pll_set->cpu_clk == 0) {
sys_clk = (24 * (sys_pll_set->pll_cntl0 & 0xFF)) /
((sys_pll_set->pll_cntl0 >> 10) & 0x1F);
}
if (0 == sys_pll_set->pll_cntl0) {
printf("sys pll cntl equal NULL, skip\n");
return -1;
}
od = (sys_pll_set->pll_cntl0 >> 20) & 0x3;
/* test sys pll */
if (sys_pll_set->cpu_clk)
sys_clk = sys_pll_set->cpu_clk;
ret = sys_pll_init(sys_pll_set);
if (ret) {
printf("SYS pll lock Failed! - %4d MHz\n", sys_clk);
} else {
printf("SYS pll lock OK! - %4d MHz >> %d/Div16 - %4d MHz.",
sys_clk, od, (sys_clk >> od) >> PLL_DIV16_OFFSET);
clocks_set_sys_cpu_clk(1);
/*open div16*/
writel(readl(CPUCTRL_CLK_CTRL1) | (1 << 24) | (1 << 1),
CPUCTRL_CLK_CTRL1);
clk_msr_val = clk_util_clk_msr(45);
printf("CLKMSR(45) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, (sys_clk >> od) >>
SYS_PLL_TEST_DIV)) {
/* sys clk/pll div16 */
printf(": Match\n");
} else {
ret = RET_CLK_NOT_MATCH;
printf(": MisMatch\n");
}
}
/* restore sys pll */
clocks_set_sys_cpu_clk(0);
//printf("cpu = 0x%x\n", readl(CPUCTRL_CLK_CTRL0));
ret = sys_pll_init(&sys_pll);
if (ret)
printf("restore sys pll lock Failed!\n");
clocks_set_sys_cpu_clk(1);
return ret;
}
static int fix_pll_test(void)
{
return 0;
}
static int ddr_pll_test(void)
{
return 0;
}
static int hifi_pll_test(hifi_pll_set_t * hifi_pll)
{
int ret = 0;
unsigned int pll_clk = 0;
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int clk_msr_val = 0;
if (hifi_pll->pll_clk == 0)
pll_clk = (24 / ((hifi_pll->pll_cntl0 >> 10) & 0x1F) *
(hifi_pll->pll_cntl0 & 0x1FF));
else
pll_clk = hifi_pll->pll_clk;
do {
writel(hifi_pll->pll_cntl0 | (1 << 29),
ANACTRL_HIFIPLL_CTRL0);
writel(hifi_pll->pll_cntl1, ANACTRL_HIFIPLL_CTRL1);
writel(hifi_pll->pll_cntl2, ANACTRL_HIFIPLL_CTRL2);
writel(hifi_pll->pll_cntl3, ANACTRL_HIFIPLL_CTRL3);
writel(hifi_pll->pll_cntl4, ANACTRL_HIFIPLL_CTRL4);
_udelay(5);
writel(hifi_pll->pll_cntl0 | (1 << 28) | (1 << 29),
ANACTRL_HIFIPLL_CTRL0);
_udelay(5);
writel(hifi_pll->pll_cntl0 | (1 << 28),
ANACTRL_HIFIPLL_CTRL0);
_udelay(10);
writel(hifi_pll->pll_cntl4 | (1 << 0), ANACTRL_HIFIPLL_CTRL4);
_udelay(100);
} while((0 == ((Rd(ANACTRL_HIFIPLL_STS) >> 31) & 0x1)) &&
(--lock_check));
if (0 == lock_check) {
printf("HIFI pll lock Failed! - %4d MHz\n", pll_clk);
ret += RET_PLL_LOCK_FAIL;
} else {
printf("HIFI pll lock OK! - %4d MHz. Div8 - %4d MHz. ",
pll_clk, pll_clk >> PLL_DIV8_OFFSET);
Wr(CLKTREE_SPICC_CLK_CTRL, ((3 << 9) | (1 << 8) | (0 << 0)));
clk_msr_val = clk_util_clk_msr(16);
printf("CLKMSR(16) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, pll_clk >> PLL_DIV8_OFFSET)) {
printf(": Match\n");
} else {
printf(": MisMatch\n");
ret += RET_CLK_NOT_MATCH;
}
}
return ret;
}
static int hifi_pll_test_all(hifi_pll_cfg_t * hifi_pll_cfg)
{
unsigned int i = 0;
int ret = 0;
for (i = 0; i < (sizeof(hifi_pll_clk) / sizeof(uint32_t)); i++)
ret += hifi_pll_test(&(hifi_pll_cfg->hifi_pll[i]));
return ret;
}
static int gp_pll_test(gp_pll_set_t * gp_pll)
{
int ret = 0;
unsigned int pll_clk = 0;
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int clk_msr_val = 0;
if (gp_pll->pll_clk == 0)
pll_clk = (24 / ((gp_pll->pll_cntl0 >> 10) & 0x1F) *
(gp_pll->pll_cntl0 & 0xFF));
else
pll_clk = gp_pll->pll_clk;
lock_check = PLL_LOCK_CHECK_MAX;
do {
writel(gp_pll->pll_cntl0 | (1 << 29), ANACTRL_GPPLL_CTRL0);
writel(gp_pll->pll_cntl1, ANACTRL_GPPLL_CTRL1);
writel(gp_pll->pll_cntl2, ANACTRL_GPPLL_CTRL2);
writel(gp_pll->pll_cntl3, ANACTRL_GPPLL_CTRL3);
writel(gp_pll->pll_cntl4, ANACTRL_GPPLL_CTRL4);
writel(gp_pll->pll_cntl5, ANACTRL_GPPLL_CTRL5);
writel(gp_pll->pll_cntl6, ANACTRL_GPPLL_CTRL6);
_udelay(5);
writel(gp_pll->pll_cntl0 | (1 << 28) | (1 << 29),
ANACTRL_GPPLL_CTRL0);
_udelay(5);
writel(gp_pll->pll_cntl0 | (1 << 28),
ANACTRL_GPPLL_CTRL0);
_udelay(10);
writel(gp_pll->pll_cntl4 | (1 << 0), ANACTRL_GPPLL_CTRL4);
_udelay(100);
} while ((!((readl(ANACTRL_GPPLL_STS) >> 31) & 0x1)) && --lock_check);
if (0 == lock_check) {
printf("GP pll lock Failed! - %4d MHz\n", pll_clk);
ret = RET_PLL_LOCK_FAIL;
} else {
printf("GP pll lock OK! - %4d MHz. Div8 - %4d MHz. ",
pll_clk, pll_clk >> PLL_DIV8_OFFSET);
Wr(CLKTREE_SPICC_CLK_CTRL, ((4 << 9) | (1 << 8) | (0 << 0)));
/* get gp_pll_clk */
clk_msr_val = clk_util_clk_msr(16);
printf("CLKMSR(16) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, pll_clk >> PLL_DIV8_OFFSET)) {
printf(": Match\n");
} else {
printf(": MisMatch\n");
ret += RET_CLK_NOT_MATCH;
}
}
return ret;
}
static int gp_pll_test_all(gp0_pll_cfg_t * gp0_pll_cfg)
{
unsigned int i = 0;
int ret = 0;
for (i = 0; i < (sizeof(gp0_pll_cfg_t) / sizeof(gp_pll_set_t)); i++)
ret += gp_pll_test(&(gp0_pll_cfg->gp0_pll[i]));
return ret;
}
static int dds_pll_test(dds_pll_set_t * dds_pll)
{
int ret=0;
#if 0 //2020.02.20
unsigned int i=0, pll_clk=0;
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int clk_msr_val = 0;
for (i=0; i<(sizeof(ddspll_tbl)/sizeof(ddspll_tbl[0])); i++) {
if (((dds_pll->pll_cntl3)/(dds_pll->pll_cntl4)) == ((ddspll_tbl[i].CTS)/(ddspll_tbl[i].N))) {
pll_clk = ddspll_tbl[i].RATE;
}
}
do {
writel(dds_pll->misctop_cntl0, ANACTRL_MISCTOP_CTRL0);
writel(dds_pll->pll_cntl0, ANACTRL_AUDDDS_CTRL0);
writel(dds_pll->pll_cntl1, ANACTRL_AUDDDS_CTRL1);
writel(dds_pll->pll_cntl2, ANACTRL_AUDDDS_CTRL2);
writel(dds_pll->pll_cntl3, ANACTRL_AUDDDS_CTRL3);
writel(dds_pll->pll_cntl4, ANACTRL_AUDDDS_CTRL4);
writel((dds_pll->pll_cntl0 | (1<<29) | (1<<10) | (1<<11)) & ~(1<<28), ANACTRL_AUDDDS_CTRL0);
writel(dds_pll->pll_cntl1 | (1<<31), ANACTRL_AUDDDS_CTRL1);
//printf("gp lock_check: %4d\n", lock_check);
} while ((!((readl(ANACTRL_AUDDDS_STS)>>31)&0x1)) && --lock_check);
if (0 == lock_check) {
printf("dds pll lock Failed! - %4d MHz\n", pll_clk);
ret = RET_PLL_LOCK_FAIL;
}
else {
printf("dds pll lock OK! - %4d MHz.", pll_clk);
clk_msr_val = clk_util_clk_msr(44);
printf("CLKMSR(44) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, pll_clk)) {
printf(": Match\n");
}
else {
printf(": MisMatch\n");
ret += RET_CLK_NOT_MATCH;
}
}
#endif
return ret;
}
static int dds_pll_test_all(void)
{
#if 0 //2020.02.20
unsigned int i=0;
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int clk_msr_val = 0;
int ret=0;
//unsigned int ctrl0 = 0;
for (i=0; i<(sizeof(ddspll_tbl)/sizeof(ddspll_tbl[0])); i++) {
//ctrl0 = 0;
//ctrl0 = ctrl0 | ((gpll0_tbl[i].m)<<0) | ((gpll0_tbl[i].n)<<10);
do {
writel(0x4, ANACTRL_MISCTOP_CTRL0);
writel(0x50041340, ANACTRL_AUDDDS_CTRL0);
writel(0x0, ANACTRL_AUDDDS_CTRL1);
writel(0x0, ANACTRL_AUDDDS_CTRL2);
writel(ddspll_tbl[i].CTS, ANACTRL_AUDDDS_CTRL3);
writel(ddspll_tbl[i].N, ANACTRL_AUDDDS_CTRL4);
writel(0x60041f40, ANACTRL_AUDDDS_CTRL0);
writel(0x80000000, ANACTRL_AUDDDS_CTRL1);
} while((0 == ((Rd(ANACTRL_AUDDDS_STS) >> 31) & 0x1)) && (--lock_check));
if (0 == lock_check) {
printf("dds pll lock Failed! - %4d MHz\n", ddspll_tbl[i].RATE);
ret += RET_PLL_LOCK_FAIL;
}
else {
printf("dds pll lock OK! - %4d MHz.", ddspll_tbl[i].RATE);
//Wr(CLKTREE_SPICC_CLK_CTRL, ((4<<9) | (1<<8) | (7<<0)));
//printf("CLKTREE_SPICC_CLK_CTRL: 0x%8x\n", readl(CLKTREE_SPICC_CLK_CTRL));
clk_msr_val = clk_util_clk_msr(44);
printf("CLKMSR(44) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, ddspll_tbl[i].RATE)) {
printf(": Match\n");
}
else {
printf(": MisMatch\n");
ret += RET_CLK_NOT_MATCH;
}
}
}
return ret;
#endif
return 0;
}
static int usbphy_pll_test(usbphy_pll_set_t * usbphy_pll)
{
int ret = 0;
unsigned int pll_clk = 0;
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned long usbphy_base_cfg = 0xFE004000;
if ((usbphy_pll->pll_cntl0 & 0x1FF) == 0x14) {
pll_clk = 480;
} else {
printf("input frequency point is not support\n");
return -1;
}
writel(usbphy_pll->pll_cntl0, (usbphy_base_cfg + 0x40));
writel(usbphy_pll->pll_cntl1, (usbphy_base_cfg + 0x44));
writel(usbphy_pll->pll_cntl2, (usbphy_base_cfg + 0x48));
lock_check = PLL_LOCK_CHECK_MAX;
do {
update_bits((usbphy_base_cfg + 0x40), 1<<29, 1 << 29);
_udelay(10);
update_bits((usbphy_base_cfg + 0x40), 1<<29, 0);
_udelay(100);
//printf("ethphy lock_check: %4d\n", lock_check);
} while ((!((readl(usbphy_base_cfg + 0x40)>>31)&0x1)) && --lock_check);
if (0 == lock_check) {
printf("usbphy pll lock Failed! - %4d MHz\n", pll_clk);
ret = RET_PLL_LOCK_FAIL;
} else {
printf("usbphy pll lock OK! - %4d MHz.\n", pll_clk);
}
return ret;
}
static int usbphy_pll_test_all(void)
{
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
int ret=0;
unsigned long usbphy_base_cfg = 0xFE004000;
writel(0x09400414, (usbphy_base_cfg + 0x40));
writel(0x927e0000, (usbphy_base_cfg + 0x44));
writel(0xac5f69e5, (usbphy_base_cfg + 0x48));
writel(0x29400414, (usbphy_base_cfg + 0x40));
writel(0x09400414, (usbphy_base_cfg + 0x40));
do {
update_bits((usbphy_base_cfg + 0x40), 1<<29, 1 << 29);
_udelay(10);
update_bits((usbphy_base_cfg + 0x40), 1<<29, 0);
_udelay(100);
//printf("usbphy lock_check: %4d\n", lock_check);
} while ((!((readl(usbphy_base_cfg + 0x40)>>31)&0x1)) && --lock_check);
if (0 == lock_check) {
printf("usbphy pll lock Failed! - 480MHz\n");
ret += RET_PLL_LOCK_FAIL;
} else {
printf("usbphy pll lock OK! - 480MHz.\n");
}
return ret;
}
static int ethphy_pll_test(ethphy_pll_set_t * ethphy_pll)
{
int ret = 0;
unsigned int pll_clk=0;
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int clk_msr_val = 0;
if ((ethphy_pll->pll_cntl0 & 0x1FF) == 0xA) {
pll_clk = 500;
} else {
printf("input frequency point is not support\n");
return -1;
}
do {
writel(ethphy_pll->pll_cntl0 | 0x30000000, ETH_PLL_CTL0);
writel(ethphy_pll->pll_cntl1, ETH_PLL_CTL1);
writel(ethphy_pll->pll_cntl2, ETH_PLL_CTL2);
_udelay(150);
writel(ethphy_pll->pll_cntl0 | 0x10000000, ETH_PLL_CTL0);
_udelay(150);
} while ((!((readl(ETH_PLL_CTL0)>>30)&0x1))&& --lock_check);
if (0 == lock_check) {
printf("ETHPHY pll lock Failed! - %4d MHz\n", pll_clk);
ret = RET_PLL_LOCK_FAIL;
} else {
printf("ETHPHY pll lock OK! - %4d MHz. ", pll_clk);
/* get ethphy_pll_clk */
clk_msr_val = clk_util_clk_msr(64)<<2;
printf("CLKMSR(64) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, pll_clk)) {
printf(": Match\n");
} else {
printf(": MisMatch\n");
ret = RET_CLK_NOT_MATCH;
}
}
return ret;
}
static int ethphy_pll_test_all(void)
{
unsigned int lock_check = PLL_LOCK_CHECK_MAX;
unsigned int clk_msr_val = 0;
int ret = 0;
do {
writel(0x9c0040a | 0x30000000, ETH_PLL_CTL0);
writel(0x927e0000, ETH_PLL_CTL1);
writel(0xac5f49e5, ETH_PLL_CTL2);
writel(0x00000000, ETH_PLL_CTL3);
_udelay(150);
writel(0x9c0040a | 0x10000000, ETH_PLL_CTL0);
_udelay(150);
} while ((!((readl(ETH_PLL_CTL0)>>30)&0x1))&& --lock_check);
if (0 == lock_check) {
printf("ethphy pll lock Failed! - 500MHz\n");
ret += RET_PLL_LOCK_FAIL;
} else {
printf("ethphy pll lock OK! - 500MHz. ");
/* get ethphy_pll_clk */
clk_msr_val = clk_util_clk_msr(64)<<2;
printf("CLKMSR(64) - %4d MHz ", clk_msr_val);
if (clk_around(clk_msr_val, 500)) {
printf(": Match\n");
} else {
printf(": MisMatch\n");
ret += RET_CLK_NOT_MATCH;
}
}
return ret;
}
static int pll_test_all(unsigned char * pll_list)
{
int ret = 0;
unsigned char i = 0;
for (i = 0; i < PLL_ENUM; i++) {
switch (pll_list[i]) {
case PLL_SYS:
ret = sys_pll_test_all(&sys_pll_cfg);
pll_report(ret, STR_PLL_TEST_SYS);
break;
case PLL_FIX:
ret = fix_pll_test();
pll_report(ret, STR_PLL_TEST_FIX);
break;
case PLL_DDR:
ret = ddr_pll_test();
pll_report(ret, STR_PLL_TEST_DDR);
break;
case PLL_HIFI:
ret = hifi_pll_test_all(&hifi_pll_cfg);
pll_report(ret, STR_PLL_TEST_HIFI);
break;
case PLL_GP:
ret = gp_pll_test_all(&gp0_pll_cfg);
pll_report(ret, STR_PLL_TEST_GP);
break;
case PLL_DDS:
ret = dds_pll_test_all();
pll_report(ret, STR_PLL_TEST_DDS);
break;
case PLL_USBPHY:
ret = usbphy_pll_test_all();
pll_report(ret, STR_PLL_TEST_USBPHY);
break;
case PLL_ETHPHY:
ret = ethphy_pll_test_all();
pll_report(ret, STR_PLL_TEST_ETHPHY);
break;
default:
break;
}
}
return ret;
}
int pll_test(int argc, char * const argv[])
{
int ret = 0;
sys_pll_set_t sys_pll_set = {0};
hifi_pll_set_t hifi_pll_set = {0};
gp_pll_set_t gp_pll_set = {0};
dds_pll_set_t dds_pll_set = {0};
usbphy_pll_set_t usbphy_pll_set = {0};
ethphy_pll_set_t ethphy_pll_set = {0};
unsigned char plls[PLL_ENUM] = {
PLL_SYS,
0xff,// PLL_FIX, //0xff will skip this pll
0xff,// PLL_DDR,
PLL_HIFI,
PLL_GP,
0xff,//PLL_DDS
0xff,//PLL_USBPHY
0xff,//PLL_ETHPHY
};
if (0 == strcmp(STR_PLL_TEST_ALL, argv[1])) {
printf("Test all plls\n");
pll_test_all(plls);
} else if(0 == strcmp(STR_PLL_TEST_SYS, argv[1])) {
if (argc == 2) {
ret = sys_pll_test_all(&sys_pll_cfg);
pll_report(ret, STR_PLL_TEST_SYS);
} else if (argc != 6) {
printf("%s pll test: args error\n", STR_PLL_TEST_SYS);
return -1;
} else {
sys_pll_set.pll_cntl0 = simple_strtoul(argv[2],
NULL, 16);
sys_pll_set.pll_cntl1 = simple_strtoul(argv[3],
NULL, 16);
sys_pll_set.pll_cntl2 = simple_strtoul(argv[4],
NULL, 16);
sys_pll_set.pll_cntl3 = simple_strtoul(argv[5],
NULL, 16);
ret = sys_pll_test(&sys_pll_set);
pll_report(ret, STR_PLL_TEST_SYS);
}
} else if (0 == strcmp(STR_PLL_TEST_HIFI, argv[1])) {
if (argc == 2) {
ret = hifi_pll_test_all(&hifi_pll_cfg);
pll_report(ret, STR_PLL_TEST_HIFI);
} else if (argc != 7){
printf("%s pll test: args error\n", STR_PLL_TEST_HIFI);
return -1;
} else {
hifi_pll_set.pll_cntl0 = simple_strtoul(argv[2],
NULL, 16);
hifi_pll_set.pll_cntl1 = simple_strtoul(argv[3],
NULL, 16);
hifi_pll_set.pll_cntl2 = simple_strtoul(argv[4],
NULL, 16);
hifi_pll_set.pll_cntl3 = simple_strtoul(argv[5],
NULL, 16);
hifi_pll_set.pll_cntl4 = simple_strtoul(argv[6],
NULL, 16);
ret = hifi_pll_test(&hifi_pll_set);
pll_report(ret, STR_PLL_TEST_HIFI);
}
} else if (0 == strcmp(STR_PLL_TEST_GP, argv[1])) {
if (argc == 2) {
ret = gp_pll_test_all(&gp0_pll_cfg);
pll_report(ret, STR_PLL_TEST_GP);
} else if (argc != 9) {
printf("%s pll test: args error\n", STR_PLL_TEST_GP);
return -1;
} else {
gp_pll_set.pll_cntl0 = simple_strtoul(argv[2],
NULL, 16);
gp_pll_set.pll_cntl1 = simple_strtoul(argv[3],
NULL, 16);
gp_pll_set.pll_cntl2 = simple_strtoul(argv[4],
NULL, 16);
gp_pll_set.pll_cntl3 = simple_strtoul(argv[5],
NULL, 16);
gp_pll_set.pll_cntl4 = simple_strtoul(argv[6],
NULL, 16);
gp_pll_set.pll_cntl5 = simple_strtoul(argv[7],
NULL, 16);
gp_pll_set.pll_cntl6 = simple_strtoul(argv[8],
NULL, 16);
ret = gp_pll_test(&gp_pll_set);
pll_report(ret, STR_PLL_TEST_GP);
}
} else if (0 == strcmp(STR_PLL_TEST_DDR, argv[1])) {
printf("%s pll not support now\n", STR_PLL_TEST_DDR);
return -1;
} else if (0 == strcmp(STR_PLL_TEST_FIX, argv[1])) {
printf("%s pll not support now\n", STR_PLL_TEST_FIX);
return -1;
} else if (0 == strcmp(STR_PLL_TEST_DDS, argv[1])) {
if (argc == 2) {
ret = dds_pll_test_all();
pll_report(ret, STR_PLL_TEST_DDS);
} else if (argc != 8) {
printf("%s pll test: args error\n", STR_PLL_TEST_DDS);
return -1;
} else {
dds_pll_set.misctop_cntl0 = simple_strtoul(argv[2],
NULL, 16);
dds_pll_set.pll_cntl0 = simple_strtoul(argv[3],
NULL, 16);
dds_pll_set.pll_cntl1 = simple_strtoul(argv[4],
NULL, 16);
dds_pll_set.pll_cntl2 = simple_strtoul(argv[5],
NULL, 16);
dds_pll_set.pll_cntl3 = simple_strtoul(argv[6],
NULL, 16);
dds_pll_set.pll_cntl4 = simple_strtoul(argv[7],
NULL, 16);
ret = dds_pll_test(&dds_pll_set);
pll_report(ret, STR_PLL_TEST_DDS);
}
} else if (0 == strcmp(STR_PLL_TEST_USBPHY, argv[1])) {
if (argc == 2) {
ret = usbphy_pll_test_all();
pll_report(ret, STR_PLL_TEST_USBPHY);
} else if (argc != 5) {
printf("%s pll test: args error\n",
STR_PLL_TEST_USBPHY);
return -1;
} else {
usbphy_pll_set.pll_cntl0 = simple_strtoul(argv[2],
NULL, 16);
usbphy_pll_set.pll_cntl1 = simple_strtoul(argv[3],
NULL, 16);
usbphy_pll_set.pll_cntl2 = simple_strtoul(argv[4],
NULL, 16);
ret = usbphy_pll_test(&usbphy_pll_set);
pll_report(ret, STR_PLL_TEST_USBPHY);
}
} else if (0 == strcmp(STR_PLL_TEST_ETHPHY, argv[1])) {
if (argc == 2) {
ret = ethphy_pll_test_all();
pll_report(ret, STR_PLL_TEST_ETHPHY);
} else if (argc != 5) {
printf("%s pll test: args error\n",
STR_PLL_TEST_ETHPHY);
return -1;
} else {
ethphy_pll_set.pll_cntl0 = simple_strtoul(argv[2],
NULL, 16);
ethphy_pll_set.pll_cntl1 = simple_strtoul(argv[3],
NULL, 16);
ethphy_pll_set.pll_cntl2 = simple_strtoul(argv[4],
NULL, 16);
ret = ethphy_pll_test(&ethphy_pll_set);
pll_report(ret, STR_PLL_TEST_ETHPHY);
}
}
return 0;
}