blob: 30eaca2e1bc5f3f95581ced1ae366e47d84a4dcf [file] [log] [blame]
/* 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-tm2/secure_apb.h>
#include <asm/arch-tm2/timer.h>
#include <asm/arch-tm2/mailbox.h>
#include <serial.h>
#define writel32(val, reg) (*((volatile uint32_t *)((uintptr_t)(reg)))) = (val)
#define readl32(reg) (*((volatile uint32_t *)((uintptr_t)(reg))))
/*
* clk_util_set_dsp_clk
* freq_sel: 0:286MHz fclk_7
* 1:400MHz fclk_5
* 2:500MHz fclk_2/2
* 4:333MHz fclk_3/2
* 5:250Mhz fclk_2/4
* 6:200Mhz fclk_5/2
* 7:100Mhz fclk_5/4
* 8:24Mhz oscin
* others:286MHz fclk/7
*/
// --------------------------------------------------
// clocks_set_cpu_core_clk
// --------------------------------------------------
void clk_util_set_dsp_clk(uint32_t id, uint32_t freq_sel)
{
uint32_t control;
uint32_t clk_sel;
uint32_t clk_div;
uint32_t addr;
addr = HHI_DSP_CLK_CNTL;
// Make sure not busy from last setting and we currently match the last setting
control = readl32(addr);
switch (freq_sel)
{
case 1 : clk_sel = 2; clk_div =0; printf("CLK_UTIL:dsp:fclk/5:400MHz\n" ); break;
case 2 : clk_sel = 0; clk_div =1; printf("CLK_UTIL:dsp:fclk/4:500MHz\n"); break;
//case 3 : clk_sel = 1; clk_div =0; printf("CLK_UTIL:dsp:fclk/3:667MHz\n"); break;
case 4 : clk_sel = 1; clk_div =1; printf("CLK_UTIL:dsp:fclk/3/2:333MHz\n" ); break;
case 5 : clk_sel = 0; clk_div =3; printf("CLK_UTIL:dsp:fclk/2:250MHz\n"); break;
case 6 : clk_sel = 2; clk_div =1; printf("CLK_UTIL:dsp:fclk/4/2:200MHz\n"); break;
case 7 : clk_sel = 2; clk_div =3; printf("CLK_UTIL:dsp:fclk/4/4:100MHz\n"); break;
case 8 : clk_sel = 4; clk_div =0; printf("CLK_UTIL:dsp:oscin:24MHz\n"); break;
//case 10 : clk_sel = 0; clk_div =0; printf ("CLK_UTIL:dsp:fclk/2:1000MHz\n"); break;
default : clk_sel = 3; clk_div =0; printf("CLK_UTIL:dsp:fclk/7:286MHz\n"); break;
}
switch ( id ) {
case 0:
if (control & (1 << 15)) { //if sync_mux ==1, sel mux 0
control = (control & ~( ( 1<<15) | (0xf<<0) | (0x7 <<4) ) ) | (1<<7) | (clk_div<<0) | (clk_sel<<4);
} else {
control = (control & ~( ( 1<<15) | (0xf<<8) | (0x7 <<12) ) ) | (1<<7) | (clk_div<<8) | (clk_sel<<12) | (1<<15);
}
break;
default :
if (control & (1 << 31)) { //if sync_mux ==1, sel mux 0
control = (control & ~( ( 1<<31) | (0xf<<16) | (0x7 <<20) ) ) | (1<<23) | (clk_div<<16) | (clk_sel<<20);
} else {
control = (control & ~( ( 1<<31) | (0xf<<24) | (0x7 <<28) ) ) | (1<<23) | (clk_div<<24) | (clk_sel<<28) | (1<<31);
}
break;
}
writel32(control,addr);
}
void start_dsp(uint32_t id,uint32_t reset_addr)
{
uint32_t StatVectorSel;
uint32_t strobe = 1;
//address remap
printf("\n start_dsp \n");
//*P_DSP_REMAP2 = 0x3000fff0; //replace the highest 12bits 0xfffxxxxx with 0x300xxxxx
StatVectorSel = (reset_addr!= 0xfffa0000);
//open the Dreset, Breset, irq_clken
if (id == 0) { //dspa
init_dsp(id,reset_addr, (0x1 | StatVectorSel<<1 | strobe<<2),(6 << 12)|(1<<6),(1<<14)|(1<<15)|(1<<1)|(1<<3)|(1<<2)|(1<<0)|(1<<31)|(1<<7));
//init_dsp(id,reset_addr, (0x1 | StatVectorSel<<1 | strobe<<2),(6 << 12)|(1<<6),(1<<14)|(1<<15)|(1<<1)|(1<<3)|(1<<2)|(1<<0)|(1<<31)|(1<<6));
//init_dsp(id,reset_addr, (0x1 | StatVectorSel<<1 | strobe<<2),0,0);
printf("dspa jtag enalble \n");
_udelay(50);
//init_dsp(id,reset_addr, (0x1 | StatVectorSel<<1 | strobe<<2),(6 << 12),);
printf("\n *P_DSP_CFG0 : ADDR_0X%p, value_0x%8x \n",P_DSP_CFG0,*P_DSP_CFG0);
// *P_DSP_CFG0 = (*P_DSP_CFG0 & ~(0xffff <<0)) | (1<<29) | (0<<0) ; //irq_clken
*P_DSP_CFG0 = (*P_DSP_CFG0 & ~(0xffff <<0)) | (0x2018 << 0) | (1<<29) | (0<<0) ; //irq_clken
_udelay(10);
*P_DSP_CFG0 = *P_DSP_CFG0 & ~(1<<31); //Dreset assert
_udelay(10);
// *P_DSP_CFG0 = *P_DSP_CFG0 | (1<<31); //Dreset deassert
// _udelay(10);
*P_DSP_CFG0 = *P_DSP_CFG0 & ~(1<<30); //Breset
_udelay(10);
// *P_DSP_CFG0 = *P_DSP_CFG0 | (1<<30); //Breset deassert
// _udelay(10);
printf("\n *P_DSP_CFG0 : ADDR_0X%p, value_0x%8x \n",P_DSP_CFG0,*P_DSP_CFG0);
} else {
init_dsp(id,reset_addr, (0x1 | StatVectorSel<<1 | strobe<<2),(7 << 12)|(1<<7),(1<<14)|(1<<15)|(1<<1)|(1<<3)|(1<<2)|(1<<0)|(1<<7)|(1<<31));
printf("dspb jtag enalble \n");
_udelay(500);
printf("\n *P_DSPB_CFG0 : ADDR_0X%p, value_0x%8x \n",P_DSPB_CFG0,*P_DSPB_CFG0);
// *P_DSPB_CFG0 = (*P_DSPB_CFG0 & ~((1<<31) | (1<<30) | (0xffff <<0)) ) | (1<<29) | (1<<0); //15:0 prid
// *P_DSPB_CFG0 = (*P_DSPB_CFG0 & ~(0xffff <<0)) | (1<<29) | (0<<0) ; //irq_clken
*P_DSPB_CFG0 = (*P_DSPB_CFG0 & ~(0xffff <<0)) | (0x2019 << 0) | (1<<29) | (0<<0) ; //irq_clken
_udelay(10);
*P_DSPB_CFG0 = *P_DSPB_CFG0 & ~(1<<31); //Dreset
_udelay(10);
*P_DSPB_CFG0 = *P_DSPB_CFG0 & ~(1<<30); //Breset
_udelay(10);
printf("\n *P_DSPB_CFG0 : ADDR_0X%p, value_0x%8x \n",P_DSPB_CFG0,*P_DSPB_CFG0);
}
}
//#define P_RESET0_LEVEL (volatile uint32_t *)0xffd01080
//#define P_RESET1_LEVEL (volatile uint32_t *)0xffd01084
//#define P_RESET2_LEVEL (volatile uint32_t *)0xffd01088
//#define P_RESET3_LEVEL (volatile uint32_t *)0xffd0108c
//#define P_RESET4_LEVEL (volatile uint32_t *)0xffd01090
//#define P_RESET5_LEVEL (volatile uint32_t *)0xffd01094
//#define P_RESET6_LEVEL (volatile uint32_t *)0xffd01098
//#define P_RESET7_LEVEL (volatile uint32_t *)0xffd0109c
void power_switch_to_dsp_a(int64_t pwr_cntl)
{
if (pwr_cntl == 1) {
printf("[PWR]: Power on DSP A\n");
// Powerup dsp a
writel32(readl32(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x1<<21)),P_AO_RTI_GEN_PWR_SLEEP0); // power on
_udelay(5);
// Power up memory
*P_HHI_DSP_MEM_PD_REG0 &= ~(0xffff<<0);
_udelay(5);
// reset
*P_RESET4_LEVEL &= ~(0x1<<0);
*P_RESET1_LEVEL &= ~(0x1<<20);
_udelay(5);
// remove isolation
writel32(readl32(P_AO_RTI_GEN_PWR_ISO0) & (~(0x1<<21)),P_AO_RTI_GEN_PWR_ISO0);
// pull up reset
*P_RESET4_LEVEL |= (0x1<<0);
*P_RESET1_LEVEL |= (0x1<<20);
_udelay(5);
} else {
// reset
*P_RESET4_LEVEL &= ~(0x1<<0);
*P_RESET1_LEVEL &= ~(0x1<<20);
// add isolation
writel32(readl32(P_AO_RTI_GEN_PWR_ISO0) | (0x1<<21),P_AO_RTI_GEN_PWR_ISO0 );
_udelay(5);
// power down memory
*P_HHI_DSP_MEM_PD_REG0 |= (0xffff<<0);
_udelay(5);
// power down dsp a
writel32(readl32(P_AO_RTI_GEN_PWR_SLEEP0) | (0x1<<21),P_AO_RTI_GEN_PWR_SLEEP0);
}
}
void power_switch_to_dsp_b(int64_t pwr_cntl)
{
if (pwr_cntl == 1) {
printf("[PWR]: Power on DSP B\n");
// Powerup dsp b
writel32(readl32(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x1<<22)),P_AO_RTI_GEN_PWR_SLEEP0); // power on
_udelay(5);
// Power up memory
*P_HHI_DSP_MEM_PD_REG0 &= ~(0xffff<<16);
_udelay(5);
// reset
*P_RESET4_LEVEL &= ~(0x1<<1);
*P_RESET1_LEVEL &= ~(0x1<<21);
_udelay(5);
// remove isolation
writel32(readl32(P_AO_RTI_GEN_PWR_ISO0) & (~(0x1<<22)),P_AO_RTI_GEN_PWR_ISO0);
// pull up reset
*P_RESET4_LEVEL |= (0x1<<1);
*P_RESET1_LEVEL |= (0x1<<21);
_udelay(5);
} else {
// reset
*P_RESET4_LEVEL &= ~(0x1<<1);
*P_RESET1_LEVEL &= ~(0x1<<21);
// add isolation
writel32(readl32(P_AO_RTI_GEN_PWR_ISO0) | (0x1<<22),P_AO_RTI_GEN_PWR_ISO0 );
_udelay(5);
// power down memory
*P_HHI_DSP_MEM_PD_REG0 |= (0xffff<<16);
_udelay(5);
// power down dsp a
writel32(readl32(P_AO_RTI_GEN_PWR_SLEEP0) | (0x1<<22),P_AO_RTI_GEN_PWR_SLEEP0);
}
}
void dsp_init(unsigned int dspid, uint32_t reset_addr, uint32_t freq_sel) {
printf("the rest_addr passing : 0x%8x \n",reset_addr);
clk_util_set_dsp_clk(dspid,freq_sel);
_udelay(10);
if (dspid == 0 )
power_switch_to_dsp_a(1); //start dsp0, at the reset address 0x30000000
else
power_switch_to_dsp_b(1); //start dsp1, at the reset address 0x30800000
start_dsp(dspid,reset_addr); //set the frep to 500Mhz
*P_AO_RTI_PULL_UP_EN_REG |= (0xf << 6 );
*P_AO_RTI_PULL_UP_REG |= (0xf << 6 );
}
static int do_startdsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned long addr;
unsigned int dspid;
uint32_t freq_sel;
int ret=0;
if (argc <= 1) {
printf("plese input dsp boot args:id, addrss, clk!\n");
return CMD_RET_USAGE;
}
dspid = simple_strtoul(argv[1], NULL, 16);
addr = simple_strtoul(argv[2], NULL, 16);
freq_sel = simple_strtoul(argv[3], NULL, 16);
printf("dsp%d boot \n",dspid);
printf("dspboot start address:0x%lx\n",addr);
printf("dsp clk num:%d\n",freq_sel);
dsp_init(dspid, addr, freq_sel);
printf("dsp init over! \n");
return ret;
}
U_BOOT_CMD(
startdsp, 4, 1, do_startdsp,
"load dspboot.bin from address",
"\n arg[0]: cmd\n"
"arg[1]: dspid \n"
"arg[2]: dspboot.bin load address!\n"
"arg[3]: dsp clk set 1:400M 2:500M 4:333M 5:250M 6:200M 7:100M 8 :24M"
);