ITOP4412----Uboot2020移植记录

gitee: 本工程代码托管于gitee,仅供参考学习使用,不保证任何出现的问题。

1、 在board/samsung/目录下添加itop4412目录,准备添加板级文件。

复制origen开发板内文件,到board/samsung/itop4412。开始修改修改。
在这里插入图片描述
上述文件全部来自origen开发板目录下。

mkitop4412spl.c

/*
 * Copyright (C) 2011 Samsung Electronics
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

#define BUFSIZE			(16*1024)
#define IMG_SIZE		(14*1024) //16*1024 14k BL2
#define SPL_HEADER_SIZE		0 //16 不保留、在sdfuse中烧录
#define FILE_PERM		(S_IRUSR | S_IWUSR | S_IRGRP \
				| S_IWGRP | S_IROTH | S_IWOTH)
#define SPL_HEADER		"S5PC210 HEADER  "
/*
* Requirement:
* IROM code reads first 14K bytes from boot device.
* IROM的出厂烧录的代码会从启动设备中读取起始14K字节
* It then calculates the checksum of 14K-4 bytes 
* and compare with data at 14K-4 offset.
* 它会计算这14k减去4字节的代码的校验和,(这里减去的4字节内容存放着开发人员自己对代码计算的校验和,这个文件就是用来干这个的)。IROM会用这4字节的校验和与自己计算的校验和比较,如果不匹配,程序不会正常运行。
* This function takes two filenames:
* 这个文件需要两个参数
* IN  "u-boot-spl.bin" and
* OUT "$(BOARD)-spl.bin as filenames.
* 输入u-boot-spl.bin文件,输出$(BOARD)-spl.bin,$(BOARD)是目标板名称例如
* 输出itop4412-spl.bin
* It reads the "u-boot-spl.bin" in 16K buffer.
* 这个文件会读取u-boot-spl.bin到一个16k的缓冲区中
* It calculates checksum of 14K-4 Bytes and stores at 14K-4 offset in buffer.
* 然后计算14k-4字节代码的校验和,储存在偏移为14K-4的缓冲区中,最后写到$(BOARD)-spl.bin里
* It writes the buffer to "$(BOARD)-spl.bin" file.
*/

int main(int argc, char **argv)
{
   
	int i, len;
	unsigned char buffer[BUFSIZE] = {
   0};
	int ifd, ofd;
	unsigned int checksum = 0, count;

	if (argc != 3) {
   
		printf(" %d Wrong number of arguments\n", argc);
		exit(EXIT_FAILURE);
	}

	ifd = open(argv[1], O_RDONLY);
	if (ifd < 0) {
   
		fprintf(stderr, "%s: Can't open %s: %s\n",
			argv[0], argv[1], strerror(errno));
		exit(EXIT_FAILURE);
	}

	ofd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FILE_PERM);
	if (ofd < 0) {
   
		fprintf(stderr, "%s: Can't open %s: %s\n",
			argv[0], argv[2], strerror(errno));
		if (ifd)
			close(ifd);
		exit(EXIT_FAILURE);
	}

	len = lseek(ifd, 0, SEEK_END);
	lseek(ifd, 0, SEEK_SET);

	memcpy(&buffer[0], SPL_HEADER, SPL_HEADER_SIZE);

	count = (len < (IMG_SIZE - SPL_HEADER_SIZE))
		? len : (IMG_SIZE - SPL_HEADER_SIZE);

	if (read(ifd, buffer + SPL_HEADER_SIZE, count) != count) {
   
		fprintf(stderr, "%s: Can't read %s: %s\n",
			argv[0], argv[1], strerror(errno));

		if (ifd)
			close(ifd);
		if (ofd)
			close(ofd);

		exit(EXIT_FAILURE);
	}
	
