- Reset improvements, enable coherence manager on ae350, k210 clk improvements, other fixes
This commit is contained in:
@@ -1026,6 +1026,7 @@ T: git https://source.denx.de/u-boot/custodians/u-boot-riscv.git
|
|||||||
F: arch/riscv/
|
F: arch/riscv/
|
||||||
F: cmd/riscv/
|
F: cmd/riscv/
|
||||||
F: doc/usage/sbi.rst
|
F: doc/usage/sbi.rst
|
||||||
|
F: drivers/sysreset/sysreset_sbi.c
|
||||||
F: drivers/timer/andes_plmt_timer.c
|
F: drivers/timer/andes_plmt_timer.c
|
||||||
F: drivers/timer/sifive_clint_timer.c
|
F: drivers/timer/sifive_clint_timer.c
|
||||||
F: tools/prelink-riscv.c
|
F: tools/prelink-riscv.c
|
||||||
|
|||||||
@@ -9,6 +9,22 @@
|
|||||||
#include <cpu_func.h>
|
#include <cpu_func.h>
|
||||||
#include <irq_func.h>
|
#include <irq_func.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
#include <asm/csr.h>
|
||||||
|
|
||||||
|
#define CSR_MCACHE_CTL 0x7ca
|
||||||
|
#define CSR_MMISC_CTL 0x7d0
|
||||||
|
#define CSR_MARCHID 0xf12
|
||||||
|
|
||||||
|
#define V5_MCACHE_CTL_IC_EN_OFFSET 0
|
||||||
|
#define V5_MCACHE_CTL_DC_EN_OFFSET 1
|
||||||
|
#define V5_MCACHE_CTL_DC_COHEN_OFFSET 19
|
||||||
|
#define V5_MCACHE_CTL_DC_COHSTA_OFFSET 20
|
||||||
|
|
||||||
|
#define V5_MCACHE_CTL_IC_EN BIT(V5_MCACHE_CTL_IC_EN_OFFSET)
|
||||||
|
#define V5_MCACHE_CTL_DC_EN BIT(V5_MCACHE_CTL_DC_EN_OFFSET)
|
||||||
|
#define V5_MCACHE_CTL_DC_COHEN_EN BIT(V5_MCACHE_CTL_DC_COHEN_OFFSET)
|
||||||
|
#define V5_MCACHE_CTL_DC_COHSTA_EN BIT(V5_MCACHE_CTL_DC_COHSTA_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cleanup_before_linux() is called just before we call linux
|
* cleanup_before_linux() is called just before we call linux
|
||||||
@@ -27,3 +43,29 @@ int cleanup_before_linux(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void harts_early_init(void)
|
||||||
|
{
|
||||||
|
if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
|
||||||
|
unsigned long long mcache_ctl_val = csr_read(CSR_MCACHE_CTL);
|
||||||
|
|
||||||
|
if (!(mcache_ctl_val & V5_MCACHE_CTL_DC_COHEN_EN))
|
||||||
|
mcache_ctl_val |= V5_MCACHE_CTL_DC_COHEN_EN;
|
||||||
|
if (!(mcache_ctl_val & V5_MCACHE_CTL_IC_EN))
|
||||||
|
mcache_ctl_val |= V5_MCACHE_CTL_IC_EN;
|
||||||
|
if (!(mcache_ctl_val & V5_MCACHE_CTL_DC_EN))
|
||||||
|
mcache_ctl_val |= V5_MCACHE_CTL_DC_EN;
|
||||||
|
csr_write(CSR_MCACHE_CTL, mcache_ctl_val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check DC_COHEN_EN, if cannot write to mcache_ctl,
|
||||||
|
* we assume this bitmap not support L2 CM
|
||||||
|
*/
|
||||||
|
mcache_ctl_val = csr_read(CSR_MCACHE_CTL);
|
||||||
|
if ((mcache_ctl_val & V5_MCACHE_CTL_DC_COHEN_EN)) {
|
||||||
|
/* Wait for DC_COHSTA bit be set */
|
||||||
|
while (!(mcache_ctl_val & V5_MCACHE_CTL_DC_COHSTA_EN))
|
||||||
|
mcache_ctl_val = csr_read(CSR_MCACHE_CTL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dm/lists.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <log.h>
|
#include <log.h>
|
||||||
#include <asm/encoding.h>
|
#include <asm/encoding.h>
|
||||||
@@ -138,7 +139,17 @@ int arch_cpu_init_dm(void)
|
|||||||
|
|
||||||
int arch_early_init_r(void)
|
int arch_early_init_r(void)
|
||||||
{
|
{
|
||||||
return riscv_cpu_probe();
|
int ret;
|
||||||
|
|
||||||
|
ret = riscv_cpu_probe();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SYSRESET_SBI))
|
||||||
|
device_bind_driver(gd->dm_root, "sbi-sysreset",
|
||||||
|
"sbi-sysreset", NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
enum sbi_ext_id {
|
enum sbi_ext_id {
|
||||||
#ifdef CONFIG_SBI_V01
|
|
||||||
SBI_EXT_0_1_SET_TIMER = 0x0,
|
SBI_EXT_0_1_SET_TIMER = 0x0,
|
||||||
SBI_EXT_0_1_CONSOLE_PUTCHAR = 0x1,
|
SBI_EXT_0_1_CONSOLE_PUTCHAR = 0x1,
|
||||||
SBI_EXT_0_1_CONSOLE_GETCHAR = 0x2,
|
SBI_EXT_0_1_CONSOLE_GETCHAR = 0x2,
|
||||||
@@ -22,11 +21,12 @@ enum sbi_ext_id {
|
|||||||
SBI_EXT_0_1_REMOTE_SFENCE_VMA = 0x6,
|
SBI_EXT_0_1_REMOTE_SFENCE_VMA = 0x6,
|
||||||
SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID = 0x7,
|
SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID = 0x7,
|
||||||
SBI_EXT_0_1_SHUTDOWN = 0x8,
|
SBI_EXT_0_1_SHUTDOWN = 0x8,
|
||||||
#endif
|
|
||||||
SBI_EXT_BASE = 0x10,
|
SBI_EXT_BASE = 0x10,
|
||||||
SBI_EXT_TIME = 0x54494D45,
|
SBI_EXT_TIME = 0x54494D45,
|
||||||
SBI_EXT_IPI = 0x735049,
|
SBI_EXT_IPI = 0x735049,
|
||||||
SBI_EXT_RFENCE = 0x52464E43,
|
SBI_EXT_RFENCE = 0x52464E43,
|
||||||
|
SBI_EXT_HSM = 0x48534D,
|
||||||
|
SBI_EXT_SRST = 0x53525354,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sbi_ext_base_fid {
|
enum sbi_ext_base_fid {
|
||||||
@@ -51,6 +51,41 @@ enum sbi_ext_rfence_fid {
|
|||||||
SBI_EXT_RFENCE_REMOTE_FENCE_I = 0,
|
SBI_EXT_RFENCE_REMOTE_FENCE_I = 0,
|
||||||
SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
|
SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
|
||||||
SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
|
SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
|
||||||
|
SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
|
||||||
|
SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
|
||||||
|
SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
|
||||||
|
SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sbi_ext_hsm_fid {
|
||||||
|
SBI_EXT_HSM_HART_START = 0,
|
||||||
|
SBI_EXT_HSM_HART_STOP,
|
||||||
|
SBI_EXT_HSM_HART_STATUS,
|
||||||
|
SBI_EXT_HSM_HART_SUSPEND,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sbi_hsm_hart_status {
|
||||||
|
SBI_HSM_HART_STATUS_STARTED = 0,
|
||||||
|
SBI_HSM_HART_STATUS_STOPPED,
|
||||||
|
SBI_HSM_HART_STATUS_START_PENDING,
|
||||||
|
SBI_HSM_HART_STATUS_STOP_PENDING,
|
||||||
|
SBI_HSM_HART_STATUS_SUSPEND_PENDING,
|
||||||
|
SBI_HSM_HART_STATUS_RESUME_PENDING,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sbi_ext_srst_fid {
|
||||||
|
SBI_EXT_SRST_RESET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sbi_srst_reset_type {
|
||||||
|
SBI_SRST_RESET_TYPE_SHUTDOWN = 0,
|
||||||
|
SBI_SRST_RESET_TYPE_COLD_REBOOT,
|
||||||
|
SBI_SRST_RESET_TYPE_WARM_REBOOT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sbi_srst_reset_reason {
|
||||||
|
SBI_SRST_RESET_REASON_NONE = 0,
|
||||||
|
SBI_SRST_RESET_REASON_SYS_FAILURE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SBI_V01
|
#ifdef CONFIG_SBI_V01
|
||||||
@@ -118,5 +153,6 @@ void sbi_set_timer(uint64_t stime_value);
|
|||||||
long sbi_get_spec_version(void);
|
long sbi_get_spec_version(void);
|
||||||
int sbi_get_impl_id(void);
|
int sbi_get_impl_id(void);
|
||||||
int sbi_probe_extension(int ext);
|
int sbi_probe_extension(int ext);
|
||||||
|
void sbi_srst_reset(unsigned long type, unsigned long reason);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void *dst)
|
|||||||
fdt_addr_t addr;
|
fdt_addr_t addr;
|
||||||
fdt_size_t size;
|
fdt_size_t size;
|
||||||
int offset, node, err, rmem_offset;
|
int offset, node, err, rmem_offset;
|
||||||
bool nomap = true;
|
|
||||||
char basename[32] = {0};
|
char basename[32] = {0};
|
||||||
int bname_len;
|
int bname_len;
|
||||||
int max_len = sizeof(basename);
|
int max_len = sizeof(basename);
|
||||||
@@ -81,9 +80,7 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void *dst)
|
|||||||
log_err("failed to add reserved memory: %d\n", err);
|
log_err("failed to add reserved memory: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (!fdt_getprop(src, node, "no-map", NULL))
|
if (fdt_getprop(src, node, "no-map", NULL)) {
|
||||||
nomap = false;
|
|
||||||
if (nomap) {
|
|
||||||
rmem_offset = fdt_node_offset_by_phandle(dst, phandle);
|
rmem_offset = fdt_node_offset_by_phandle(dst, phandle);
|
||||||
fdt_setprop_empty(dst, rmem_offset, "no-map");
|
fdt_setprop_empty(dst, rmem_offset, "no-map");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,18 @@ int sbi_probe_extension(int extid)
|
|||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sbi_srst_reset() - invoke system reset extension
|
||||||
|
*
|
||||||
|
* @type: type of reset
|
||||||
|
* @reason: reason for reset
|
||||||
|
*/
|
||||||
|
void sbi_srst_reset(unsigned long type, unsigned long reason)
|
||||||
|
{
|
||||||
|
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SBI_V01
|
#ifdef CONFIG_SBI_V01
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,21 +29,21 @@ static struct sbi_imp implementations[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct sbi_ext extensions[] = {
|
static struct sbi_ext extensions[] = {
|
||||||
{ 0x00000000, "sbi_set_timer" },
|
{ SBI_EXT_0_1_SET_TIMER, "sbi_set_timer" },
|
||||||
{ 0x00000001, "sbi_console_putchar" },
|
{ SBI_EXT_0_1_CONSOLE_PUTCHAR, "sbi_console_putchar" },
|
||||||
{ 0x00000002, "sbi_console_getchar" },
|
{ SBI_EXT_0_1_CONSOLE_GETCHAR, "sbi_console_getchar" },
|
||||||
{ 0x00000003, "sbi_clear_ipi" },
|
{ SBI_EXT_0_1_CLEAR_IPI, "sbi_clear_ipi" },
|
||||||
{ 0x00000004, "sbi_send_ipi" },
|
{ SBI_EXT_0_1_SEND_IPI, "sbi_send_ipi" },
|
||||||
{ 0x00000005, "sbi_remote_fence_i" },
|
{ SBI_EXT_0_1_REMOTE_FENCE_I, "sbi_remote_fence_i" },
|
||||||
{ 0x00000006, "sbi_remote_sfence_vma" },
|
{ SBI_EXT_0_1_REMOTE_SFENCE_VMA, "sbi_remote_sfence_vma" },
|
||||||
{ 0x00000007, "sbi_remote_sfence_vma_asid" },
|
{ SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, "sbi_remote_sfence_vma_asid" },
|
||||||
{ 0x00000008, "sbi_shutdown" },
|
{ SBI_EXT_0_1_SHUTDOWN, "sbi_shutdown" },
|
||||||
{ 0x00000010, "SBI Base Functionality" },
|
{ SBI_EXT_BASE, "SBI Base Functionality" },
|
||||||
{ 0x54494D45, "Timer Extension" },
|
{ SBI_EXT_TIME, "Timer Extension" },
|
||||||
{ 0x00735049, "IPI Extension" },
|
{ SBI_EXT_IPI, "IPI Extension" },
|
||||||
{ 0x52464E43, "RFENCE Extension" },
|
{ SBI_EXT_RFENCE, "RFENCE Extension" },
|
||||||
{ 0x0048534D, "Hart State Management Extension" },
|
{ SBI_EXT_HSM, "Hart State Management Extension" },
|
||||||
{ 0x53525354, "System Reset Extension" },
|
{ SBI_EXT_SRST, "System Reset Extension" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int do_sbi(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_sbi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
|||||||
@@ -684,7 +684,7 @@ ulong env_get_bootm_low(void)
|
|||||||
|
|
||||||
#if defined(CONFIG_SYS_SDRAM_BASE)
|
#if defined(CONFIG_SYS_SDRAM_BASE)
|
||||||
return CONFIG_SYS_SDRAM_BASE;
|
return CONFIG_SYS_SDRAM_BASE;
|
||||||
#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE)
|
#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_RISCV)
|
||||||
return gd->bd->bi_dram[0].start;
|
return gd->bd->bi_dram[0].start;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -15,3 +15,4 @@ CONFIG_CMD_NVEDIT_EFI=y
|
|||||||
CONFIG_OF_PRIOR_STAGE=y
|
CONFIG_OF_PRIOR_STAGE=y
|
||||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||||
CONFIG_DM_MTD=y
|
CONFIG_DM_MTD=y
|
||||||
|
CONFIG_SYSRESET_SBI=y
|
||||||
|
|||||||
@@ -17,3 +17,4 @@ CONFIG_CMD_SBI=y
|
|||||||
CONFIG_OF_PRIOR_STAGE=y
|
CONFIG_OF_PRIOR_STAGE=y
|
||||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||||
CONFIG_DM_MTD=y
|
CONFIG_DM_MTD=y
|
||||||
|
CONFIG_SYSRESET_SBI=y
|
||||||
|
|||||||
@@ -18,3 +18,4 @@ CONFIG_CMD_NVEDIT_EFI=y
|
|||||||
CONFIG_OF_PRIOR_STAGE=y
|
CONFIG_OF_PRIOR_STAGE=y
|
||||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||||
CONFIG_DM_MTD=y
|
CONFIG_DM_MTD=y
|
||||||
|
CONFIG_SYSRESET_SBI=y
|
||||||
|
|||||||
@@ -18,3 +18,4 @@ CONFIG_CMD_SBI=y
|
|||||||
CONFIG_OF_PRIOR_STAGE=y
|
CONFIG_OF_PRIOR_STAGE=y
|
||||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||||
CONFIG_DM_MTD=y
|
CONFIG_DM_MTD=y
|
||||||
|
CONFIG_SYSRESET_SBI=y
|
||||||
|
|||||||
@@ -709,6 +709,10 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in,
|
|||||||
* Whether we swapped r and od while enforcing frequency limits
|
* Whether we swapped r and od while enforcing frequency limits
|
||||||
*/
|
*/
|
||||||
bool swapped = false;
|
bool swapped = false;
|
||||||
|
/*
|
||||||
|
* Whether the intermediate frequencies are out-of-spec
|
||||||
|
*/
|
||||||
|
bool out_of_spec;
|
||||||
u64 last_od = od;
|
u64 last_od = od;
|
||||||
u64 last_r = r;
|
u64 last_r = r;
|
||||||
|
|
||||||
@@ -767,76 +771,95 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in,
|
|||||||
* aren't in spec, try swapping r and od. If everything is
|
* aren't in spec, try swapping r and od. If everything is
|
||||||
* in-spec, calculate the relative error.
|
* in-spec, calculate the relative error.
|
||||||
*/
|
*/
|
||||||
while (true) {
|
again:
|
||||||
|
out_of_spec = false;
|
||||||
|
if (r > max_r) {
|
||||||
|
out_of_spec = true;
|
||||||
|
} else {
|
||||||
/*
|
/*
|
||||||
* Whether the intermediate frequencies are out-of-spec
|
* There is no way to only divide once; we need
|
||||||
|
* to examine the frequency with and without the
|
||||||
|
* effect of od.
|
||||||
*/
|
*/
|
||||||
bool out_of_spec = false;
|
u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
|
||||||
|
|
||||||
if (r > max_r) {
|
if (vco > 1750000000 || vco < 340000000)
|
||||||
out_of_spec = true;
|
out_of_spec = true;
|
||||||
} else {
|
}
|
||||||
/*
|
|
||||||
* There is no way to only divide once; we need
|
|
||||||
* to examine the frequency with and without the
|
|
||||||
* effect of od.
|
|
||||||
*/
|
|
||||||
u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
|
|
||||||
|
|
||||||
if (vco > 1750000000 || vco < 340000000)
|
if (out_of_spec) {
|
||||||
out_of_spec = true;
|
u64 new_r, new_od;
|
||||||
|
|
||||||
|
if (!swapped) {
|
||||||
|
u64 tmp = r;
|
||||||
|
|
||||||
|
r = od;
|
||||||
|
od = tmp;
|
||||||
|
swapped = true;
|
||||||
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_of_spec) {
|
/*
|
||||||
if (!swapped) {
|
* Try looking ahead to see if there are additional
|
||||||
u64 tmp = r;
|
* factors for the same product.
|
||||||
|
*/
|
||||||
|
if (i + 1 < ARRAY_SIZE(factors)) {
|
||||||
|
i++;
|
||||||
|
new_r = UNPACK_R(factors[i]);
|
||||||
|
new_od = UNPACK_OD(factors[i]);
|
||||||
|
if (r * od == new_r * new_od) {
|
||||||
|
r = new_r;
|
||||||
|
od = new_od;
|
||||||
|
swapped = false;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
r = od;
|
/*
|
||||||
od = tmp;
|
* Try looking back to see if there is a worse ratio
|
||||||
swapped = true;
|
* that we could try anyway
|
||||||
continue;
|
*/
|
||||||
} else {
|
while (i > 0) {
|
||||||
/*
|
i--;
|
||||||
* Try looking ahead to see if there are
|
new_r = UNPACK_R(factors[i]);
|
||||||
* additional factors for the same
|
new_od = UNPACK_OD(factors[i]);
|
||||||
* product.
|
/*
|
||||||
*/
|
* Don't loop over factors for the same product
|
||||||
if (i + 1 < ARRAY_SIZE(factors)) {
|
* to avoid getting stuck because of the above
|
||||||
u64 new_r, new_od;
|
* clause
|
||||||
|
*/
|
||||||
i++;
|
if (r * od != new_r * new_od) {
|
||||||
new_r = UNPACK_R(factors[i]);
|
if (new_r * new_od > last_r * last_od) {
|
||||||
new_od = UNPACK_OD(factors[i]);
|
r = new_r;
|
||||||
if (r * od == new_r * new_od) {
|
od = new_od;
|
||||||
r = new_r;
|
swapped = false;
|
||||||
od = new_od;
|
goto again;
|
||||||
swapped = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
i--;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
|
/* We ran out of things to try */
|
||||||
/* The lower 16 bits are spurious */
|
continue;
|
||||||
error = abs((error - BIT(32))) >> 16;
|
}
|
||||||
|
|
||||||
if (error < best_error) {
|
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
|
||||||
best->r = r;
|
/* The lower 16 bits are spurious */
|
||||||
best->f = f;
|
error = abs((error - BIT(32))) >> 16;
|
||||||
best->od = od;
|
|
||||||
best_error = error;
|
if (error < best_error) {
|
||||||
}
|
best->r = r;
|
||||||
break;
|
best->f = f;
|
||||||
|
best->od = od;
|
||||||
|
best_error = error;
|
||||||
}
|
}
|
||||||
} while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
|
} while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
|
||||||
|
|
||||||
|
log_debug("best error %lld\n", best_error);
|
||||||
if (best_error == S64_MAX)
|
if (best_error == S64_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
log_debug("best error %lld\n", best_error);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,9 +872,6 @@ static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
|
|||||||
u32 reg;
|
u32 reg;
|
||||||
ulong calc_rate;
|
ulong calc_rate;
|
||||||
|
|
||||||
if (rate_in < 0)
|
|
||||||
return rate_in;
|
|
||||||
|
|
||||||
err = k210_pll_calc_config(rate, rate_in, &config);
|
err = k210_pll_calc_config(rate, rate_in, &config);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@@ -895,7 +915,7 @@ static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id,
|
|||||||
u64 r, f, od;
|
u64 r, f, od;
|
||||||
u32 reg = readl(priv->base + k210_plls[id].off);
|
u32 reg = readl(priv->base + k210_plls[id].off);
|
||||||
|
|
||||||
if (rate_in < 0 || (reg & K210_PLL_BYPASS))
|
if (reg & K210_PLL_BYPASS)
|
||||||
return rate_in;
|
return rate_in;
|
||||||
|
|
||||||
if (!(reg & K210_PLL_PWRD))
|
if (!(reg & K210_PLL_PWRD))
|
||||||
@@ -1029,6 +1049,8 @@ static ulong do_k210_clk_get_rate(struct k210_clk_priv *priv, int id)
|
|||||||
|
|
||||||
parent = k210_clk_get_parent(priv, id);
|
parent = k210_clk_get_parent(priv, id);
|
||||||
parent_rate = do_k210_clk_get_rate(priv, parent);
|
parent_rate = do_k210_clk_get_rate(priv, parent);
|
||||||
|
if (IS_ERR_VALUE(parent_rate))
|
||||||
|
return parent_rate;
|
||||||
|
|
||||||
if (k210_clks[id].flags & K210_CLKF_PLL)
|
if (k210_clks[id].flags & K210_CLKF_PLL)
|
||||||
return k210_pll_get_rate(priv, k210_clks[id].pll, parent_rate);
|
return k210_pll_get_rate(priv, k210_clks[id].pll, parent_rate);
|
||||||
@@ -1099,6 +1121,8 @@ static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
|
|||||||
|
|
||||||
parent = k210_clk_get_parent(priv, clk->id);
|
parent = k210_clk_get_parent(priv, clk->id);
|
||||||
rate_in = do_k210_clk_get_rate(priv, parent);
|
rate_in = do_k210_clk_get_rate(priv, parent);
|
||||||
|
if (IS_ERR_VALUE(rate_in))
|
||||||
|
return rate_in;
|
||||||
|
|
||||||
log_debug("id=%ld rate=%lu rate_in=%lu\n", clk->id, rate, rate_in);
|
log_debug("id=%ld rate=%lu rate_in=%lu\n", clk->id, rate, rate_in);
|
||||||
|
|
||||||
|
|||||||
@@ -280,6 +280,14 @@ config DEBUG_EFI_CONSOLE
|
|||||||
U-Boot when running on top of EFI (Extensive Firmware Interface).
|
U-Boot when running on top of EFI (Extensive Firmware Interface).
|
||||||
This is a type of BIOS used by PCs.
|
This is a type of BIOS used by PCs.
|
||||||
|
|
||||||
|
config DEBUG_SBI_CONSOLE
|
||||||
|
bool "SBI"
|
||||||
|
depends on SBI_V01
|
||||||
|
help
|
||||||
|
Select this to enable a debug console which calls back to SBI to
|
||||||
|
output to the console. This can be useful for early debugging of
|
||||||
|
U-Boot when running on top of SBI (Supervisor Binary Interface).
|
||||||
|
|
||||||
config DEBUG_UART_S5P
|
config DEBUG_UART_S5P
|
||||||
bool "Samsung S5P"
|
bool "Samsung S5P"
|
||||||
depends on ARCH_EXYNOS || ARCH_S5PC1XX
|
depends on ARCH_EXYNOS || ARCH_S5PC1XX
|
||||||
@@ -442,6 +450,7 @@ endchoice
|
|||||||
config DEBUG_UART_BASE
|
config DEBUG_UART_BASE
|
||||||
hex "Base address of UART"
|
hex "Base address of UART"
|
||||||
depends on DEBUG_UART
|
depends on DEBUG_UART
|
||||||
|
default 0 if DEBUG_SBI_CONSOLE
|
||||||
default 0 if DEBUG_UART_SANDBOX
|
default 0 if DEBUG_UART_SANDBOX
|
||||||
help
|
help
|
||||||
This is the base address of your UART for memory-mapped UARTs.
|
This is the base address of your UART for memory-mapped UARTs.
|
||||||
@@ -452,6 +461,7 @@ config DEBUG_UART_BASE
|
|||||||
config DEBUG_UART_CLOCK
|
config DEBUG_UART_CLOCK
|
||||||
int "UART input clock"
|
int "UART input clock"
|
||||||
depends on DEBUG_UART
|
depends on DEBUG_UART
|
||||||
|
default 0 if DEBUG_SBI_CONSOLE
|
||||||
default 0 if DEBUG_UART_SANDBOX
|
default 0 if DEBUG_UART_SANDBOX
|
||||||
default 0 if DEBUG_MVEBU_A3700_UART
|
default 0 if DEBUG_MVEBU_A3700_UART
|
||||||
help
|
help
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
|
|||||||
obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o
|
obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o
|
||||||
obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
|
obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
|
||||||
obj-$(CONFIG_CORTINA_UART) += serial_cortina.o
|
obj-$(CONFIG_CORTINA_UART) += serial_cortina.o
|
||||||
|
obj-$(CONFIG_DEBUG_SBI_CONSOLE) += serial_sbi.o
|
||||||
obj-$(CONFIG_EFI_APP) += serial_efi.o
|
obj-$(CONFIG_EFI_APP) += serial_efi.o
|
||||||
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
|
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
|
||||||
obj-$(CONFIG_MCFUART) += serial_mcf.o
|
obj-$(CONFIG_MCFUART) += serial_mcf.o
|
||||||
|
|||||||
16
drivers/serial/serial_sbi.c
Normal file
16
drivers/serial/serial_sbi.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
#include <debug_uart.h>
|
||||||
|
#include <asm/sbi.h>
|
||||||
|
|
||||||
|
static inline void _debug_uart_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _debug_uart_putc(int c)
|
||||||
|
{
|
||||||
|
if (CONFIG_IS_ENABLED(RISCV_SMODE))
|
||||||
|
sbi_console_putchar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_UART_FUNCS
|
||||||
@@ -85,6 +85,18 @@ config SYSRESET_PSCI
|
|||||||
Enable PSCI SYSTEM_RESET function call. To use this, PSCI firmware
|
Enable PSCI SYSTEM_RESET function call. To use this, PSCI firmware
|
||||||
must be running on your system.
|
must be running on your system.
|
||||||
|
|
||||||
|
config SYSRESET_SBI
|
||||||
|
bool "Enable support for SBI System Reset"
|
||||||
|
depends on RISCV_SMODE && SBI_V02
|
||||||
|
select SYSRESET_CMD_POWEROFF if CMD_POWEROFF
|
||||||
|
help
|
||||||
|
Enable system reset and poweroff via the SBI system reset extension.
|
||||||
|
The extension was introduced in version 0.3 of the SBI specification.
|
||||||
|
|
||||||
|
If the SBI implementation provides the extension, is board specific.
|
||||||
|
The RISC-V platform specification mandates the extension for rich
|
||||||
|
operating system platforms.
|
||||||
|
|
||||||
config SYSRESET_SOCFPGA
|
config SYSRESET_SOCFPGA
|
||||||
bool "Enable support for Intel SOCFPGA family"
|
bool "Enable support for Intel SOCFPGA family"
|
||||||
depends on ARCH_SOCFPGA && (TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10)
|
depends on ARCH_SOCFPGA && (TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o
|
|||||||
obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
|
obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
|
||||||
obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o
|
obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o
|
||||||
obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
|
obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
|
||||||
|
obj-$(CONFIG_SYSRESET_SBI) += sysreset_sbi.o
|
||||||
obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o
|
obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o
|
||||||
obj-$(CONFIG_SYSRESET_SOCFPGA_SOC64) += sysreset_socfpga_soc64.o
|
obj-$(CONFIG_SYSRESET_SOCFPGA_SOC64) += sysreset_socfpga_soc64.o
|
||||||
obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o
|
obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o
|
||||||
|
|||||||
51
drivers/sysreset/sysreset_sbi.c
Normal file
51
drivers/sysreset/sysreset_sbi.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <log.h>
|
||||||
|
#include <sysreset.h>
|
||||||
|
#include <asm/sbi.h>
|
||||||
|
|
||||||
|
static enum sbi_srst_reset_type reset_type_map[SYSRESET_COUNT] = {
|
||||||
|
[SYSRESET_WARM] = SBI_SRST_RESET_TYPE_WARM_REBOOT,
|
||||||
|
[SYSRESET_COLD] = SBI_SRST_RESET_TYPE_COLD_REBOOT,
|
||||||
|
[SYSRESET_POWER] = SBI_SRST_RESET_TYPE_COLD_REBOOT,
|
||||||
|
[SYSRESET_POWER_OFF] = SBI_SRST_RESET_TYPE_SHUTDOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sbi_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||||
|
{
|
||||||
|
enum sbi_srst_reset_type reset_type;
|
||||||
|
|
||||||
|
reset_type = reset_type_map[type];
|
||||||
|
sbi_srst_reset(reset_type, SBI_SRST_RESET_REASON_NONE);
|
||||||
|
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sbi_sysreset_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
long have_reset;
|
||||||
|
|
||||||
|
have_reset = sbi_probe_extension(SBI_EXT_SRST);
|
||||||
|
if (have_reset)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_warning("SBI has no system reset extension\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sysreset_ops sbi_sysreset_ops = {
|
||||||
|
.request = sbi_sysreset_request,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(sbi_sysreset) = {
|
||||||
|
.name = "sbi-sysreset",
|
||||||
|
.id = UCLASS_SYSRESET,
|
||||||
|
.ops = &sbi_sysreset_ops,
|
||||||
|
.probe = sbi_sysreset_probe,
|
||||||
|
};
|
||||||
@@ -69,27 +69,25 @@ static int dm_test_k210_pll(struct unit_test_state *uts)
|
|||||||
&theirs));
|
&theirs));
|
||||||
ut_asserteq(-EINVAL, k210_pll_calc_config(1500000000, 20000000,
|
ut_asserteq(-EINVAL, k210_pll_calc_config(1500000000, 20000000,
|
||||||
&theirs));
|
&theirs));
|
||||||
|
ut_asserteq(-EINVAL, k210_pll_calc_config(1750000000, 13300000,
|
||||||
|
&theirs));
|
||||||
|
|
||||||
/* Verify we get the same output with brute-force */
|
/* Verify we get the same output with brute-force */
|
||||||
ut_assertok(dm_test_k210_pll_calc_config(390000000, 26000000, &ours));
|
#define compare(rate, rate_in) do { \
|
||||||
ut_assertok(k210_pll_calc_config(390000000, 26000000, &theirs));
|
ut_assertok(dm_test_k210_pll_calc_config(rate, rate_in, &ours)); \
|
||||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
ut_assertok(k210_pll_calc_config(rate, rate_in, &theirs)); \
|
||||||
|
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
ut_assertok(dm_test_k210_pll_calc_config(26000000, 390000000, &ours));
|
compare(390000000, 26000000);
|
||||||
ut_assertok(k210_pll_calc_config(26000000, 390000000, &theirs));
|
compare(26000000, 390000000);
|
||||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
compare(400000000, 26000000);
|
||||||
|
compare(27000000, 26000000);
|
||||||
ut_assertok(dm_test_k210_pll_calc_config(400000000, 26000000, &ours));
|
compare(26000000, 27000000);
|
||||||
ut_assertok(k210_pll_calc_config(400000000, 26000000, &theirs));
|
compare(13300000 * 64, 13300000);
|
||||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
compare(21250000, 21250000 * 70);
|
||||||
|
compare(21250000, 1750000000);
|
||||||
ut_assertok(dm_test_k210_pll_calc_config(27000000, 26000000, &ours));
|
compare(1750000000, 1750000000);
|
||||||
ut_assertok(k210_pll_calc_config(27000000, 26000000, &theirs));
|
|
||||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
|
||||||
|
|
||||||
ut_assertok(dm_test_k210_pll_calc_config(26000000, 27000000, &ours));
|
|
||||||
ut_assertok(k210_pll_calc_config(26000000, 27000000, &theirs));
|
|
||||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user