405 lines
9.2 KiB
C
405 lines
9.2 KiB
C
#include <common.h>
|
|
#include <asm/io.h>
|
|
#include <asm-generic/div64.h>
|
|
#include <mach/imx-regs.h>
|
|
#include <mach/clock-imx6.h>
|
|
#include <mach/imx6-anadig.h>
|
|
|
|
enum pll_clocks {
|
|
CPU_PLL1, /* System PLL */
|
|
BUS_PLL2, /* System Bus PLL*/
|
|
USBOTG_PLL3, /* OTG USB PLL */
|
|
AUD_PLL4, /* Audio PLL */
|
|
VID_PLL5, /* Video PLL */
|
|
MLB_PLL6, /* MLB PLL */
|
|
USBHOST_PLL7, /* Host USB PLL */
|
|
ENET_PLL8, /* ENET PLL */
|
|
};
|
|
|
|
#define SZ_DEC_1M 1000000
|
|
|
|
/* Out-of-reset PFDs and clock source definitions */
|
|
#define PLL2_PFD0_FREQ 352000000
|
|
#define PLL2_PFD1_FREQ 594000000
|
|
#define PLL2_PFD2_FREQ 400000000
|
|
#define PLL2_PFD2_DIV_FREQ 200000000
|
|
#define PLL3_PFD0_FREQ 720000000
|
|
#define PLL3_PFD1_FREQ 540000000
|
|
#define PLL3_PFD2_FREQ 508200000
|
|
#define PLL3_PFD3_FREQ 454700000
|
|
#define PLL3_80M 80000000
|
|
#define PLL3_60M 60000000
|
|
|
|
#define AHB_CLK_ROOT 132000000
|
|
#define IPG_CLK_ROOT 66000000
|
|
#define ENET_FREQ_0 25000000
|
|
#define ENET_FREQ_1 50000000
|
|
#define ENET_FREQ_2 100000000
|
|
#define ENET_FREQ_3 125000000
|
|
|
|
#define CONFIG_MX6_HCLK_FREQ 24000000
|
|
|
|
static u32 __decode_pll(enum pll_clocks pll, u32 infreq)
|
|
{
|
|
u32 div;
|
|
|
|
switch (pll) {
|
|
case CPU_PLL1:
|
|
div = readl(MX6_ANATOP_BASE_ADDR + HW_ANADIG_PLL_SYS) &
|
|
BM_ANADIG_PLL_SYS_DIV_SELECT;
|
|
return infreq * (div >> 1);
|
|
case BUS_PLL2:
|
|
div = readl(MX6_ANATOP_BASE_ADDR + HW_ANADIG_PLL_528) &
|
|
BM_ANADIG_PLL_528_DIV_SELECT;
|
|
return infreq * (20 + (div << 1));
|
|
case USBOTG_PLL3:
|
|
div = readl(MX6_ANATOP_BASE_ADDR + HW_ANADIG_USB2_PLL_480_CTRL) &
|
|
BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT;
|
|
return infreq * (20 + (div << 1));
|
|
case ENET_PLL8:
|
|
div = readl(MX6_ANATOP_BASE_ADDR + HW_ANADIG_PLL_ENET) &
|
|
BM_ANADIG_PLL_ENET_DIV_SELECT;
|
|
switch (div) {
|
|
default:
|
|
case 0:
|
|
return ENET_FREQ_0;
|
|
case 1:
|
|
return ENET_FREQ_1;
|
|
case 2:
|
|
return ENET_FREQ_2;
|
|
case 3:
|
|
return ENET_FREQ_3;
|
|
}
|
|
case AUD_PLL4:
|
|
case VID_PLL5:
|
|
case MLB_PLL6:
|
|
case USBHOST_PLL7:
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static u32 __get_mcu_main_clk(void)
|
|
{
|
|
u32 reg, freq;
|
|
reg = (__REG(MXC_CCM_CACRR) & MXC_CCM_CACRR_ARM_PODF_MASK) >>
|
|
MXC_CCM_CACRR_ARM_PODF_OFFSET;
|
|
freq = __decode_pll(CPU_PLL1, CONFIG_MX6_HCLK_FREQ);
|
|
return freq / (reg + 1);
|
|
}
|
|
|
|
static u32 __get_periph_clk(void)
|
|
{
|
|
u32 reg;
|
|
reg = __REG(MXC_CCM_CBCDR);
|
|
if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
|
|
reg = __REG(MXC_CCM_CBCMR);
|
|
switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK) >>
|
|
MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET) {
|
|
case 0:
|
|
return __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ);
|
|
case 1:
|
|
case 2:
|
|
return CONFIG_MX6_HCLK_FREQ;
|
|
default:
|
|
return 0;
|
|
}
|
|
} else {
|
|
reg = __REG(MXC_CCM_CBCMR);
|
|
switch ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) >>
|
|
MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET) {
|
|
default:
|
|
case 0:
|
|
return __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ);
|
|
case 1:
|
|
return PLL2_PFD2_FREQ;
|
|
case 2:
|
|
return PLL2_PFD0_FREQ;
|
|
case 3:
|
|
return PLL2_PFD2_DIV_FREQ;
|
|
}
|
|
}
|
|
}
|
|
|
|
static u32 __get_ipg_clk(void)
|
|
{
|
|
u32 ahb_podf, ipg_podf;
|
|
|
|
ahb_podf = __REG(MXC_CCM_CBCDR);
|
|
ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
|
|
MXC_CCM_CBCDR_IPG_PODF_OFFSET;
|
|
ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
|
|
MXC_CCM_CBCDR_AHB_PODF_OFFSET;
|
|
return __get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1));
|
|
}
|
|
|
|
u32 imx_get_gptclk(void)
|
|
{
|
|
return __get_ipg_clk();
|
|
}
|
|
|
|
static u32 __get_ipg_per_clk(void)
|
|
{
|
|
u32 podf;
|
|
u32 clk_root = __get_ipg_clk();
|
|
|
|
podf = __REG(MXC_CCM_CSCMR1) & MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
|
|
return clk_root / (podf + 1);
|
|
}
|
|
|
|
u32 imx_get_uartclk(void)
|
|
{
|
|
u32 freq = PLL3_80M, reg, podf;
|
|
|
|
reg = __REG(MXC_CCM_CSCDR1);
|
|
podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
|
|
MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
|
|
freq /= (podf + 1);
|
|
|
|
return freq;
|
|
}
|
|
|
|
static u32 __get_cspi_clk(void)
|
|
{
|
|
u32 freq = PLL3_60M, reg, podf;
|
|
|
|
reg = __REG(MXC_CCM_CSCDR2);
|
|
podf = (reg & MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK) >>
|
|
MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET;
|
|
freq /= (podf + 1);
|
|
|
|
return freq;
|
|
}
|
|
|
|
static u32 __get_axi_clk(void)
|
|
{
|
|
u32 clkroot;
|
|
u32 cbcdr = __REG(MXC_CCM_CBCDR);
|
|
u32 podf = (cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK) >>
|
|
MXC_CCM_CBCDR_AXI_PODF_OFFSET;
|
|
|
|
if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
|
|
if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
|
|
clkroot = PLL2_PFD2_FREQ;
|
|
else
|
|
clkroot = PLL3_PFD1_FREQ;;
|
|
} else
|
|
clkroot = __get_periph_clk();
|
|
|
|
return clkroot / (podf + 1);
|
|
}
|
|
|
|
static u32 __get_ahb_clk(void)
|
|
{
|
|
u32 cbcdr = __REG(MXC_CCM_CBCDR);
|
|
u32 podf = (cbcdr & MXC_CCM_CBCDR_AHB_PODF_MASK) \
|
|
>> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
|
|
|
|
return __get_periph_clk() / (podf + 1);
|
|
}
|
|
|
|
static u32 __get_emi_slow_clk(void)
|
|
{
|
|
u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
|
|
u32 emi_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK) >>
|
|
MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET;
|
|
u32 podf = (cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK) >>
|
|
MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
|
|
|
|
switch (emi_clk_sel) {
|
|
default:
|
|
case 0:
|
|
return __get_axi_clk() / (podf + 1);
|
|
case 1:
|
|
return __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ) /
|
|
(podf + 1);
|
|
case 2:
|
|
return PLL2_PFD2_FREQ / (podf + 1);
|
|
case 3:
|
|
return PLL2_PFD0_FREQ / (podf + 1);
|
|
}
|
|
}
|
|
|
|
static u32 __get_nfc_clk(void)
|
|
{
|
|
u32 clkroot;
|
|
u32 cs2cdr = __REG(MXC_CCM_CS2CDR);
|
|
u32 podf = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK) \
|
|
>> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
|
|
u32 pred = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK) \
|
|
>> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
|
|
|
|
switch ((cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK) >>
|
|
MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET) {
|
|
default:
|
|
case 0:
|
|
clkroot = PLL2_PFD0_FREQ;
|
|
break;
|
|
case 1:
|
|
clkroot = __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ);
|
|
break;
|
|
case 2:
|
|
clkroot = __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ);
|
|
break;
|
|
case 3:
|
|
clkroot = PLL2_PFD2_FREQ;
|
|
break;
|
|
}
|
|
|
|
return clkroot / (pred+1) / (podf+1);
|
|
}
|
|
|
|
static u32 __get_ddr_clk(void)
|
|
{
|
|
u32 cbcdr = __REG(MXC_CCM_CBCDR);
|
|
u32 podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >>
|
|
MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET;
|
|
|
|
return __get_periph_clk() / (podf + 1);
|
|
}
|
|
|
|
static u32 __get_usdhc1_clk(void)
|
|
{
|
|
u32 clkroot;
|
|
u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
|
|
u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
|
|
u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
|
|
MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
|
|
|
|
if (cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL)
|
|
clkroot = PLL2_PFD0_FREQ;
|
|
else
|
|
clkroot = PLL2_PFD2_FREQ;
|
|
|
|
return clkroot / (podf + 1);
|
|
}
|
|
|
|
static u32 __get_usdhc2_clk(void)
|
|
{
|
|
u32 clkroot;
|
|
u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
|
|
u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
|
|
u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
|
|
MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
|
|
|
|
if (cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL)
|
|
clkroot = PLL2_PFD0_FREQ;
|
|
else
|
|
clkroot = PLL2_PFD2_FREQ;
|
|
|
|
return clkroot / (podf + 1);
|
|
}
|
|
|
|
static u32 __get_usdhc3_clk(void)
|
|
{
|
|
u32 clkroot;
|
|
u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
|
|
u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
|
|
u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
|
|
MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
|
|
|
|
if (cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL)
|
|
clkroot = PLL2_PFD0_FREQ;
|
|
else
|
|
clkroot = PLL2_PFD2_FREQ;
|
|
|
|
return clkroot / (podf + 1);
|
|
}
|
|
|
|
static u32 __get_usdhc4_clk(void)
|
|
{
|
|
u32 clkroot;
|
|
u32 cscmr1 = __REG(MXC_CCM_CSCMR1);
|
|
u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
|
|
u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
|
|
MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
|
|
|
|
if (cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL)
|
|
clkroot = PLL2_PFD0_FREQ;
|
|
else
|
|
clkroot = PLL2_PFD2_FREQ;
|
|
|
|
return clkroot / (podf + 1);
|
|
}
|
|
|
|
u32 imx_get_mmcclk(void)
|
|
{
|
|
return __get_usdhc3_clk();
|
|
}
|
|
|
|
u32 imx_get_fecclk(void)
|
|
{
|
|
return __get_ipg_clk();
|
|
}
|
|
|
|
u32 imx_get_i2cclk(void)
|
|
{
|
|
return __get_ipg_per_clk();
|
|
}
|
|
|
|
u32 imx_get_cspiclk(void)
|
|
{
|
|
return __get_cspi_clk();
|
|
}
|
|
|
|
void imx_dump_clocks(void)
|
|
{
|
|
u32 freq;
|
|
|
|
freq = __decode_pll(CPU_PLL1, CONFIG_MX6_HCLK_FREQ);
|
|
printf("mx6q pll1: %d\n", freq);
|
|
freq = __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ);
|
|
printf("mx6q pll2: %d\n", freq);
|
|
freq = __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ);
|
|
printf("mx6q pll3: %d\n", freq);
|
|
freq = __decode_pll(ENET_PLL8, CONFIG_MX6_HCLK_FREQ);
|
|
printf("mx6q pll8: %d\n", freq);
|
|
printf("mcu main: %d\n", __get_mcu_main_clk());
|
|
printf("periph: %d\n", __get_periph_clk());
|
|
printf("i2c: %d\n", __get_ipg_per_clk());
|
|
printf("ipg: %d\n", __get_ipg_clk());
|
|
printf("ipg per: %d\n", __get_ipg_per_clk());
|
|
printf("cspi: %d\n", __get_cspi_clk());
|
|
printf("axi: %d\n", __get_axi_clk());
|
|
printf("ahb: %d\n", __get_ahb_clk());
|
|
printf("emi slow: %d\n", __get_emi_slow_clk());
|
|
printf("nfc: %d\n", __get_nfc_clk());
|
|
printf("ddr: %d\n", __get_ddr_clk());
|
|
printf("usdhc1: %d\n", __get_usdhc1_clk());
|
|
printf("usdhc2: %d\n", __get_usdhc2_clk());
|
|
printf("usdhc3: %d\n", __get_usdhc3_clk());
|
|
printf("usdhc4: %d\n", __get_usdhc4_clk());
|
|
}
|
|
|
|
void imx6_ipu_clk_enable(int di)
|
|
{
|
|
u32 reg;
|
|
|
|
if (di == 1) {
|
|
reg = readl(MXC_CCM_CCGR3);
|
|
reg |= 0xC033;
|
|
writel(reg, MXC_CCM_CCGR3);
|
|
} else {
|
|
reg = readl(MXC_CCM_CCGR3);
|
|
reg |= 0x300F;
|
|
writel(reg, MXC_CCM_CCGR3);
|
|
}
|
|
|
|
reg = readl(MX6_ANATOP_BASE_ADDR + 0xF0);
|
|
reg &= ~0x00003F00;
|
|
reg |= 0x00001300;
|
|
writel(reg, MX6_ANATOP_BASE_ADDR + 0xF4);
|
|
|
|
reg = readl(MXC_CCM_CS2CDR);
|
|
reg &= ~0x00007E00;
|
|
reg |= 0x00001200;
|
|
writel(reg, MXC_CCM_CS2CDR);
|
|
|
|
reg = readl(MXC_CCM_CSCMR2);
|
|
reg |= 0x00000C00;
|
|
writel(reg, MXC_CCM_CSCMR2);
|
|
|
|
reg = 0x0002A953;
|
|
writel(reg, MXC_CCM_CHSCDR);
|
|
}
|