S6: PXP Bringup Bootloader bootup DSP code porting [2/2]

PD#SWPL-153936

Problem:
S6 PXP Bringup DSP.

Solution:
Code porting from t3x and ucode.

Verify:
Test in S6 PXP.

Change-Id: Idc6683d33469c455dd3754b12ebdfdf164738e2c
Signed-off-by: bangzheng.liu <bangzheng.liu@amlogic.com>
diff --git a/cmd/amlogic/cmd_startdsp.c b/cmd/amlogic/cmd_startdsp.c
new file mode 100644
index 0000000..b4da8ae
--- /dev/null
+++ b/cmd/amlogic/cmd_startdsp.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/amlogic/arch/register.h>
+#include <asm/amlogic/arch/bl31_apis.h>
+#include <asm/amlogic/arch/pwr_ctrl.h>
+#include <serial.h>
+
+// --------------------------------------------------
+//                    set_dsp_clk
+// --------------------------------------------------
+
+/*
+ * set_dsp_clk
+ * freq_sel:
+ *      [ for S6 ]
+ *           0:   1000MHz  gp2_pll
+ *           1:    800MHz  fclk_div2p5
+ *           2: 666.67MHz  fclk_div3
+ *           3:     24MHz  oscin
+ *           4:    500MHz  fclk_div4
+ *           5:    400MHz  fclk_div2p5/2
+ *           6:    333MHz  fclk_div3/2
+ *           7:    250MHz  fclk_div4/2
+ *           8:    200MHz  fclk_div5/2
+ *           9:    100MHz  fclk_div5/4
+ *          10: 245.76MHz  hifi_pll/2
+ *     default:    800MHz  fclk_div2p5
+ */
+
+int set_dsp_clk(uint32_t id, uint32_t freq_sel)
+{
+	uint32_t control;
+	uint32_t clk_sel;
+	uint32_t clk_div;
+	uint32_t addr = 0;
+	char *dsp_clk_tag = NULL;
+	int ret = 0;
+
+	switch (id) {
+	case 0:
+		addr = CLKCTRL_DSPA_CLK_CTRL0;
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+
+	if (ret) {
+		printf("dsp clk set failed: invalid id %d\n", id);
+		return ret;
+	}
+
+	// Make sure not busy from last setting and we currently match the last setting
+
+	control = readl(addr);
+	printf("CLKCTRL_DSP_CLK_CTRL0 = %x\n", readl(addr));
+
+	switch (freq_sel) {
+	case 0:
+		clk_sel = 4;
+		clk_div = 0;
+		dsp_clk_tag = "gp2_pll:1000MHz";
+		break;
+	case 1:
+		clk_sel = 1;
+		clk_div = 0;
+		dsp_clk_tag = "fclk_div2p5:800MHz";
+		break;
+	case 2:
+		clk_sel = 2;
+		clk_div = 0;
+		dsp_clk_tag = "fclk_div3:666.67MHz";
+		break;
+	case 3:
+		clk_sel = 0;
+		clk_div = 0;
+		dsp_clk_tag = "oscin:24MHz";
+		break;
+	case 4:
+		clk_sel = 5;
+		clk_div = 0;
+		dsp_clk_tag = "fclk_div4:500MHz";
+		break;
+	case 5:
+		clk_sel = 3;
+		clk_div = 0;
+		dsp_clk_tag = "fclk_div5:400MHz";
+		break;
+	case 6:
+		clk_sel = 2;
+		clk_div = 1;
+		dsp_clk_tag = "fclk_div3/2:333MHz";
+		break;
+	case 7:
+		clk_sel = 5;
+		clk_div = 1;
+		dsp_clk_tag = "fclk_div4/2:250MHz";
+		break;
+	case 8:
+		clk_sel = 3;
+		clk_div = 1;
+		dsp_clk_tag = "fclk_div2p5/2:200MHz";
+		break;
+	case 9:
+		clk_sel = 3;
+		clk_div = 3;
+		dsp_clk_tag = "fclk_div5/4:100MHz";
+		break;
+	case 10:
+		clk_sel = 6;
+		clk_div = 1;
+		dsp_clk_tag = "hifi_pll/2:245.76MHz";
+		break;
+	default:
+		clk_sel = 1;
+		clk_div = 0;
+		dsp_clk_tag = "fclk_div2p5:800MHz (default)";
+		break;
+	}
+
+	printf("CLK_UTIL:dsp[%d]:%s\n", id, dsp_clk_tag);
+
+	if (control & (1 << 15)) {   //if sync_mux ==1, sel mux 0
+		control = (control & ~((1 << 15) | (0x3ff << 0) | (0x7 << 10))) |
+			(1 << 13) | (1 << 29) | (clk_div << 0) | (clk_sel << 10);
+	} else {
+		control = (control & ~((1 << 15) | (0x3ff << 16) | (0x7 << 26))) |
+			(1 << 13) | (1 << 29) | (clk_div << 16) | (clk_sel << 26) | (1 << 15);
+	}
+
+	writel(control, addr);
+
+	if (id == 0)
+		printf("CLKCTRL_DSPA_CLK_CTRL0 = %x\n", readl(addr));
+
+	return ret;
+}
+
+static int do_startdsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	uint32_t dspid;
+	uint32_t addr;
+	uint32_t freq_sel;
+	uint32_t bus_cfg;
+	uint32_t cfg0;
+	uint32_t StatVectorSel;
+	uint32_t strobe = 1;
+
+	if (argc <= 1) {
+		printf("please input dsp boot args: id, address, clk!\n");
+		return CMD_RET_USAGE;
+	}
+
+	dspid = simple_strtoul(argv[1], NULL, 16);
+	if (dspid > 1) {
+		printf("start dsp failed: invalid id\n");
+		return -1;
+	}
+
+	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%x\n", addr);
+	printf("dsp clk num:%d\n", freq_sel);
+
+	StatVectorSel = (addr != 0xfffa0000);
+	cfg0 = 0x1 | StatVectorSel << 1 | strobe << 2;
+
+	power_set_dsp(PDID_DSPA, PWR_ON);
+
+	udelay(100);
+
+	if (set_dsp_clk(dspid, freq_sel))
+		return -1;
+
+	udelay(100);
+
+	init_dsp(dspid, addr, cfg0, bus_cfg);
+	printf("dsp init over!\n");
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	startdsp, 5, 1, do_startdsp,
+	"load dspboot.bin from address",
+	"\narg[0]: cmd\n"
+	"arg[1]: dspid\n"
+	"arg[2]: dspboot.bin load address!\n"
+	"arg[3]: dsp clk set\n 0:1G 1:800M 2:667M 3:24M 4:500M 5:400M 6:333M 7:250M 8:200M 9:100M 10:245.76M\n"
+	"arg[4]: bus select for dsp access one 4G of 16G ddr: 0x00: 0~4G 0x01: 4~8G 0x10: 8~12G 0x11: 12~16G\n"
+);
+