Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hal/imxrt117x: fix Fractional PLL configuration and enable PLL1 #372

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 142 additions & 12 deletions hal/armv7m/imxrt/117x/imxrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "imxrt.h"
#include "../../cpu.h"
#include "../otp.h"
#include "board_config.h"

#include <hal/hal.h>
#include <lib/lib.h>
Expand Down Expand Up @@ -56,8 +57,9 @@ enum {
/* OSC */
osc_48m_ctrl = 0x04, osc_24m_ctrl = 0x08, osc_400m_ctrl0 = 0x10, osc_400m_ctrl1 = 0x14, osc_400m_ctrl2 = 0x18,
osc_16m_ctrl = 0x30,

/* PLL */
arm_pll_ctrl = 0x80, sys_pll3_ctrl = 0x84, sys_pll3_update= 0x88, sys_pll3_pfd = 0x8c,
arm_pll_ctrl = 0x80, sys_pll3_ctrl = 0x84, sys_pll3_update = 0x88, sys_pll3_pfd = 0x8c,
sys_pll2_ctrl = 0x90, sys_pll2_update = 0x94, sys_pll2_ss = 0x98, sys_pll2_pfd = 0x9c,
sys_pll2_mfd = 0xa8, sys_pll1_ss = 0xac, sys_pll1_ctrl = 0xb0, sys_pll1_denominator = 0xb4,
sys_pll1_numerator = 0xb8, sys_pll1_div_select = 0xbc, pll_audio_ctrl = 0xc0, pll_audio_ss = 0xc4,
Expand All @@ -68,12 +70,22 @@ enum {
pmu_ldo_pll = 0x140, pmu_ldo_lpsr_ana = 0x144, pmu_ldo_lpsr_dig2 = 0x148, pmu_ldo_lpsr_dig = 0x14c,
pmu_ref_ctrl = 0x15c,


/* ANATOP AI */
vddsoc_ai_ctrl = 0x208, vddsoc_ai_wdata = 0x20c, vddsoc_ai_rdata = 0x210
vddsoc_ai_ctrl = 0x208, vddsoc_ai_wdata = 0x20c, vddsoc_ai_rdata = 0x210,
vddsoc2pll_ai_ctrl_1g = 0x214, vddsoc2pll_ai_wdata_1g = 0x218, vddsoc2pll_ai_rdata_1g = 0x21c,
vddsoc2pll_ai_ctrl_audio = 0x220, vddsoc2pll_ai_wdata_audio = 0x224, vddsoc2pll_ai_rdata_audio = 0x228,
vddsoc2pll_ai_ctrl_video = 0x22c, vddsoc2pll_ai_wdata_video = 0x230, vddsoc2pll_ai_rdata_video = 0x234
};


/* Fractional PLL (AI interface) */
enum {
frac_pll_ctrl0 = 0x00, frac_pll_ctrl0_set = 0x04, frac_pll_ctrl0_clr = 0x08, frac_pll_ctrl0_tog = 0x0c,
frac_pll_ss = 0x10, frac_pll_ss_set = 0x14, frac_pll_ss_clr = 0x18, frac_pll_ss_tog = 0x1c,
frac_pll_num = 0x20, frac_pll_num_set = 0x24, frac_pll_num_clr = 0x28, frac_pll_num_tog = 0x2c,
frac_pll_denom = 0x30, frac_pll_denom_set = 0x34, frac_pll_denom_clr = 0x38, frac_pll_denom_tog = 0x3c
};

struct {
volatile u32 *aips[4];
volatile u32 *stk;
Expand Down Expand Up @@ -470,6 +482,58 @@ static void _imxrt_delay(u32 ticks)
}


__attribute__((unused)) static u32 _imxrt_vddsoc2PllAiRead(int ai_ctrl_addr, int ai_reg)
{
u32 pre_tog_done, tog_done, t;

pre_tog_done = *(imxrt_common.anadig_pll + ai_ctrl_addr) & (1uL << 9u);

t = *(imxrt_common.anadig_pll + ai_ctrl_addr) & ~((1uL << 16u) | 0xff);
t |= (1uL << 16u) | (ai_reg & 0xff);

/* Write AI_CTRL, RWB=1 */
*(imxrt_common.anadig_pll + ai_ctrl_addr) = t;

/* Toggle AI_CTRL */
*(imxrt_common.anadig_pll + ai_ctrl_addr) ^= (1uL << 8u);

tog_done = *(imxrt_common.anadig_pll + ai_ctrl_addr) & (1uL << 9u);

/* Wait for TOGGLE_DONE */
do {
tog_done = *(imxrt_common.anadig_pll + ai_ctrl_addr) & (1uL << 9u);
} while (tog_done == pre_tog_done);

/* Read AI_RDATA */
return *(imxrt_common.anadig_pll + (ai_ctrl_addr + 0x8));
}


static void _imxrt_vddsoc2PllAiWrite(int ai_ctrl_addr, int ai_reg, u32 data)
{
u32 pre_tog_done, tog_done, t;

pre_tog_done = *(imxrt_common.anadig_pll + ai_ctrl_addr) & (1uL << 9u);

t = *(imxrt_common.anadig_pll + ai_ctrl_addr) & ~((1uL << 16u) | 0xff);
t |= ai_reg & 0xff;

/* Write AI_CTRL, RWB=0 */
*(imxrt_common.anadig_pll + ai_ctrl_addr) = t;

/* Write AI_WDATA */
*(imxrt_common.anadig_pll + (ai_ctrl_addr + 0x4)) = data;

/* Toggle AI_CTRL */
*(imxrt_common.anadig_pll + ai_ctrl_addr) ^= (1uL << 8u);

/* Wait for TOGGLE_DONE */
do {
tog_done = *(imxrt_common.anadig_pll + ai_ctrl_addr) & (1uL << 9u);
} while (tog_done == pre_tog_done);
}


static void _imxrt_setPllBypass(u8 clk_pll, u8 enable)
{
/* clang-format off */
Expand All @@ -480,9 +544,7 @@ static void _imxrt_setPllBypass(u8 clk_pll, u8 enable)
(*(imxrt_common.anadig_pll + arm_pll_ctrl) & ~(1uL << 17u));
break;
case clk_pllsys1:
*(imxrt_common.anadig_pll + sys_pll1_ctrl) = (enable != 0) ?
(*(imxrt_common.anadig_pll + sys_pll1_ctrl) | (1uL << 16u)) :
(*(imxrt_common.anadig_pll + sys_pll1_ctrl) & ~(1uL << 16u));
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, (enable != 0) ? frac_pll_ctrl0_set : frac_pll_ctrl0_clr, (1uL << 16u));
break;
case clk_pllsys2:
*(imxrt_common.anadig_pll + sys_pll2_ctrl) = (enable != 0) ?
Expand All @@ -495,10 +557,10 @@ static void _imxrt_setPllBypass(u8 clk_pll, u8 enable)
(*(imxrt_common.anadig_pll + sys_pll3_ctrl) & ~(1uL << 16u));
break;
case clk_pllaudio:
/* TODO: access through ANATOP AI */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_audio, (enable != 0) ? frac_pll_ctrl0_set : frac_pll_ctrl0_clr, (1uL << 16u));
break;
case clk_pllvideo:
/* TODO: access through ANATOP AI */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_video, (enable != 0) ? frac_pll_ctrl0_set : frac_pll_ctrl0_clr, (1uL << 16u));
break;
default:
break;
Expand Down Expand Up @@ -769,13 +831,78 @@ int _imxrt_setPfdPllFracClock(u8 pfd, u8 clk_pll, u8 frac)
}


