Permalink
Browse files

ARM: exynos: add clock and DMC init for exynos4412

  • Loading branch information...
fourkbomb committed Apr 28, 2018
1 parent ecace78 commit 700b61e5313cf764ced165f4e080a0419509e783
@@ -15,7 +15,7 @@ ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o
obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o
obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4210.o clock_init_exynos4210.o
obj-$(CONFIG_EXYNOS4) += dmc_init_exynos4412.o
obj-$(CONFIG_EXYNOS4412)+= dmc_init_exynos4412.o clock_init_exynos4412.o
obj-y += spl_boot.o tzpc.o
obj-y += lowlevel_init.o
endif
@@ -0,0 +1,150 @@
/*
* Clock initialisation for Exynos4412 based boards
*
* Copyright (C) 2018 Simon Shields <simon@lineageos.org>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <common.h>
#include <config.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clk.h>
#include <asm/arch/clock.h>
#include <asm/arch/power.h>
#include "common_setup.h"
#include "exynos4412_setup.h"

/*
* TODO: change all clock sources, then change clock dividers.
*/
void system_clock_init(void)
{
struct exynos4x12_clock *clk =
(struct exynos4x12_clock *)samsung_get_base_clock();
struct exynos4412_power *power =
(struct exynos4412_power *)samsung_get_base_power();
#if 0
struct exynos4_dmc *dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
struct exynos4_dmc *dmc1 = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + DMC_OFFSET);
#endif

/* Set up UART */

writel(0, &clk->src_cpu);
writel(CLK_SRC_TOP0_VAL, &clk->src_top0);
writel(CLK_SRC_TOP1_VAL, &clk->src_top1);
writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus);
writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus);
writel(CLK_SRC_PERIL0_VAL, &clk->src_peril0);

sdelay(0x10000);

writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0);
writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1);
writel(CLK_DIV_TOP_VAL, &clk->div_top);
writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus);
writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus);
writel(CLK_DIV_PERIL0_VAL, &clk->div_peril0);

/* PLLs */
writel(APLL_LOCK_VAL, &clk->apll_lock);
writel(MPLL_LOCK_VAL, &clk->mpll_lock);
writel(EPLL_LOCK_VAL, &clk->epll_lock);
writel(VPLL_LOCK_VAL, &clk->vpll_lock);

writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0);
writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1);

/* APLL: 800MHz */
writel(APLL_CON1_VAL, &clk->apll_con1);
writel(APLL_CON0_VAL, &clk->apll_con0);

/* The iROM sets MPLL at 400MHz.
* Skip increasing MPLL if it's not at 400MHz */
if (readl(&clk->mpll_con0) == 0xa0640301) {
/* MPLL: 800MHz */
writel(MPLL_CON1_VAL, &clk->mpll_con1);
writel(MPLL_CON0_VAL, &clk->mpll_con0);
}

/* EPLL: 96MHz */
/* (64) * (24000000) / (2 * (1 << 3)) */
writel(EPLL_CON2_VAL, &clk->epll_con2);
writel(EPLL_CON1_VAL, &clk->epll_con1);
writel(EPLL_CON0_VAL, &clk->epll_con0);

/* VPLL: 108MHz */
/* (72) * (24000000) / (2 * (1 << 3)) */
writel(VPLL_CON2_VAL, &clk->vpll_con2);
writel(VPLL_CON1_VAL, &clk->vpll_con1);
writel(VPLL_CON0_VAL, &clk->vpll_con0);

/* Stabilise */
sdelay(0x40000);

/* Now that PLLs are set up, we can set the other clocks to use them... */
writel((1 << 24) | (1 << 0), &clk->src_cpu);
writel((1 << 16) | (1 << 12), &clk->src_dmc);
writel((1 << 8) | (1 << 4), &clk->src_top0);
writel((1 << 24) | (1 << 20) | (1 << 16) | (1 << 12), &clk->src_top1);

sdelay(0x10000);

/*
* In the SDMMC booting case, we need to reconfigure MMC clock
* to make the iROM happy.
*/
u32 fsys2_div = readl(&clk->div_fsys2);
/* new MMC2 div is 16 */
fsys2_div |= 0xf;
writel(fsys2_div, &clk->div_fsys2);

/*check C2C_CTRL enable bit */
if ((readl(&power->c2c_ctrl) & 1) != 0)
return;
#if 0
writel(PHYCONTROL0_VAL, &dmc->phycontrol0);
writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8) | CTRL_SHIFTC(4), &dmc->phycontrol1);
writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmc->phycontrol0);
sdelay(0x20000);

writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmc->phycontrol1);
writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmc->phycontrol1);

sdelay(0x20000);

writel(PHYCONTROL0_VAL, &dmc1->phycontrol0);
writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8) | CTRL_SHIFTC(4), &dmc1->phycontrol1);
writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmc1->phycontrol0);
sdelay(0x20000);

writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmc1->phycontrol1);
writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmc1->phycontrol1);

sdelay(0x20000);

writel(DMC_CONCONTROL, &dmc->concontrol);
writel(DMC_CONCONTROL, &dmc1->concontrol);

writel(DMC_MEMCONTROL, &dmc->memcontrol);
writel(DMC_MEMCONTROL, &dmc1->memcontrol);
#endif
}
@@ -9,103 +9,12 @@
#include "common_setup.h"
#include "exynos4412_setup.h"

// TODO: 4412 and 4210 should be commonised using something like is_soc_4210
void system_clock_init(void)
{
struct exynos4x12_clock *clk =
(struct exynos4x12_clock *)samsung_get_base_clock();
struct exynos4412_power *power = (struct exynos4412_power *)samsung_get_base_power();
struct exynos4_dmc *dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
struct exynos4_dmc *dmc1 = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + DMC_OFFSET);

// disable WDT
writel(0, (unsigned int *)0x10060000);

writel(0, &clk->src_cpu);

sdelay(0x10000);

writel(CLK_DIV_DMC0_VAL, &clk->div_dmc0);
writel(CLK_DIV_DMC1_VAL, &clk->div_dmc1);

writel(CLK_SRC_TOP0_VAL, &clk->src_top0);
writel(CLK_SRC_TOP1_VAL, &clk->src_top1);
sdelay(0x10000);
writel(CLK_DIV_TOP_VAL, &clk->div_top);

writel(CLK_SRC_LEFTBUS_VAL, &clk->src_leftbus);
sdelay(0x10000);
writel(CLK_DIV_LEFTBUS_VAL, &clk->div_leftbus);

writel(CLK_SRC_RIGHTBUS_VAL, &clk->src_rightbus);
sdelay(0x10000);
writel(CLK_DIV_RIGHTBUS_VAL, &clk->div_rightbus);

// setup PLLs
writel(0x3e8, &clk->apll_lock);
writel(0x2f1, &clk->mpll_lock);
writel(0x2321, &clk->epll_lock);
writel(0x2321, &clk->vpll_lock);

writel(CLK_DIV_CPU0_VAL, &clk->div_cpu0);
writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1);

writel(APLL_CON1_VAL, &clk->apll_con1);
writel(APLL_CON0_VAL, &clk->apll_con0);

/* don't reset MPLL in C2C case */
if (readl(&clk->mpll_con1) == 0xa0640301) {
writel(MPLL_CON1_VAL, &clk->mpll_con1);
writel(MPLL_CON0_VAL, &clk->mpll_con0);
}

writel(EPLL_CON2_VAL, &clk->epll_con2);
writel(EPLL_CON1_VAL, &clk->epll_con1);
writel(EPLL_CON0_VAL, &clk->epll_con0);

writel(VPLL_CON2_VAL, &clk->vpll_con2);
writel(VPLL_CON1_VAL, &clk->vpll_con1);
writel(VPLL_CON0_VAL, &clk->vpll_con0);

sdelay(0x10000);

/* wtf */
writel(0x01000001, &clk->src_cpu);
writel(0x00011000, &clk->src_dmc);
writel(0x00000110, &clk->src_top0);
writel(0x01111000, &clk->src_top1);

sdelay(0x10000);

if ((readl(&power->c2c_ctrl) & 1) != 0) {
return;
}

/* todo: split this out, clean it up. Or drop it entirely? */
// DRAM clocks
writel(0x7f10100a, &dmc->phycontrol0);
writel(0xe0000084, &dmc->phycontrol1);
writel(0x7f10100b, &dmc->phycontrol0);

sdelay(0x20000);

writel(0x0000008c, &dmc->phycontrol1); // force DLL resync
writel(0x00000084, &dmc->phycontrol1);

sdelay(0x20000);

writel(0x0fff30fa, &dmc->concontrol);
writel(0x0fff30fa, &dmc1->concontrol);

writel(0x00202533, &dmc->memcontrol);
writel(0x00202533, &dmc1->memcontrol);
}

void mem_ctrl_init(int reset)
{
struct exynos4x12_clock *clk =
(struct exynos4x12_clock *)samsung_get_base_clock();
struct exynos4_dmc *dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
struct exynos4_dmc *dmc1 = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + DMC_OFFSET);

