- 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: cmd/riscv/
|
||||
F: doc/usage/sbi.rst
|
||||
F: drivers/sysreset/sysreset_sbi.c
|
||||
F: drivers/timer/andes_plmt_timer.c
|
||||
F: drivers/timer/sifive_clint_timer.c
|
||||
F: tools/prelink-riscv.c
|
||||
|
||||
@@ -9,6 +9,22 @@
|
||||
#include <cpu_func.h>
|
||||
#include <irq_func.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
|
||||
@@ -27,3 +43,29 @@ int cleanup_before_linux(void)
|
||||
|
||||
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 <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <dm/lists.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <asm/encoding.h>
|
||||
@@ -138,7 +139,17 @@ int arch_cpu_init_dm(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>
|
||||
|
||||
enum sbi_ext_id {
|
||||
#ifdef CONFIG_SBI_V01
|
||||
SBI_EXT_0_1_SET_TIMER = 0x0,
|
||||
SBI_EXT_0_1_CONSOLE_PUTCHAR = 0x1,
|
||||
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_ASID = 0x7,
|
||||
SBI_EXT_0_1_SHUTDOWN = 0x8,
|
||||
#endif
|
||||
SBI_EXT_BASE = 0x10,
|
||||
SBI_EXT_TIME = 0x54494D45,
|
||||
SBI_EXT_IPI = 0x735049,
|
||||
SBI_EXT_RFENCE = 0x52464E43,
|
||||
SBI_EXT_HSM = 0x48534D,
|
||||
SBI_EXT_SRST = 0x53525354,
|
||||
};
|
||||
|
||||
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_SFENCE_VMA,
|
||||
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
|
||||
@@ -118,5 +153,6 @@ void sbi_set_timer(uint64_t stime_value);
|
||||
long sbi_get_spec_version(void);
|
||||
int sbi_get_impl_id(void);
|
||||
int sbi_probe_extension(int ext);
|
||||
void sbi_srst_reset(unsigned long type, unsigned long reason);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,6 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void *dst)
|
||||
fdt_addr_t addr;
|
||||
fdt_size_t size;
|
||||
int offset, node, err, rmem_offset;
|
||||
bool nomap = true;
|
||||
char basename[32] = {0};
|
||||
int bname_len;
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
if (!fdt_getprop(src, node, "no-map", NULL))
|
||||
nomap = false;
|
||||
if (nomap) {
|
||||
if (fdt_getprop(src, node, "no-map", NULL)) {
|
||||
rmem_offset = fdt_node_offset_by_phandle(dst, phandle);
|
||||
fdt_setprop_empty(dst, rmem_offset, "no-map");
|
||||
}
|
||||
|
||||
@@ -108,6 +108,18 @@ int sbi_probe_extension(int extid)
|
||||
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
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,21 +29,21 @@ static struct sbi_imp implementations[] = {
|
||||
};
|
||||
|
||||
static struct sbi_ext extensions[] = {
|
||||
{ 0x00000000, "sbi_set_timer" },
|
||||
{ 0x00000001, "sbi_console_putchar" },
|
||||
{ 0x00000002, "sbi_console_getchar" },
|
||||
{ 0x00000003, "sbi_clear_ipi" },
|
||||
{ 0x00000004, "sbi_send_ipi" },
|
||||
{ 0x00000005, "sbi_remote_fence_i" },
|
||||
{ 0x00000006, "sbi_remote_sfence_vma" },
|
||||
{ 0x00000007, "sbi_remote_sfence_vma_asid" },
|
||||
{ 0x00000008, "sbi_shutdown" },
|
||||
{ 0x00000010, "SBI Base Functionality" },
|
||||
{ 0x54494D45, "Timer Extension" },
|
||||
{ 0x00735049, "IPI Extension" },
|
||||
{ 0x52464E43, "RFENCE Extension" },
|
||||
{ 0x0048534D, "Hart State Management Extension" },
|
||||
{ 0x53525354, "System Reset Extension" },
|
||||
{ SBI_EXT_0_1_SET_TIMER, "sbi_set_timer" },
|
||||
{ SBI_EXT_0_1_CONSOLE_PUTCHAR, "sbi_console_putchar" },
|
||||
{ SBI_EXT_0_1_CONSOLE_GETCHAR, "sbi_console_getchar" },
|
||||
{ SBI_EXT_0_1_CLEAR_IPI, "sbi_clear_ipi" },
|
||||
{ SBI_EXT_0_1_SEND_IPI, "sbi_send_ipi" },
|
||||
{ SBI_EXT_0_1_REMOTE_FENCE_I, "sbi_remote_fence_i" },
|
||||
{ SBI_EXT_0_1_REMOTE_SFENCE_VMA, "sbi_remote_sfence_vma" },
|
||||
{ SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, "sbi_remote_sfence_vma_asid" },
|
||||
{ SBI_EXT_0_1_SHUTDOWN, "sbi_shutdown" },
|
||||
{ SBI_EXT_BASE, "SBI Base Functionality" },
|
||||
{ SBI_EXT_TIME, "Timer Extension" },
|
||||
{ SBI_EXT_IPI, "IPI Extension" },
|
||||
{ SBI_EXT_RFENCE, "RFENCE Extension" },
|
||||
{ SBI_EXT_HSM, "Hart State Management Extension" },
|
||||
{ SBI_EXT_SRST, "System Reset Extension" },
|
||||
};
|
||||
|
||||
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)
|
||||
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;
|
||||
#else
|
||||
return 0;
|
||||
|
||||
@@ -15,3 +15,4 @@ CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_OF_PRIOR_STAGE=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_DM_MTD=y
|
||||
CONFIG_SYSRESET_SBI=y
|
||||
|
||||
@@ -17,3 +17,4 @@ CONFIG_CMD_SBI=y
|
||||
CONFIG_OF_PRIOR_STAGE=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_DM_MTD=y
|
||||
CONFIG_SYSRESET_SBI=y
|
||||
|
||||
@@ -18,3 +18,4 @@ CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_OF_PRIOR_STAGE=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_DM_MTD=y
|
||||
CONFIG_SYSRESET_SBI=y
|
||||
|
||||
@@ -18,3 +18,4 @@ CONFIG_CMD_SBI=y
|
||||
CONFIG_OF_PRIOR_STAGE=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=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
|
||||
*/
|
||||
bool swapped = false;
|
||||
/*
|
||||
* Whether the intermediate frequencies are out-of-spec
|
||||
*/
|
||||
bool out_of_spec;
|
||||
u64 last_od = od;
|
||||
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
|
||||
* 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;
|
||||
} 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)
|
||||
out_of_spec = true;
|
||||
if (out_of_spec) {
|
||||
u64 new_r, new_od;
|
||||
|
||||
if (!swapped) {
|
||||
u64 tmp = r;
|
||||
|
||||
r = od;
|
||||
od = tmp;
|
||||
swapped = true;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (out_of_spec) {
|
||||
if (!swapped) {
|
||||
u64 tmp = r;
|
||||
/*
|
||||
* Try looking ahead to see if there are additional
|
||||
* 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;
|
||||
swapped = true;
|
||||
continue;
|
||||
} else {
|
||||
/*
|
||||
* Try looking ahead to see if there are
|
||||
* additional factors for the same
|
||||
* product.
|
||||
*/
|
||||
if (i + 1 < ARRAY_SIZE(factors)) {
|
||||
u64 new_r, new_od;
|
||||
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
i--;
|
||||
/*
|
||||
* Try looking back to see if there is a worse ratio
|
||||
* that we could try anyway
|
||||
*/
|
||||
while (i > 0) {
|
||||
i--;
|
||||
new_r = UNPACK_R(factors[i]);
|
||||
new_od = UNPACK_OD(factors[i]);
|
||||
/*
|
||||
* Don't loop over factors for the same product
|
||||
* to avoid getting stuck because of the above
|
||||
* clause
|
||||
*/
|
||||
if (r * od != new_r * new_od) {
|
||||
if (new_r * new_od > last_r * last_od) {
|
||||
r = new_r;
|
||||
od = new_od;
|
||||
swapped = false;
|
||||
goto again;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
|
||||
/* The lower 16 bits are spurious */
|
||||
error = abs((error - BIT(32))) >> 16;
|
||||
/* We ran out of things to try */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error < best_error) {
|
||||
best->r = r;
|
||||
best->f = f;
|
||||
best->od = od;
|
||||
best_error = error;
|
||||
}
|
||||
break;
|
||||
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
|
||||
/* The lower 16 bits are spurious */
|
||||
error = abs((error - BIT(32))) >> 16;
|
||||
|
||||
if (error < best_error) {
|
||||
best->r = r;
|
||||
best->f = f;
|
||||
best->od = od;
|
||||
best_error = error;
|
||||
}
|
||||
} while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
|
||||
|
||||
log_debug("best error %lld\n", best_error);
|
||||
if (best_error == S64_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
log_debug("best error %lld\n", best_error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -849,9 +872,6 @@ static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
|
||||
u32 reg;
|
||||
ulong calc_rate;
|
||||
|
||||
if (rate_in < 0)
|
||||
return rate_in;
|
||||
|
||||
err = k210_pll_calc_config(rate, rate_in, &config);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -895,7 +915,7 @@ static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id,
|
||||
u64 r, f, od;
|
||||
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;
|
||||
|
||||
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_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)
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
@@ -280,6 +280,14 @@ config DEBUG_EFI_CONSOLE
|
||||
U-Boot when running on top of EFI (Extensive Firmware Interface).
|
||||
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
|
||||
bool "Samsung S5P"
|
||||
depends on ARCH_EXYNOS || ARCH_S5PC1XX
|
||||
@@ -442,6 +450,7 @@ endchoice
|
||||
config DEBUG_UART_BASE
|
||||
hex "Base address of UART"
|
||||
depends on DEBUG_UART
|
||||
default 0 if DEBUG_SBI_CONSOLE
|
||||
default 0 if DEBUG_UART_SANDBOX
|
||||
help
|
||||
This is the base address of your UART for memory-mapped UARTs.
|
||||
@@ -452,6 +461,7 @@ config DEBUG_UART_BASE
|
||||
config DEBUG_UART_CLOCK
|
||||
int "UART input clock"
|
||||
depends on DEBUG_UART
|
||||
default 0 if DEBUG_SBI_CONSOLE
|
||||
default 0 if DEBUG_UART_SANDBOX
|
||||
default 0 if DEBUG_MVEBU_A3700_UART
|
||||
help
|
||||
|
||||
@@ -36,6 +36,7 @@ obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
|
||||
obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o
|
||||
obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.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_LPC32XX_HSUART) += lpc32xx_hsuart.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
|
||||
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
|
||||
bool "Enable support for Intel SOCFPGA family"
|
||||
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_OCTEON) += sysreset_octeon.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_SOC64) += sysreset_socfpga_soc64.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));
|
||||
ut_asserteq(-EINVAL, k210_pll_calc_config(1500000000, 20000000,
|
||||
&theirs));
|
||||
ut_asserteq(-EINVAL, k210_pll_calc_config(1750000000, 13300000,
|
||||
&theirs));
|
||||
|
||||
/* Verify we get the same output with brute-force */
|
||||
ut_assertok(dm_test_k210_pll_calc_config(390000000, 26000000, &ours));
|
||||
ut_assertok(k210_pll_calc_config(390000000, 26000000, &theirs));
|
||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
||||
#define compare(rate, rate_in) do { \
|
||||
ut_assertok(dm_test_k210_pll_calc_config(rate, rate_in, &ours)); \
|
||||
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));
|
||||
ut_assertok(k210_pll_calc_config(26000000, 390000000, &theirs));
|
||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
||||
|
||||
ut_assertok(dm_test_k210_pll_calc_config(400000000, 26000000, &ours));
|
||||
ut_assertok(k210_pll_calc_config(400000000, 26000000, &theirs));
|
||||
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
|
||||
|
||||
ut_assertok(dm_test_k210_pll_calc_config(27000000, 26000000, &ours));
|
||||
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));
|
||||
compare(390000000, 26000000);
|
||||
compare(26000000, 390000000);
|
||||
compare(400000000, 26000000);
|
||||
compare(27000000, 26000000);
|
||||
compare(26000000, 27000000);
|
||||
compare(13300000 * 64, 13300000);
|
||||
compare(21250000, 21250000 * 70);
|
||||
compare(21250000, 1750000000);
|
||||
compare(1750000000, 1750000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user