imx9_clockconfig: Add way to set PLL frequencies
This patch adds a way to configure PLL frequencies. The configuration is given by board logic. These values should only be modified by the bootloader, but we don't have that yet so the flag is never activated.
This commit is contained in:
parent
e3f4749a3c
commit
0d9a3d94eb
@ -310,10 +310,6 @@ config IMX9_LPSPI
|
||||
bool "LPSPI support"
|
||||
default n
|
||||
|
||||
config IMX9_PLL
|
||||
bool "PLL setup support"
|
||||
default n
|
||||
|
||||
menu "LPI2C Peripherals"
|
||||
|
||||
menuconfig IMX9_LPI2C1
|
||||
|
@ -168,6 +168,10 @@
|
||||
|
||||
#define CCM_GPR_SH_GPR_SHIFT (0) /* Bits 0-31: General purpose register, shared for all CPU domains (GPR) */
|
||||
#define CCM_GPR_SH_GPR_MASK (0xffffffff << CCM_GPR_SH_GPR_SHIFT)
|
||||
#define CCM_GPR_A55_CLK_SEL_SHIFT (0)
|
||||
#define CCM_GPR_A55_CLK_SEL_MASK (0x01 << CCM_GPR_A55_CLK_SEL_SHIFT)
|
||||
#define CCM_GPR_A55_CLK_SEL_CCM (0 << 0)
|
||||
#define CCM_GPR_A55_CLK_SEL_PLL (1 << 0)
|
||||
|
||||
/* General Purpose Register (GPR_SHAREDn_AUTHEN, n=0..7) */
|
||||
|
||||
@ -561,6 +565,12 @@
|
||||
#define CCM_LPCG_TMC 125
|
||||
#define CCM_LPCG_PMRO 126
|
||||
|
||||
/* Shared register indices */
|
||||
|
||||
#define CCM_SHARED_EXT_CLK 0
|
||||
#define CCM_SHARED_A55_CLK 1
|
||||
#define CCM_SHARED_DRAM_CLK 2
|
||||
|
||||
/* Other parameters */
|
||||
|
||||
#define ROOT_MUX_MAX 4 /* Count of root clock MUX options */
|
||||
|
@ -175,7 +175,7 @@
|
||||
#define PLL_DFS_MFN_MASK (0x7 << PLL_DFS_MFN_SHIFT)
|
||||
#define PLL_DFS_MFN(n) (((n) << PLL_DFS_MFN_SHIFT) & PLL_DFS_MFN_MASK)
|
||||
#define PLL_DFS_MFI_SHIFT (8) /* Bits 8-15: MFI */
|
||||
#define PLL_DFS_MFI_MASK (0xFF << PLL_DFS_MFI_SHIFT)
|
||||
#define PLL_DFS_MFI_MASK (0xff << PLL_DFS_MFI_SHIFT)
|
||||
#define PLL_DFS_MFI(n) (((n) << PLL_DFS_MFI_SHIFT) & PLL_DFS_MFI_MASK)
|
||||
|
||||
/* PLL Dividers (DIV) */
|
||||
@ -192,35 +192,4 @@
|
||||
#define PLL_DFS_STATUS_DFS_OK_MASK (0x7 << PLL_DFS_STATUS_DFS_OK_SHIFT)
|
||||
#define PLL_DFS_STATUS_DFS_OK(n) (((n) << PLL_DFS_STATUS_DFS_OK_SHIFT) & PLL_DFS_STATUS_DFS_OK_MASK)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct pll_parms
|
||||
{
|
||||
/* Integer part (DIV) */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t rdiv; /* Input clock divider */
|
||||
uint32_t odiv; /* PLL output divider */
|
||||
uint32_t mfi; /* PLL integer divider */
|
||||
};
|
||||
|
||||
/* Fractional part (NUMERATOR / DENOMINATOR) */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t mfn; /* PLL fractional divider numerator */
|
||||
uint32_t mfd; /* PLL fractional divider denominator */
|
||||
};
|
||||
};
|
||||
|
||||
struct pfd_parms
|
||||
{
|
||||
uint32_t mfi; /* PLL integer divider */
|
||||
uint32_t mfn; /* PLL fractional divider numerator */
|
||||
bool divby2_en; /* Enable the divide-by-2 output */
|
||||
};
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PLL_H_*/
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "arm64_mmu.h"
|
||||
|
||||
#include "imx9_boot.h"
|
||||
#include "imx9_clockconfig.h"
|
||||
#include "imx9_serial.h"
|
||||
#include "imx9_gpio.h"
|
||||
#include "imx9_lowputc.h"
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "barriers.h"
|
||||
|
||||
#include "arm64_internal.h"
|
||||
@ -42,6 +44,12 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* The base oscillator frequency is 24MHz */
|
||||
|
||||
#define XTAL_FREQ 24000000u
|
||||
|
||||
/* Common barrier */
|
||||
|
||||
#define mb() \
|
||||
do \
|
||||
{ \
|
||||
@ -50,16 +58,12 @@
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* The base oscillator frequency is 24MHz */
|
||||
|
||||
#define XTAL_FREQ 24000000u
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IMX9_PLL
|
||||
static int pll_init(uintptr_t reg, bool frac, struct pll_parms *parm)
|
||||
#ifdef CONFIG_IMX9_BOOTLOADER
|
||||
static int pll_init(uintptr_t reg, bool frac, struct pll_parms_s *parm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
@ -104,7 +108,7 @@ static int pll_init(uintptr_t reg, bool frac, struct pll_parms *parm)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm)
|
||||
static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms_s *pfdparm)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
uint32_t div;
|
||||
@ -136,12 +140,13 @@ static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm)
|
||||
/* Bypass and disable DFS */
|
||||
|
||||
putreg32(PLL_DFS_BYPASS_EN, PLL_SET(ctrl));
|
||||
putreg32(PLL_DFS_CLKOUT_EN | PLL_DFS_ENABLE, PLL_CLR(ctrl));
|
||||
putreg32(PLL_DFS_CLKOUT_EN | PLL_DFS_CLKOUT_DIVBY2_EN | PLL_DFS_ENABLE,
|
||||
PLL_CLR(ctrl));
|
||||
|
||||
/* Set the divider */
|
||||
|
||||
val = PLL_DFS_MFI(pfdparm->mfi) | PLL_DFS_MFN(pfdparm->mfn);
|
||||
putreg32(val, PLL_SET(div));
|
||||
putreg32(val, PLL_VAL(div));
|
||||
|
||||
/* Enable (or disable) the divby2 output */
|
||||
|
||||
@ -163,10 +168,16 @@ static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm)
|
||||
|
||||
while (!(getreg32(PLL_DFS_STATUS(reg)) & (1 << pfd)));
|
||||
|
||||
/* Then disable bypass */
|
||||
|
||||
putreg32(PLL_DFS_BYPASS_EN, PLL_CLR(ctrl));
|
||||
mb();
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t calculate_vco_freq(const struct pll_parms *parm, bool frac)
|
||||
static uint32_t calculate_vco_freq(const struct pll_parms_s *parm, bool frac)
|
||||
{
|
||||
/* Base clock is common for all VCO:s */
|
||||
|
||||
@ -183,7 +194,7 @@ static uint32_t calculate_vco_freq(const struct pll_parms *parm, bool frac)
|
||||
|
||||
static uint32_t vco_freq_out(uintptr_t reg, bool frac)
|
||||
{
|
||||
struct pll_parms parm;
|
||||
struct pll_parms_s parm;
|
||||
uint32_t ctrl;
|
||||
uint32_t status;
|
||||
uint32_t div;
|
||||
@ -193,7 +204,6 @@ static uint32_t vco_freq_out(uintptr_t reg, bool frac)
|
||||
ctrl = getreg32(PLL_CTRL(reg));
|
||||
if ((ctrl & PLL_CTRL_POWERUP) == 0)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -202,7 +212,6 @@ static uint32_t vco_freq_out(uintptr_t reg, bool frac)
|
||||
status = getreg32(PLL_PLL_STATUS(reg));
|
||||
if ((status & PLL_PLL_STATUS_PLL_LOCK) == 0)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -250,7 +259,6 @@ static uint32_t pll_freq_out(uintptr_t reg, bool frac)
|
||||
|
||||
if ((ctrl & PLL_CTRL_CLKMUX_EN) == 0)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -284,7 +292,7 @@ static uint32_t pll_freq_out(uintptr_t reg, bool frac)
|
||||
|
||||
static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2)
|
||||
{
|
||||
struct pfd_parms parm;
|
||||
struct pfd_parms_s parm;
|
||||
uint32_t ctrl;
|
||||
uint32_t div;
|
||||
uint32_t vco;
|
||||
@ -338,14 +346,12 @@ static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2)
|
||||
|
||||
/* Populate the DFS parameters */
|
||||
|
||||
parm.mfi = (div & PLL_DFS_MFI_MASK) >> PLL_DFS_MFI_SHIFT;
|
||||
parm.mfn = (div & PLL_DFS_MFN_MASK) >> PLL_DFS_MFN_SHIFT;
|
||||
parm.mfi = (div & PLL_DFS_MFI_MASK) >> PLL_DFS_MFI_SHIFT;
|
||||
parm.mfn = (div & PLL_DFS_MFN_MASK) >> PLL_DFS_MFN_SHIFT;
|
||||
|
||||
return ((uint64_t)vco * 5) / (parm.mfi * 5 + parm.mfn) / div2;
|
||||
return ((uint64_t)vco * 5) / (parm.mfi * 5 + parm.mfn) / div2;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -362,29 +368,34 @@ static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2)
|
||||
|
||||
void imx9_clockconfig(void)
|
||||
{
|
||||
/* REVISIT: Define a clock config and run it. For now we rely on the fact
|
||||
* that the boot code + bootloader will have set us up.
|
||||
*
|
||||
* During boot the ROM code initializes the PLL clocks as follows:
|
||||
*
|
||||
* - OSC24M : 24 MHz
|
||||
* - ARMPLL : 2000 MHz
|
||||
* - ARMPLL_OUT : 2000 MHz
|
||||
* - DRAMPLL : 1000 MHz
|
||||
* - SYSPLL1 : 4000 MHz
|
||||
* - SYSPLL_PFD0 : 1000 MHz
|
||||
* - SYSPLL_PFD1 : 800 MHz
|
||||
* - SYSPLL_PFD2 : 625 MHz
|
||||
* - AUDIOPLL : OFF
|
||||
* - AUDIOPLL_OUT : OFF
|
||||
* - VIDEOPLL : OFF
|
||||
* - VIDEOPLL_OUT : OFF
|
||||
*
|
||||
* After reset all clock sources (OSCPLL) and root clocks (CLOCK_ROOT) are
|
||||
* running, but gated (LPCG).
|
||||
*
|
||||
* By default, all peripheral root clocks are set to the 24 MHz oscillator.
|
||||
*/
|
||||
#ifdef CONFIG_IMX9_BOOTLOADER
|
||||
struct imx9_pll_cfg_s pll_cfgs[] = PLL_CFGS;
|
||||
struct imx9_pfd_cfg_s pfd_cfgs[] = PFD_CFGS;
|
||||
struct imx9_pll_cfg_s pll_arm = ARMPLL_CFG;
|
||||
int i;
|
||||
|
||||
/* Set the CPU clock */
|
||||
|
||||
putreg32(IMX9_CCM_GPR_SH_CLR(CCM_SHARED_A55_CLK), CCM_GPR_A55_CLK_SEL_PLL);
|
||||
pll_init(pll_arm.reg, pll_arm.frac, &pll_arm.parms);
|
||||
putreg32(IMX9_CCM_GPR_SH_SET(CCM_SHARED_A55_CLK), CCM_GPR_A55_CLK_SEL_PLL);
|
||||
|
||||
/* Run the PLL configuration */
|
||||
|
||||
for (i = 0; i < nitems(pll_cfgs); i++)
|
||||
{
|
||||
struct imx9_pll_cfg_s *cfg = &pll_cfgs[i];
|
||||
pll_init(cfg->reg, cfg->frac, &cfg->parms);
|
||||
}
|
||||
|
||||
/* Run the PFD configuration */
|
||||
|
||||
for (i = 0; i < nitems(pfd_cfgs); i++)
|
||||
{
|
||||
struct imx9_pfd_cfg_s *cfg = &pfd_cfgs[i];
|
||||
pll_pfd_init(cfg->reg, cfg->pfd, &cfg->parms);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -29,6 +29,85 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PLL_PARMS(_rdiv, _odiv, _mfi, _mfn, _mfd) \
|
||||
{ \
|
||||
.rdiv = (_rdiv), \
|
||||
.odiv = (_odiv), \
|
||||
.mfi = (_mfi), \
|
||||
.mfn = (_mfn), \
|
||||
.mfd = (_mfd), \
|
||||
}
|
||||
|
||||
#define PLL_CFG(_reg, _frac, _parms) \
|
||||
{ \
|
||||
.reg = (_reg), \
|
||||
.frac = (_frac), \
|
||||
.parms = _parms, \
|
||||
}
|
||||
|
||||
#define PFD_PARMS(_mfi, _mfn, _div2) \
|
||||
{ \
|
||||
.mfi = (_mfi), \
|
||||
.mfn = (_mfn), \
|
||||
.divby2_en = (_div2) \
|
||||
}
|
||||
|
||||
#define PFD_CFG(_reg, _pfd, _parms) \
|
||||
{ \
|
||||
.reg = (_reg), \
|
||||
.pfd = (_pfd), \
|
||||
.parms = _parms, \
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct pll_parms_s
|
||||
{
|
||||
/* Integer part (DIV) */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t rdiv; /* Input clock divider */
|
||||
uint32_t odiv; /* PLL output divider */
|
||||
uint32_t mfi; /* PLL integer divider */
|
||||
};
|
||||
|
||||
/* Fractional part (NUMERATOR / DENOMINATOR) */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t mfn; /* PLL fractional divider numerator */
|
||||
uint32_t mfd; /* PLL fractional divider denominator */
|
||||
};
|
||||
};
|
||||
|
||||
struct pfd_parms_s
|
||||
{
|
||||
uint32_t mfi; /* PLL integer divider */
|
||||
uint32_t mfn; /* PLL fractional divider numerator */
|
||||
bool divby2_en; /* Enable the divide-by-2 output */
|
||||
};
|
||||
|
||||
struct imx9_pll_cfg_s
|
||||
{
|
||||
uintptr_t reg; /* The PLL register base */
|
||||
bool frac; /* Fractional PLL ? */
|
||||
struct pll_parms_s parms; /* The PLL parameters */
|
||||
};
|
||||
|
||||
struct imx9_pfd_cfg_s
|
||||
{
|
||||
uintptr_t reg; /* The PLL register base */
|
||||
int pfd; /* The PFD number */
|
||||
struct pfd_parms_s parms; /* The PFD parameters */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
@ -88,6 +88,39 @@
|
||||
#define MUX_LPSPI6_CS IOMUX_CFG(IOMUXC_PAD_GPIO_IO00_GPIO2_IO00, IOMUX_GPIO_DEFAULT, IOMUXC_MUX_SION_ON)
|
||||
#define GPIO_LPSPI6_CS (GPIO_PORT2 | GPIO_PIN0 | GPIO_OUTPUT | GPIO_OUTPUT_ONE)
|
||||
|
||||
/* Set the PLL clocks as follows:
|
||||
*
|
||||
* - OSC24M : 24 MHz
|
||||
* - ARMPLL_OUT : 1692 MHz
|
||||
* - DRAMPLL : 933 MHz
|
||||
* - SYSPLL1 : 4000 MHz
|
||||
* - SYSPLL_PFD0 : 1000 MHz
|
||||
* - SYSPLL_PFD1 : 800 MHz
|
||||
* - SYSPLL_PFD2 : 625 MHz
|
||||
* - AUDIOPLL_OUT : OFF
|
||||
* - VIDEOPLL_OUT : OFF
|
||||
*
|
||||
* After reset all clock sources (OSCPLL) and root clocks (CLOCK_ROOT) are
|
||||
* running, but gated (LPCG).
|
||||
*
|
||||
* By default, all peripheral root clocks are set to the 24 MHz oscillator.
|
||||
*/
|
||||
|
||||
#define ARMPLL_CFG PLL_CFG(IMX9_ARMPLL_BASE, false, PLL_PARMS(1, 2, 141, 0, 0))
|
||||
#define DRAMPLL_CFG PLL_CFG(IMX9_DRAMPLL_BASE, true, PLL_PARMS(1, 2, 155, 1, 2))
|
||||
|
||||
#define PLL_CFGS \
|
||||
{ \
|
||||
PLL_CFG(IMX9_SYSPLL_BASE, true, PLL_PARMS(1, 4, 166, 2, 3)), \
|
||||
}
|
||||
|
||||
#define PFD_CFGS \
|
||||
{ \
|
||||
PFD_CFG(IMX9_SYSPLL_BASE, 0, PFD_PARMS(4, 0, true)), \
|
||||
PFD_CFG(IMX9_SYSPLL_BASE, 1, PFD_PARMS(5, 0, true)), \
|
||||
PFD_CFG(IMX9_SYSPLL_BASE, 2, PFD_PARMS(6, 2, true)), \
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user