writel(0x00117713, &clk->div_dmc0);

@@ -151,49 +60,74 @@ void mem_ctrl_init(int reset)
writel(0x810, &dmc->directcmd);
writel(0xc08, &dmc->directcmd);

dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + DMC_OFFSET);
writel(0xe3855403, &dmc1->phyzqcontrol);
writel(0x71101008, &dmc1->phycontrol0);
writel(0x7110100a, &dmc1->phycontrol0);

writel(0xe3855403, &dmc->phyzqcontrol);
writel(0x71101008, &dmc->phycontrol0);
writel(0x7110100a, &dmc->phycontrol0);
writel(0x00000084, &dmc1->phycontrol1);
writel(0x71101008, &dmc1->phycontrol0);
writel(0x0000008c, &dmc1->phycontrol1);
writel(0x00000084, &dmc1->phycontrol1);
writel(0x0000008c, &dmc1->phycontrol1);
writel(0x00000084, &dmc1->phycontrol1);

writel(0x00000084, &dmc->phycontrol1);
writel(0x71101008, &dmc->phycontrol0);
writel(0x0000008c, &dmc->phycontrol1);
writel(0x00000084, &dmc->phycontrol1);
writel(0x0000008c, &dmc->phycontrol1);
writel(0x00000084, &dmc->phycontrol1);

writel(0x0fff30ca, &dmc->concontrol);
writel(0x00202500, &dmc->memcontrol);
writel(0x40c01323, &dmc->memconfig0);
writel(0x80000000 | 0x7, &dmc->ivcontrol);
writel(0x64000000, &dmc->prechconfig);
writel(0x9c4000ff, &dmc->phycontrol0);
writel(0x0fff30ca, &dmc1->concontrol);
writel(0x00202500, &dmc1->memcontrol);
writel(0x40c01323, &dmc1->memconfig0);
writel(0x80000000 | 0x7, &dmc1->ivcontrol);
writel(0x64000000, &dmc1->prechconfig);
writel(0x9c4000ff, &dmc1->phycontrol0);

writel(0x5d, &dmc->timingref);
writel(0x5d, &dmc1->timingref);

writel(0x34498691, &dmc->timingrow);
writel(0x36330306, &dmc->timingdata);
writel(0x50380365, &dmc->timingpower);
writel(0x34498691, &dmc1->timingrow);
writel(0x36330306, &dmc1->timingdata);
writel(0x50380365, &dmc1->timingpower);

sdelay(0x100000);

writel(0x07000000, &dmc->directcmd);
writel(0x07000000, &dmc1->directcmd);

sdelay(0x100000);

writel(0x00071c00, &dmc->directcmd);
writel(0x00071c00, &dmc1->directcmd);

sdelay(0x100000);

writel(0x00010bfc, &dmc->directcmd);
writel(0x00010bfc, &dmc1->directcmd);

sdelay(0x100000);

writel(0x608, &dmc->directcmd);
writel(0x810, &dmc->directcmd);
writel(0xc08, &dmc->directcmd);
writel(0x608, &dmc1->directcmd);
writel(0x810, &dmc1->directcmd);
writel(0xc08, &dmc1->directcmd);

writel(PHYCONTROL0_VAL, &dmc->phycontrol0);
writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8) | CTRL_SHIFTC(4), &dmc->phycontrol1);
writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmc->phycontrol0);
sdelay(0x20000);

writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmc->phycontrol1);
writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmc->phycontrol1);

sdelay(0x20000);

writel(PHYCONTROL0_VAL, &dmc1->phycontrol0);
writel(MEM_TERM_EN | PHY_READ_EN | CTRL_SHGATE | CTRL_REF(8) | CTRL_SHIFTC(4), &dmc1->phycontrol1);
writel(PHYCONTROL0_VAL | CTRL_DLL_START, &dmc1->phycontrol0);
sdelay(0x20000);

writel(CTRL_REF(8) | CTRL_SHIFTC(4), &dmc1->phycontrol1);
writel(CTRL_REF(8) | FP_RESYNC | CTRL_SHIFTC(4), &dmc1->phycontrol1);

sdelay(0x20000);

writel(DMC_CONCONTROL, &dmc->concontrol);
writel(DMC_CONCONTROL, &dmc1->concontrol);

writel(DMC_MEMCONTROL, &dmc->memcontrol);
writel(DMC_MEMCONTROL, &dmc1->memcontrol);

}


Oops, something went wrong.

0 comments on commit 700b61e

Please sign in to comment.