#if 0
	for (i = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
		checksum += buffer[i+16];

	*(unsigned long *)buffer ^= 0x1f;
	*(unsigned long *)(buffer+4) ^= checksum;

	for (i = 1; i < SPL_HEADER_SIZE; i++)
		buffer[i] ^= buffer[i-1];
#endif

	for (i = 0; i < IMG_SIZE - 4; i++)
		checksum += (unsigned char)buffer[i];

	*(unsigned int *)&buffer[i] = checksum;

	if (write(ofd, buffer, BUFSIZE) != BUFSIZE) {
   
		fprintf(stderr, "%s: Can't write %s: %s\n",
			argv[0], argv[2], strerror(errno));

		if (ifd)
			close(ifd);
		if (ofd)
			close(ofd);

		exit(EXIT_FAILURE);
	}

	if (ifd)
		close(ifd);
	if (ofd)
		close(ofd);

	return EXIT_SUCCESS;
}

这个文件会被编译成BL2工具,在最终生成uboot的时候自动被调用,代码如下

./spl/board/samsung/itop4412/tools/mkitop4412spl spl/u-boot-spl.bin spl/itop4412-spl.bin

itop4412.c

如果要对板子做一些特殊的初始化,可以添加在这里,点个灯什么的。

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2011 Samsung Electronics
 */

#include <common.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/arch/cpu.h>
#include <asm/arch/mmc.h>
#include <asm/arch/periph.h>
#include <asm/arch/pinmux.h>
#include <usb.h>

u32 get_board_rev(void)
{
   
	return 0;
}

int exynos_init(void)
{
   
	return 0;
}

int board_usb_init(int index, enum usb_init_type init)
{
   
	return 0;
}

#ifdef CONFIG_BOARD_EARLY_INIT_F
int exynos_early_init_f(void)
{
   
	return 0;
}
#endif

Kconfig

用于make menuconfig的配置选项,图形化配置需要。

if TARGET_ITOP4412

config SYS_BOARD
	default "itop4412"

config SYS_VENDOR
	default "samsung"

config SYS_CONFIG_NAME
	default "itop4412"

endif

Maintained

一些声明

ITOP4412 BOARD
M:	Chander Kashyap <k.chander@samsung.com>
S:	Maintained
F:	board/samsung/itop4412/
F:	include/configs/itop4412.h
F:	configs/itop4412_defconfig

Makefile

编译脚本

# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2011 Samsung Electronics

ifdef CONFIG_SPL_BUILD
# necessary to create built-in.o
obj- := __dummy__.o

hostprogs-y := tools/mkitop4412spl
always := $(hostprogs-y)

# omit -O2 option to suppress
#   warning: dereferencing type-punned pointer will break strict-aliasing rules
#
# TODO:
# Fix the root cause in tools/mkorigenspl.c and delete the following work-around
$(obj)/tools/mkitop4412spl: HOSTCFLAGS:=$(filter-out -O2,$(HOSTCFLAGS))
else
obj-y	+= itop4412.o
endif

2、在arch/arm/include/asm/mach-types.h中添加4412机器码

#define MACH_TYPE_ITOP4412          5115//在最后面+1

3、添加board.c实现s_init()拉高电源芯片hold引脚和点亮led灯。

board.c

#include <common.h>
#include <config.h>
#include <asm/io.h>

void s_init(void)
{
   
   writel(readl(0x1002330c) | 0x300, 0x1002330c);
   writel(0, 0x11000c08);

   /* led test */
   writel(0x10, 0x11000060);
   writel(0x2, 0x11000064);

   writel(0x1, 0x11000100);
   writel(0x1, 0x11000104);
}

修改arch/arm/mach-exynos/Makefile

为编译board.c、dmc内存管理、clock时钟配置提供支持。

# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2009 Samsung Electronics
# Minkyu Kang <mk7.kang@samsung.com>

obj-y	+= board.o
obj-y	+= soc.o
obj-$(CONFIG_CPU_V7A) += clock.o pinmux.o power.o system.o
obj-$(CONFIG_ARM64)	+= mmu-arm64.o

obj-$(CONFIG_EXYNOS5420)	+= sec_boot.o

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_exynos4.o clock_init_exynos4.o
ifneq (,$(filter y, $(CONFIG_EXYNOS4210) $(CONFIG_TARGET_ITOP4412)))
obj-y     += dmc_init_exynos4.o clock_init_exynos4.o
endif
obj-y	+= spl_boot.o tzpc.o
obj-y	+= lowlevel_init.o
endif

