177 lines
4.5 KiB
C
177 lines
4.5 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
||||
|
|
/*
|
|||
|
|
* common/cmd_startdsp.c
|
|||
|
|
*
|
|||
|
|
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
|||
|
|
*
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#include <common.h>
|
|||
|
|
#include <command.h>
|
|||
|
|
#include <asm/arch/cpu.h>
|
|||
|
|
#include <asm/arch/secure_apb.h>
|
|||
|
|
#include <asm/arch/timer.h>
|
|||
|
|
#include <asm/arch/bl31_apis.h>
|
|||
|
|
#include <asm/arch/pwr_ctrl.h>
|
|||
|
|
#include <serial.h>
|
|||
|
|
#include <asm/arch-p1/register.h>
|
|||
|
|
|
|||
|
|
#define Wr(addr, data) *(volatile uint32_t *)(addr)=(data)
|
|||
|
|
#define Rd(addr) *(volatile uint32_t *)(addr)
|
|||
|
|
|
|||
|
|
// .clk0 (cts_oscin_clk ),
|
|||
|
|
// .clk1 (fclk_div2p5 ),
|
|||
|
|
// .clk2 (fclk_div3 ),
|
|||
|
|
// .clk3 (m4_pll_clk ),
|
|||
|
|
// .clk4 (hifi_pll_clk ),
|
|||
|
|
// .clk5 (fclk_div4 ),
|
|||
|
|
// .clk6 (gp2_pll_clk ),
|
|||
|
|
// .clk7 (cts_rtc_clk ),
|
|||
|
|
void set_m4_clk(int sel, int div)
|
|||
|
|
{
|
|||
|
|
uint32_t reg_val = 0;
|
|||
|
|
|
|||
|
|
reg_val = Rd(CLKCTRL_M4_CLK_CTRL);
|
|||
|
|
// enable osc_clk firstly
|
|||
|
|
if (reg_val == 0) {
|
|||
|
|
reg_val = (1 << 13);
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val); /* pre_a clock gate en */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reg_val = Rd(CLKCTRL_M4_CLK_CTRL);
|
|||
|
|
if (reg_val & (1 << 15)) {
|
|||
|
|
/* Pre_a source select M4_PLL, pre_a clock gate en, Pre_a div5 */
|
|||
|
|
reg_val = (reg_val & ~((0x7 << 10) | (1 << 13) | (0x3ff << 0)))
|
|||
|
|
| ((sel << 10) | (0 << 13) | (div << 0));
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val);
|
|||
|
|
reg_val = (reg_val & ~((0x7 << 10) | (1 << 13) | (0x3ff << 0)))
|
|||
|
|
| ((sel << 10) | (1 << 13) | (div << 0));
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val);
|
|||
|
|
/* select pre_a */
|
|||
|
|
reg_val = Rd(CLKCTRL_M4_CLK_CTRL);
|
|||
|
|
reg_val &= ~(1 << 15);
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val);
|
|||
|
|
} else {
|
|||
|
|
/* Pre_b source select M4_PLL, pre_b clock gate en, Pre_b div5 */
|
|||
|
|
reg_val = (reg_val & ~((0x7 << 26) | (1 << 29) | (0x3ff << 16)))
|
|||
|
|
| ((sel << 26) | (0 << 29) | (div << 16));
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val);
|
|||
|
|
reg_val = (reg_val & ~((0x7 << 26) | (1 << 29) | (0x3ff << 16)))
|
|||
|
|
| ((sel << 26) | (1 << 29) | (div << 16));
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val);
|
|||
|
|
/* select pre_b */
|
|||
|
|
reg_val = Rd(CLKCTRL_M4_CLK_CTRL);
|
|||
|
|
reg_val |= (1 << 15);
|
|||
|
|
Wr(CLKCTRL_M4_CLK_CTRL, reg_val);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void set_m4_pll_clk(uint32_t freq)
|
|||
|
|
{
|
|||
|
|
uint32_t M, N, OD = 0;
|
|||
|
|
uint32_t reg_cntl0;
|
|||
|
|
|
|||
|
|
for (int i = 0; i < 6; i++) {
|
|||
|
|
if ((freq << i) >= 1600 && (freq << i) < 3200) {
|
|||
|
|
OD = i;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
M = ((freq + 12) << OD) / 24;
|
|||
|
|
N = 1;
|
|||
|
|
reg_cntl0 = (OD << 12) | (N << 16) | M;
|
|||
|
|
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL0, (0x2 << 28) | reg_cntl0); // reset pll
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL0, (0x3 << 28) | reg_cntl0); // reset + en
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL1, 0x1420500f);
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL2, 0x00023041);
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL3, 0x00000000);
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL0, (0x1 << 28) | reg_cntl0); // release reset
|
|||
|
|
Wr(CLKCTRL_M4PLL_CTRL2, 0x00023001);
|
|||
|
|
|
|||
|
|
while ((Rd(CLKCTRL_M4PLL_STS) & 0x80000000) == 0)
|
|||
|
|
;
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
static int do_startm4(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
|
|
{
|
|||
|
|
uint32_t cpu_id;
|
|||
|
|
uint32_t bin_addr;
|
|||
|
|
uint32_t bank_config;
|
|||
|
|
uint32_t id;
|
|||
|
|
uint32_t cmd;
|
|||
|
|
|
|||
|
|
int ret = 0;
|
|||
|
|
|
|||
|
|
if (argc != 5) {
|
|||
|
|
printf("Plese input M4 boot args:cpu_id, bin_addr!\n");
|
|||
|
|
return CMD_RET_USAGE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cpu_id = simple_strtoul(argv[1], NULL, 16);
|
|||
|
|
bin_addr = simple_strtoul(argv[2], NULL, 16);
|
|||
|
|
bank_config = simple_strtoul(argv[3], NULL, 16);
|
|||
|
|
cmd = simple_strtoul(argv[4], NULL, 16);
|
|||
|
|
|
|||
|
|
if (bank_config == 0u) {
|
|||
|
|
/*default:M4A_ROM=M4A_RAM=M4B_ROM=M4B_RAM=128K */
|
|||
|
|
bank_config = 0xFCB87430u;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cpu_id >= 2) {
|
|||
|
|
printf("\nPlese input M4 boot cpu_id less than 2!");
|
|||
|
|
return CMD_RET_USAGE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (bin_addr & 0x3u) {
|
|||
|
|
printf("Plese load the bin in ddr address in word(4 bytes) align.\n");
|
|||
|
|
return CMD_RET_USAGE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cpu_id == 0) {
|
|||
|
|
printf("M4A is boot, cpu_id:%d\n", cpu_id);
|
|||
|
|
printf("M4A bin address:0x%x\n", bin_addr);
|
|||
|
|
} else {
|
|||
|
|
printf("M4B is boot, cpu_id:%d\n", cpu_id);
|
|||
|
|
printf("M4B bin address:0x%x\n", bin_addr);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cmd == MFH_V2_START) {
|
|||
|
|
/*hold reset M4 */
|
|||
|
|
id = PACK_SMC_SUBID_ID(MFH_V2_RESET, cpu_id);
|
|||
|
|
start_m4(id, bin_addr, bank_config);
|
|||
|
|
|
|||
|
|
if (cpu_id == 0) {
|
|||
|
|
/*repower on cpu */
|
|||
|
|
pwr_ctrl_psci_smc(PM_M4A, 1);
|
|||
|
|
} else {
|
|||
|
|
/*repower on cpu */
|
|||
|
|
pwr_ctrl_psci_smc(PM_M4B, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 300MHz */
|
|||
|
|
set_m4_clk(3u, 4u);
|
|||
|
|
set_m4_pll_clk(1500);
|
|||
|
|
id = PACK_SMC_SUBID_ID(cmd, cpu_id);
|
|||
|
|
start_m4(id, bin_addr, bank_config);
|
|||
|
|
} else {
|
|||
|
|
id = PACK_SMC_SUBID_ID(MFH_V2_RESET, cpu_id);
|
|||
|
|
start_m4(id, bin_addr, bank_config);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
U_BOOT_CMD(
|
|||
|
|
startm4, 5, 1, do_startm4,
|
|||
|
|
"load bin from DDR memory address(soc: p1) ",
|
|||
|
|
"\narg[0]: cmd\n"
|
|||
|
|
"arg[1]: cpu_id, the cpu id 0 is start M4A, the cpu id 1 is start M4B\n"
|
|||
|
|
"arg[2]: bin_ddr, load execution bin from ddr memory address\n"
|
|||
|
|
"arg[3]: bank config, default:0xFCB87430u\n"
|
|||
|
|
"arg[4]: cmd, 0x21--START, 0x22--STOP, 0x22--RESET\n"
|
|||
|
|
);
|
|||
|
|
|