static void _imxrt_deinitSysPll1(void)
__attribute__((unused)) static void _imxrt_deinitSysPll1(void)
{
/* Disable PLL1 and div2, div5 */
*(imxrt_common.anadig_pll + sys_pll1_ctrl) &= ~((1uL << 26u) | (1uL << 25u) | (1uL << 13u));

/* Gate PLL1 */
*(imxrt_common.anadig_pll + sys_pll1_ctrl) |= 1uL << 14u;

/* Disable PLL1 */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_clr, (1uL << 15u));

/* Power down PLL1 */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_clr, (1uL << 14u));

/* Disable Spread Spectrum */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ss_clr, (1uL << 15u));

/* Disable ldo */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_clr, (1uL << 22u));
}


__attribute__((unused)) static void _imxrt_initSysPll1(void)
{
_imxrt_pmuEnablePllLdo();

_imxrt_setPllBypass(clk_pllsys1, 1);

/* Enable SYS_PLL1 clk output */
*(imxrt_common.anadig_pll + sys_pll1_ctrl) |= (1uL << 13u);

/* Configure Fractional PLL: div, num, denom */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_set, 41u);
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_denom, 0x0fffffff);
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_num, 0x0aaaaaaa);
/* Disable SS */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ss_clr, (1uL << 15));

/* Enable ldo */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_set, (1uL << 22u));
_imxrt_delay(100u * 1000u);

/* POWERUP */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_set, (1uL << 14u) | (1uL << 13u));

/* assert HOLD_RING_OFF */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_set, (1uL << 13u));
/* Wait until PLL lock time is halfway through */
/* Lock time is 11250 ref cycles */
_imxrt_delay(5625u);
/* de-assert HOLD_RING_OFF */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_clr, (1uL << 13u));

/* Wait till PLL lock time is complete */
while ((*(imxrt_common.anadig_pll + sys_pll1_ctrl) & (1uL << 29u)) != (1uL << 29u)) {
}

/* Enable PLL1 */
_imxrt_vddsoc2PllAiWrite(vddsoc2pll_ai_ctrl_1g, frac_pll_ctrl0_set, (1uL << 15u));

/* Disable PLL gate */
*(imxrt_common.anadig_pll + sys_pll1_ctrl) &= ~(1uL << 14u);

#ifdef CLOCK_SYS_PLL1DIV2_ENABLE
*(imxrt_common.anadig_pll + sys_pll1_ctrl) |= (1uL << 25);
#endif

#ifdef CLOCK_SYS_PLL1DIV5_ENABLE
*(imxrt_common.anadig_pll + sys_pll1_ctrl) |= (1uL << 26);
#endif

_imxrt_setPllBypass(clk_pllsys1, 0);
}


Expand Down Expand Up @@ -938,11 +1065,14 @@ static void _imxrt_initClocks(void)
/* imxrt_common.cpuclk = 696000000u; */
#endif

#ifdef CLOCK_SYS_PLL1_ENABLE
/* Initialize 1Gig ethernet PLL */
_imxrt_initSysPll1();
#else
/* Bypass and deinitialize SYS_PLL1 */
_imxrt_setPllBypass(clk_pllsys1, 1);

/* Deinit 1Gig ethernet PLL */
_imxrt_deinitSysPll1();

#endif
/* TODO: Init PLL2 fixed 528 MHz */
/* _imxrt_initSysPll2(); */

Expand Down
Loading