4、修改dmc_init_exynos4.c、clock_init_exynos4.c,添加itop4412_setup.h

时钟和内存控制器的寄存器很难配,需要对照手册一点一点的弄。有不少前辈已经做好了工作,直接copy。

dmc_init_exynos4.c

内存控制器配置

/*
 * Memory setup for board based on EXYNOS4210
 *
 * Copyright (C) 2013 Samsung Electronics
 * Rajeshwari Shinde <rajeshwari.s@samsung.com>
 *
 * 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 <config.h>
#include <asm/arch/dmc.h>
#include "common_setup.h"

#ifdef CONFIG_ITOP4412
#include "itop4412_setup.h"
#else
#include "exynos4_setup.h"
#endif

struct mem_timings mem = {
   
	.direct_cmd_msr = {
   
		DIRECT_CMD1, DIRECT_CMD2, DIRECT_CMD3, DIRECT_CMD4
	},
	.timingref = TIMINGREF_VAL,
	.timingrow = TIMINGROW_VAL,
	.timingdata = TIMINGDATA_VAL,
	.timingpower = TIMINGPOWER_VAL,
	.zqcontrol = ZQ_CONTROL_VAL,
	.control0 = CONTROL0_VAL,
	.control1 = CONTROL1_VAL,
	.control2 = CONTROL2_VAL,
	.concontrol = CONCONTROL_VAL,
	.prechconfig = PRECHCONFIG,
	.memcontrol = MEMCONTROL_VAL,
	.memconfig0 = MEMCONFIG0_VAL,
	.memconfig1 = MEMCONFIG1_VAL,
	.dll_resync = FORCE_DLL_RESYNC,
	.dll_on = DLL_CONTROL_ON,
};
static void phy_control_reset(int ctrl_no, struct exynos4_dmc *dmc)
{
   
	if (ctrl_no) {
   
		writel((mem.control1 | (1 << mem.dll_resync)),
		       &dmc->phycontrol1);
		writel((mem.control1 | (0 << mem.dll_resync)),
		       &dmc->phycontrol1);
	} else {
   
		writel((mem.control0 | (0 << mem.dll_on)),
		       &dmc->phycontrol0);
		writel((mem.control0 | (1 << mem.dll_on)),
		       &dmc->phycontrol0);
	}
}

static void dmc_config_mrs(struct exynos4_dmc *dmc, int chip)
{
   
	int i;
	unsigned long mask = 0;

	if (chip)
		mask = DIRECT_CMD_CHIP1_SHIFT;

	for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
   
		writel(mem.direct_cmd_msr[i] | mask,
		       &dmc->directcmd);
	}
}

static void dmc_init(struct exynos4_dmc *dmc)
{
   
	/*
	 * DLL Parameter Setting:
	 * Termination: Enable R/W
	 * Phase Delay for DQS Cleaning: 180' Shift
	 */
	writel(mem.control1, &dmc->phycontrol1);

	/*
	 * ZQ Calibration
	 * Termination: Disable
	 * Auto Calibration Start: Enable
	 */
	writel(mem.zqcontrol, &dmc->phyzqcontrol);
	sdelay(0x100000);

	/*
	 * Update DLL Information:
	 * Force DLL Resyncronization
	 */
	phy_control_reset(1, dmc);
	phy_control_reset(0, dmc);

	/* Set DLL Parameters */
	writel(mem.control1, &dmc->phycontrol1);

	/* DLL Start */
	writel((mem.control0 | CTRL_START | CTRL_DLL_ON), &dmc->phycontrol0);

	writel(mem.control2, &dmc->phycontrol2);

	/* Set Clock Ratio of Bus clock to Memory Clock */
	writel(mem.concontrol, &dmc->concontrol);

	/*
	 * Memor Burst length: 8
	 * Number of chips: 2
	 * Memory Bus width: 32 bit
	 * Memory Type: DDR3
	 * Additional Latancy for PLL: 1 Cycle
	 */
	writel(mem.memcontrol, &dmc->memcontrol);

	writel(mem.memconfig0, &dmc->memconfig0);
	writel(mem.memconfig1, &dmc->memconfig1);

	/* Config Precharge Policy */
	writel(mem.prechconfig, &dmc->prechconfig);
	/*
	 * TimingAref, TimingRow, TimingData, TimingPower Setting:
	 * Values as per Memory AC Parameters
	 */
	writel(mem.timingref, &dmc->timingref);
	writel(mem.timingrow, &dmc->timingrow);
	writel(mem.timingdata, &dmc->timingdata);
	writel(mem.timingpower, &dmc->timingpower);

	/* Chip0: NOP Command: Assert and Hold CKE to high level */
	writel(DIRECT_CMD_NOP, &dmc->directcmd);
	sdelay(0x100000);

	/* Chip0: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */
	dmc_config_mrs(dmc, 0);
	sdelay(0x100000);

	/* Chip0: ZQINIT */
	writel(DIRECT_CMD_ZQ, &dmc->directcmd);
	sdelay(0x100000);

	writel((DIRECT_CMD_NOP | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd);
	sdelay(0x100000);

	/* Chip1: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */
	dmc_config_mrs(dmc, 1);
	sdelay(0x100000);

	/* Chip1: ZQINIT */
	writel((DIRECT_CMD_ZQ | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd);
	sdelay(0x100000);

	phy_control_reset(1, dmc);
	sdelay(0x100000);

	/* turn on DREX0, DREX1 */
	writel((mem.concontrol | AREF_EN), &dmc->concontrol);
}

void mem_ctrl_init(int reset)
{
   
	struct exynos4_dmc *dmc;

	/*
	 * Async bridge configuration at CPU_core:
	 * 1: half_sync
	 * 0: full_sync
	 */
	writel(1, ASYNC_CONFIG);
#ifdef CONFIG_ITOP4412
	/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
	writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
		APB_SFR_INTERLEAVE_CONF_OFFSET);
	/* Update MIU Configuration */
	writel(APB_SFR_ARBRITATION_CONF_VAL, EXYNOS4_MIU_BASE +
		APB_SFR_ARBRITATION_CONF_OFFSET);
#else
	writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
		APB_SFR_INTERLEAVE_CONF_OFFSET);
	writel(INTERLEAVE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
		ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET);
	writel(INTERLEAVE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
		ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET);
	writel(INTERLEAVE_ADDR_MAP_EN, EXYNOS4_MIU_BASE +
		ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
#ifdef CONFIG_MIU_LINEAR
	writel(SLAVE0_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
		ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET);
	writel(SLAVE0_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
		ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET);
	writel(SLAVE1_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
		ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET);
	writel(SLAVE1_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
		ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET);
	writel(APB_SFR_SLV_ADDR_MAP_CONF_VAL, EXYNOS4_MIU_BASE +
		ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
#endif
#endif
	/* DREX0 */
	dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
	dmc_init(dmc);
	dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl()
					+ DMC_OFFSET);
	dmc_init(dmc);
}

