mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-07 05:34:28 +00:00
b52a199e32
Few of the rockchip family SoC atleast rk3288, rk3399 are sharing some cru register bits so adding common code between these SoC families would require to include both cru include files that indeed resulting function declarations error. So, create a common cru include as cru.h then include the rk3399 arch cru include file and move the common cru register bit definitions into it. The rest of rockchip cru files will add it in future. Reviewed-by: Kever Yang <kever.yang@rock-chips.com> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
203 lines
4.1 KiB
C
203 lines
4.1 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2016 Rockchip Electronics Co., Ltd
|
|
*/
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <env.h>
|
|
#include <clk.h>
|
|
#include <init.h>
|
|
#include <asm/armv7.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch-rockchip/bootrom.h>
|
|
#include <asm/arch-rockchip/clock.h>
|
|
#include <asm/arch-rockchip/cru.h>
|
|
#include <asm/arch-rockchip/hardware.h>
|
|
#include <asm/arch-rockchip/grf_rk3288.h>
|
|
#include <asm/arch-rockchip/pmu_rk3288.h>
|
|
#include <asm/arch-rockchip/qos_rk3288.h>
|
|
#include <asm/arch-rockchip/sdram.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
#define GRF_BASE 0xff770000
|
|
|
|
const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
|
|
[BROM_BOOTSOURCE_EMMC] = "/dwmmc@ff0f0000",
|
|
[BROM_BOOTSOURCE_SD] = "/dwmmc@ff0c0000",
|
|
};
|
|
|
|
#ifdef CONFIG_SPL_BUILD
|
|
static void configure_l2ctlr(void)
|
|
{
|
|
u32 l2ctlr;
|
|
|
|
l2ctlr = read_l2ctlr();
|
|
l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
|
|
|
|
/*
|
|
* Data RAM write latency: 2 cycles
|
|
* Data RAM read latency: 2 cycles
|
|
* Data RAM setup latency: 1 cycle
|
|
* Tag RAM write latency: 1 cycle
|
|
* Tag RAM read latency: 1 cycle
|
|
* Tag RAM setup latency: 1 cycle
|
|
*/
|
|
l2ctlr |= (1 << 3 | 1 << 0);
|
|
write_l2ctlr(l2ctlr);
|
|
}
|
|
#endif
|
|
|
|
int rk3288_qos_init(void)
|
|
{
|
|
int val = 2 << PRIORITY_HIGH_SHIFT | 2 << PRIORITY_LOW_SHIFT;
|
|
/* set vop qos to higher priority */
|
|
writel(val, CPU_AXI_QOS_PRIORITY + VIO0_VOP_QOS);
|
|
writel(val, CPU_AXI_QOS_PRIORITY + VIO1_VOP_QOS);
|
|
|
|
if (!fdt_node_check_compatible(gd->fdt_blob, 0,
|
|
"rockchip,rk3288-tinker")) {
|
|
/* set isp qos to higher priority */
|
|
writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_R_QOS);
|
|
writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W0_QOS);
|
|
writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W1_QOS);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int arch_cpu_init(void)
|
|
{
|
|
#ifdef CONFIG_SPL_BUILD
|
|
configure_l2ctlr();
|
|
#else
|
|
/* We do some SoC one time setting here. */
|
|
struct rk3288_grf * const grf = (void *)GRF_BASE;
|
|
|
|
/* Use rkpwm by default */
|
|
rk_setreg(&grf->soc_con2, 1 << 0);
|
|
|
|
/*
|
|
* Disable JTAG on sdmmc0 IO. The SDMMC won't work until this bit is
|
|
* cleared
|
|
*/
|
|
rk_clrreg(&grf->soc_con0, 1 << 12);
|
|
|
|
rk3288_qos_init();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
|
|
void board_debug_uart_init(void)
|
|
{
|
|
/* Enable early UART on the RK3288 */
|
|
struct rk3288_grf * const grf = (void *)GRF_BASE;
|
|
|
|
rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
|
|
GPIO7C6_MASK << GPIO7C6_SHIFT,
|
|
GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
|
|
GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
|
|
}
|
|
#endif
|
|
|
|
static void rk3288_detect_reset_reason(void)
|
|
{
|
|
struct rockchip_cru *cru = rockchip_get_cru();
|
|
const char *reason;
|
|
|
|
if (IS_ERR(cru))
|
|
return;
|
|
|
|
switch (cru->cru_glb_rst_st) {
|
|
case GLB_POR_RST:
|
|
reason = "POR";
|
|
break;
|
|
case FST_GLB_RST_ST:
|
|
case SND_GLB_RST_ST:
|
|
reason = "RST";
|
|
break;
|
|
case FST_GLB_TSADC_RST_ST:
|
|
case SND_GLB_TSADC_RST_ST:
|
|
reason = "THERMAL";
|
|
break;
|
|
case FST_GLB_WDT_RST_ST:
|
|
case SND_GLB_WDT_RST_ST:
|
|
reason = "WDOG";
|
|
break;
|
|
default:
|
|
reason = "unknown reset";
|
|
}
|
|
|
|
env_set("reset_reason", reason);
|
|
|
|
/*
|
|
* Clear cru_glb_rst_st, so we can determine the last reset cause
|
|
* for following resets.
|
|
*/
|
|
rk_clrreg(&cru->cru_glb_rst_st, GLB_RST_ST_MASK);
|
|
}
|
|
|
|
__weak int rk3288_board_late_init(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int rk_board_late_init(void)
|
|
{
|
|
rk3288_detect_reset_reason();
|
|
|
|
return rk3288_board_late_init();
|
|
}
|
|
|
|
static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
char * const argv[])
|
|
{
|
|
static const struct {
|
|
char *name;
|
|
int id;
|
|
} clks[] = {
|
|
{ "osc", CLK_OSC },
|
|
{ "apll", CLK_ARM },
|
|
{ "dpll", CLK_DDR },
|
|
{ "cpll", CLK_CODEC },
|
|
{ "gpll", CLK_GENERAL },
|
|
#ifdef CONFIG_ROCKCHIP_RK3036
|
|
{ "mpll", CLK_NEW },
|
|
#else
|
|
{ "npll", CLK_NEW },
|
|
#endif
|
|
};
|
|
int ret, i;
|
|
struct udevice *dev;
|
|
|
|
ret = rockchip_get_clk(&dev);
|
|
if (ret) {
|
|
printf("clk-uclass not found\n");
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(clks); i++) {
|
|
struct clk clk;
|
|
ulong rate;
|
|
|
|
clk.id = clks[i].id;
|
|
ret = clk_request(dev, &clk);
|
|
if (ret < 0)
|
|
continue;
|
|
|
|
rate = clk_get_rate(&clk);
|
|
printf("%s: %lu\n", clks[i].name, rate);
|
|
|
|
clk_free(&clk);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_CMD(
|
|
clock, 2, 1, do_clock,
|
|
"display information about clocks",
|
|
""
|
|
);
|