clock_init_exynos4.c

时钟配置

/*
 * Clock Initialization for board based on EXYNOS4210
 *
 * Copyright (C) 2013 Samsung Electronics
 * Rajeshwari Shinde <rajeshwari.s@samsung.com>
 *
 * 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 "common_setup.h"

#ifdef CONFIG_ITOP4412
#include "itop4412_setup.h"
#else
#include "exynos4_setup.h"
#endif
/*
 * system_clock_init: Initialize core clock and bus clock.
 * void system_clock_init(void)
 */
/**
 * freq (ARMCLK) = 1400 MHz at 1.3 V
 * freq (ACLK_COREM0) = 350 MHz at 1.3V
 * freq (ACLK_COREM1) = 188 MHz at 1.3 V
 * freq (PERIPHCLK) = 1400 MHz at 1.3 V
 * freq (ATCLK) = 214 MHz at 1.3 V
 * freq (PCLK_DBG) = 107 MHz at 1.3 V
 * freq (SCLK_DMC) = 400 MHz at 1.0 V
 * freq (ACLK_DMCD) = 200 MHz at 1.0 V
 * freq (ACLK_DMCP) = 100 MHz at 1.0 V
 * freq (ACLK_ACP) = 200 MHz at 1.0 V
 * freq (PCLK_ACP) = 100 MHz at 1.0 V
 * freq (SCLK_C2C) = 400 MHz at 1.0 V
 * freq (ACLK_C2C) = 200 MHz at 1.0 V
 * freq (ACLK_GDL) = 200 MHz at 1.0 V
 * freq (ACLK_GPL) = 100 MHz at 1.0 V
 * freq (ACLK_GDR) = 200 MHz at 1.0 V
 * freq (ACLK_GPR) = 100 MHz at 1.0 V
 * freq (ACLK_400_MCUISP) = 400 MHz at 1.0 V
 * freq (ACLK_200) = 160 MHz at 1.0 V
 * freq (ACLK_100) = 100 MHz at 1.0 V
 * freq (ACLK_160) = 160 MHz at 1.0 V
 * freq (ACLK_133) = 133 MHz at 1.0 V
 * freq (SCLK_ONENAND) = 160 MHz at 1.0 V
 */
void system_clock_init(void)
{
   
	unsigned int set, clr, clr_src_cpu, clr_pll_con0, clr_src_dmc;
	struct exynos4x12_clock *clk = (struct exynos4x12_clock *)
						samsung_get_base_clock();

/************************************************************
 * Step 1:
 *
 * Set PDIV, MDIV, and SDIV values (Refer to (A, M, E, V)
 * Change other PLL control values
 ************************************************************/

	/**
	 * Set dividers for MOUTcore = 1000 MHz
	 *
	 * DOUTcore    = MOUTcore / (CORE_RATIO +1)      = 1000 MHz (0)
	 * ACLK_COREM0 = ARMCLK   / (COREM0_RATIO +1)    = 250 MHz (3)
	 * ACLK_COREM1 = ARMCLK   / (COREM1_RATIO +1)    = 125 MHz (7)
	 * PERIPHCLK   = DOUTcore / (PERIPH_RATIO + 1)   = 1000 MHz (0)
	 * ATCLK       = MOUTcore / (ATB_RATIO + 1)      = 200 MHz (4)
	 * PCLK_DBG    = ATCLK    / (PCLK_DBG_RATIO + 1) = 100 MHz (1)
	 * SCLKapll    = MOUTapll / (APLL_RATIO + 1)     = 500 MHz (1)
	 * ARMCLK      = DOUTcore / (CORE2_RATIO + 1)    = 1000 MHz (0)
	 */

	/** CLK_DIV_CPU0 */
	clr = CORE_RATIO(7) | COREM0_RATIO(7) | COREM1_RATIO(7) |
	      PERIPH_RATIO(7) | ATB_RATIO(7) | PCLK_DBG_RATIO(7) |
	      APLL_RATIO(7) | CORE2_RATIO(7);
	set = CORE_RATIO(0) | COREM0_RATIO(3) | COREM1_RATIO(7) |
	      PERIPH_RATIO(0) | ATB_RATIO(4) | PCLK_DBG_RATIO(1) |
	      APLL_RATIO(1) | CORE2_RATIO(0);

	clrsetbits_le32(&clk->div_cpu0, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_cpu0) & DIV_STAT_CPU0_CHANGING)
		continue;

	/**
	 * Set dividers for MOUThpm = 1000 MHz (MOUTapll)
	 *
	 * DOUTcopy    = MOUThpm   / (COPY_RATIO + 1)   = 200 MHz (4)
	 * SCLK_HPM    = DOUTcopy  / (HPM_RATIO + 1)    = 200 MHz (0)
	 * ACLK_CORES  = ARMCLK    / (CORES_RATIO + 1)  = 1000 MHz (0)
	 */

	/** CLK_DIV_CPU1 */
	clr = COPY_RATIO(7) | HPM_RATIO(7) | CORES_RATIO(7);
	set = COPY_RATIO(4) | HPM_RATIO(0) | CORES_RATIO(0);

	clrsetbits_le32(&clk->div_cpu1, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_cpu1) & DIV_STAT_CPU1_CHANGING)
		continue;

	/**
	 * Set dividers for -->
	 * MOUTdmc  = 800 MHz
	 * MOUTdphy = 800 MHz
	 *
	 * ACLK_ACP  = MOUTdmc   / (ACP_RATIO + 1)      = 200 MHz (3)
	 * PCLK_ACP  = ACLK_ACP  / (ACP_PCLK_RATIO + 1) = 100 MHz (1)
	 * SCLK_DPHY = MOUTdphy  / (DPHY_RATIO + 1)     = 400 MHz (1)
	 * SCLK_DMC  = MOUTdmc   / (DMC_RATIO + 1)      = 400 MHz (1)
	 * ACLK_DMCD = SCLK_DMC  / (DMCD_RATIO + 1)     = 200 MHz (1)
	 * ACLK_DMCP = ACLK_DMCD / (DMCP_RATIO + 1)     = 100 MHz (1)
	 */

	/** CLK_DIV_DMC0 */
	clr = ACP_RATIO(7) | ACP_PCLK_RATIO(7) | DPHY_RATIO(7) |
	      DMC_RATIO(7) | DMCD_RATIO(7) | DMCP_RATIO(7);
	set = ACP_RATIO(3) | ACP_PCLK_RATIO(1) | DPHY_RATIO(1) |
	      DMC_RATIO(1) | DMCD_RATIO(1) | DMCP_RATIO(1);

	clrsetbits_le32(&clk->div_dmc0, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_dmc0) & DIV_STAT_DMC0_CHANGING)
		continue;

	/**
	 * For:
	 * MOUTg2d = 800 MHz
	 * MOUTc2c = 800 Mhz
	 * MOUTpwi = 24 MHz
	 *
	 * SCLK_G2D_ACP = MOUTg2d  / (G2D_ACP_RATIO + 1)  = 200 MHz (3)
	 * SCLK_C2C     = MOUTc2c  / (C2C_RATIO + 1)      = 400 MHz (1)
	 * SCLK_PWI     = MOUTpwi  / (PWI_RATIO + 1)      = 24 MHz (0)
	 * ACLK_C2C     = SCLK_C2C / (C2C_ACLK_RATIO + 1) = 200 MHz (1)
	 * DVSEM_RATIO : It decides frequency for PWM frame time slot in DVS emulation mode.
	 * DPM_RATIO   : It decides frequency of DPM channel clock.
	 */

	/** CLK_DIV_DMC1 */
	clr = G2D_ACP_RATIO(15) | C2C_RATIO(7) | PWI_RATIO(15) |
	      C2C_ACLK_RATIO(7) | DVSEM_RATIO(127) | DPM_RATIO(127);
	set = G2D_ACP_RATIO(3) | C2C_RATIO(1) | PWI_RATIO(0) |
	      C2C_ACLK_RATIO(1) | DVSEM_RATIO(1) | DPM_RATIO(1);

	clrsetbits_le32(&clk->div_dmc1, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_dmc1) & DIV_STAT_DMC1_CHANGING)
		continue;

	/**
	 * MOUTmpll        = 800 MHz
	 * MOUTvpll        = 54 MHz
	 *
	 * ACLK_200        = MOUTACLK_200        / (ACLK_200_RATIO + 1)        = 200 MHz (3)
	 * ACLK_100        = MOUTACLK_100        / (ACLK_100_RATIO + 1)        = 100 MHz (7)
	 * ACLK_160        = MOUTACLK_160        / (ACLK_160_RATIO + 1)        = 160 MHz (4)
	 * ACLK_133        = MOUTACLK_133        / (ACLK_133_RATIO + 1)        = 133 MHz (5)
	 * ONENAND         = MOUTONENAND_1       / (ONENAND_RATIO + 1)         = 160 MHz (0)
	 * ACLK_266_GPS    = MOUTACLK_266_GPS    / (ACLK_266_GPS_RATIO + 1)    = 266 MHz (2)
	 * ACLK_400_MCUISP = MOUTACLK_400_MCUISP / (ACLK_400_MCUISP_RATIO + 1) = 400 MHz (1)
	 */

	/** CLK_DIV_TOP */
	clr = ACLK_200_RATIO(7) | ACLK_100_RATIO(15) | ACLK_160_RATIO(7) | 
	      ACLK_133_RATIO(7) | ONENAND_RATIO(7) | ACLK_266_GPS_RATIO(7) | ACLK_400_MCUISP_RATIO(7);
	set = ACLK_200_RATIO(3) | ACLK_100_RATIO(7) | ACLK_160_RATIO(4) |
	      ACLK_133_RATIO(5) | ONENAND_RATIO(0) | ACLK_266_GPS_RATIO(2) | ACLK_400_MCUISP_RATIO(1);

	clrsetbits_le32(&clk->div_top, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_top) & DIV_STAT_TOP_CHANGING)
		continue;

	/**
	 * ACLK_GDL = MOUTGDL / (GDL_RATIO + 1) = 200 MHz (3)
	 * ACLK_GPL = MOUTGPL / (GPL_RATIO + 1) = 100 MHz (1)
	 */

	/** CLK_DIV_LEFTBUS */
	clr = GDL_RATIO(7) | GPL_RATIO(7);
	set = GDL_RATIO(3) | GPL_RATIO(1);

	clrsetbits_le32(&clk->div_leftbus, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_leftbus) & DIV_STAT_LEFTBUS_CHANGING)
		continue;

	/**
	 * ACLK_GDR = MOUTGDR / (GDR_RATIO + 1) = 200 MHz (3)
	 * ACLK_GPR = MOUTGPR / (GPR_RATIO + 1) = 100 MHz (1)
	 */

	/** CLK_DIV_RIGHTBUS */
	clr = GPR_RATIO(7) | GDR_RATIO(7);
	set = GPR_RATIO(3) | GDR_RATIO(1);

	clrsetbits_le32(&clk->div_rightbus, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_rightbus) & DIV_STAT_RIGHTBUS_CHANGING)
		continue;

	/**
	 * MOUTUART[1-4] = 800 Mhz (MPLL)
	 *
	 * SCLK_UART0 = MOUTUART0 / (UART0_RATIO + 1) = 100 MHz (7)
	 * SCLK_UART1 = MOUTUART1 / (UART1_RATIO + 1) = 100 MHz (7)
	 * SCLK_UART2 = MOUTUART2 / (UART2_RATIO + 1) = 100 MHz (7)
	 * SCLK_UART3 = MOUTUART3 / (UART3_RATIO + 1) = 100 MHz (7)
	 * SCLK_UART4 = MOUTUART4 / (UART4_RATIO + 1) = 100 MHz (7)
	 */
	/** CLK_DIV_PERIL0 */
	clr = UART0_RATIO(15) | UART1_RATIO(15) | UART2_RATIO(15) |
	      UART3_RATIO(15) | UART4_RATIO(15);
	set = UART0_RATIO(7) | UART1_RATIO(7) | UART2_RATIO(7) |
          UART3_RATIO(7) | UART4_RATIO(7);

	clrsetbits_le32(&clk->div_peril0, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_peril0) & DIV_STAT_PERIL0_CHANGING)
		continue;
	/**
	 * For MOUTMMC0-3 = 800 MHz (MPLL)
	 *
	 * SCLK_MIPIHSI = MOUTMIPIHSI / (MIPIHSI_RATIO + 1) = 200 MHz (3)
	 */
	/* CLK_DIV_FSYS0 */
	clr = MIPIHSI_RATIO(15);
	set = MIPIHSI_RATIO(3);

	clrsetbits_le32(&clk->div_fsys0, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_fsys0) & DIV_STAT_FSYS0_CHANGING)
		continue;

	/**
	 * For MOUTMMC0-3 = 800 MHz (MPLL)
	 *
	 * DOUTMMC0  = MOUTMMC0 / (MMC0_RATIO + 1)     = 100 MHz (7)
	 * SCLK_MMC0 = DOUTMMC0 / (MMC0_PRE_RATIO + 1) = 50 MHz (1)
	 * DOUTMMC1  = MOUTMMC1 / (MMC1_RATIO + 1)     = 100 MHz (7)
	 * SCLK_MMC1 = DOUTMMC1 / (MMC1_PRE_RATIO + 1) = 50 MHz (1)
	 */
	/* CLK_DIV_FSYS1 */
	clr = MMC0_RATIO(15) | MMC0_PRE_RATIO(255) | MMC1_RATIO(15) |
	      MMC1_PRE_RATIO(255);
	
	set = MMC0_RATIO(7) | MMC0_PRE_RATIO(1) | MMC1_RATIO(7) |
			  MMC1_PRE_RATIO(1);

	clrsetbits_le32(&clk->div_fsys1, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_fsys1) & DIV_STAT_FSYS1_CHANGING)
		continue;

	/**
	 * For MOUTmmc0-3 = 800 MHz (MPLL)
	 *
	 * DOUTmmc3  = MOUTmmc3 / (MMC2_RATIO + 1)     = 100 MHz (7)
	 * sclk_mmc3 = DOUTmmc3 / (MMC2_PRE_RATIO + 1) = 50 MHz (1)
	 * DOUTmmc2  = MOUTmmc2 / (MMC3_RATIO + 1)     = 100 MHz (7)
	 * sclk_mmc2 = DOUTmmc2 / (MMC3_PRE_RATIO + 1) = 50 MHz (1)
	*/
	/* CLK_DIV_FSYS2 */
	clr = MMC2_RATIO(15) | MMC2_PRE_RATIO(255) | MMC3_RATIO(15) |
	      MMC3_PRE_RATIO(255);
	set = MMC2_RATIO(7) | MMC2_PRE_RATIO(1) | MMC3_RATIO(7) |
	      MMC3_PRE_RATIO(1);

	clrsetbits_le32(&clk->div_fsys2, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_fsys2) & DIV_STAT_FSYS2_CHANGING)
		continue;

	/**
	 * For MOUTmmc4 = 800 MHz (MPLL)
	 *
	 * DOUTmmc4  = MOUTmmc4 / (MMC4_RATIO + 1)     = 100 MHz (7)
	 * sclk_mmc4 = DOUTmmc4 / (MMC4_PRE_RATIO + 1) = 50 MHz (1)
	*/
	/* CLK_DIV_FSYS3 */
	clr = MMC4_RATIO(15) | MMC4_PRE_RATIO(255);
	set = MMC4_RATIO(7) | MMC4_PRE_RATIO(1);

	clrsetbits_le32(&clk->div_fsys3, clr, set);

	/* Wait for divider ready status */
	while (readl(&clk->div_stat_fsys3) & DIV_STAT_FSYS3_CHANGING)
		continue;

/************************************************************
 * Step 2:
 *
 * Set K, AFC, MRR, MFR values if necessary 
 * (Refer to (A, M, E, V)PLL_CON1 SFRs)
 * Turn on a PLL (Refer to (A, M, E, V) PLL_CON0 SFRs)
 ************************************************************/

	/* Set APLL to 1000MHz */
	/** APLL_CON1 */
	clr = AFC(31) | LOCK_CON_DLY(31) | LOCK_CON_IN(3) |
	      LOCK_CON_OUT(3) |FEED_EN(1)| AFC_ENB(1) |
	      DCC_ENB(1) | BYPASS(1) |RESV0(1) | RESV1(1);
	set = AFC(0) | LOCK_CON_DLY(8) | LOCK_CON_IN(3) |
	      LOCK_CON_OUT(0) |FEED_EN(0)| AFC_ENB(0) |
	      DCC_ENB(1) | BYPASS(0) |RESV0(0) | RESV1(0);

	clrsetbits_le32(&clk->apll_con1, clr, set);

	/** APLL_CON0 */
	clr_pll_con0 = SDIV(7) | PDIV(63) | MDIV(1023) | FSEL(1) | PLL_ENABLE(1);
	set = SDIV(0) | PDIV(3) | MDIV<
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值