Compare commits
8 Commits
sg2042-v1.
...
sg2044-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15c8ab7701 | ||
|
|
78f021d248 | ||
|
|
df02b2f353 | ||
|
|
7f6a748be6 | ||
|
|
da2348b161 | ||
|
|
999ec3b2e7 | ||
|
|
e285bad3c3 | ||
|
|
7225632021 |
1
Makefile
1
Makefile
@@ -427,7 +427,6 @@ DTSCPPFLAGS = $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assemble
|
||||
|
||||
ifneq ($(DEBUG),)
|
||||
CFLAGS += -O0
|
||||
ELFFLAGS += -Wl,--print-gc-sections
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
32
include/sbi/sbi_clk.h
Normal file
32
include/sbi/sbi_clk.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_CLK_H__
|
||||
#define __SBI_CLK_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/* clock device */
|
||||
struct sbi_clk_device {
|
||||
char name[32];
|
||||
int (*clk_set_rate)(const char *name, uint64_t rate);
|
||||
uint64_t (*clk_get_rate)(const char *name);
|
||||
int (*clk_enable)(const char *name);
|
||||
int (*clk_disable)(const char *name);
|
||||
};
|
||||
|
||||
int sbi_clk_set_rate(const char *name, uint64_t rate);
|
||||
uint64_t sbi_clk_get_rate(const char *name);
|
||||
int sbi_clk_enable(const char *name);
|
||||
int sbi_clk_disable(const char *name);
|
||||
|
||||
const struct sbi_clk_device *sbi_clk_get_device(const void *fdt);
|
||||
void sbi_clk_set_device(const struct sbi_clk_device *dev);
|
||||
|
||||
#endif
|
||||
26
include/sbi_utils/clk/fdt_clk.h
Normal file
26
include/sbi_utils/clk/fdt_clk.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#ifndef __FDT_CLK_H__
|
||||
#define __FDT_CLK_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi_utils/fdt/fdt_driver.h>
|
||||
|
||||
#ifdef CONFIG_FDT_CLK
|
||||
|
||||
void fdt_clk_init(const void *fdt);
|
||||
|
||||
#else
|
||||
|
||||
static inline void fdt_clk_init(const void *fdt) { }
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
104
include/sbi_utils/clk/sg2044_clk.h
Normal file
104
include/sbi_utils/clk/sg2044_clk.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#ifndef _SG2044_CLK_H_
|
||||
#define _SG2044_CLK_H_
|
||||
|
||||
#include <sbi/sbi_string.h>
|
||||
#include <sbi/sbi_bitops.h>
|
||||
|
||||
#define KHZ 1000UL
|
||||
#define MHZ (KHZ * KHZ)
|
||||
|
||||
#define SG2044_CLK_USE_INIT_VAL BIT(0) /* use default value */
|
||||
#define SG2044_CLK_USE_REG_VAL BIT(1) /* use reg divider value */
|
||||
#define SG2044_CLK_RO BIT(2) /* use reg divider value */
|
||||
|
||||
#define CLK_PLL BIT(0)
|
||||
#define CLK_MUX BIT(1)
|
||||
|
||||
#define PLL_CTRL_OFFSET 0xC4
|
||||
#define PLL_STAT_LOCK_OFFSET 0x10
|
||||
#define PLL_SELECT_OFFSET 0x2020
|
||||
#define CLK_MODE 0x4
|
||||
#define CLK_MODE_MASK 0x3
|
||||
|
||||
#define FBDIV_SHIFT 0
|
||||
#define FBDIV_WIDTH 12
|
||||
#define REFDIV_SHIFT 12
|
||||
#define REFDIV_WIDTH 6
|
||||
#define POSTDIV1_SHIFT 18
|
||||
#define POSTDIV1_WIDTH 3
|
||||
#define POSTDIV2_SHIFT 21
|
||||
#define POSTDIV2_WIDTH 3
|
||||
|
||||
#define REFDIV_MIN 1
|
||||
#define REFDIV_MAX 63
|
||||
#define FBDIV_MIN 8
|
||||
#define FBDIV_MAX 1066
|
||||
|
||||
#define PLL_FREQ_MIN (1600 * MHZ)
|
||||
#define PLL_FREQ_MAX (3200 * MHZ)
|
||||
|
||||
#define div_mask(width) ((1 << (width)) - 1)
|
||||
#define TOP_PLL_CTRL(fbdiv, p1, p2, refdiv) \
|
||||
(BIT(30) | (0x2 << 27) | BIT(24) | (((p2 - 1) & 0x7) << 21) | \
|
||||
(((p1 - 1) & 0x7) << 18) | ((refdiv & 0x3f) << 12) | (fbdiv & 0xfff))
|
||||
|
||||
#define MPLL0_CLK 0
|
||||
#define MPLL1_CLK 1
|
||||
#define MPLL2_CLK 2
|
||||
#define MPLL3_CLK 3
|
||||
#define MPLL4_CLK 4
|
||||
#define MPLL5_CLK 5
|
||||
#define FPLL0_CLK 6
|
||||
#define FPLL1_CLK 7
|
||||
#define DPLL0_CLK 8
|
||||
#define DPLL1_CLK 9
|
||||
#define DPLL2_CLK 10
|
||||
#define DPLL3_CLK 11
|
||||
#define DPLL4_CLK 12
|
||||
#define DPLL5_CLK 13
|
||||
#define DPLL6_CLK 14
|
||||
#define DPLL7_CLK 15
|
||||
|
||||
static inline char is_power_of_2(unsigned long n)
|
||||
{
|
||||
return (n != 0 && ((n & (n - 1)) == 0));
|
||||
}
|
||||
|
||||
#define do_div(n, base) ({ \
|
||||
uint32_t __base = (base); \
|
||||
uint32_t __rem; \
|
||||
__rem = (uint32_t)(n) % __base; \
|
||||
(n) = (uint32_t)(n) / __base; \
|
||||
__rem; \
|
||||
})
|
||||
|
||||
struct sg2044_pll_ctrl {
|
||||
unsigned int mode;
|
||||
unsigned long freq;
|
||||
|
||||
unsigned int fbdiv;
|
||||
unsigned int postdiv1;
|
||||
unsigned int postdiv2;
|
||||
unsigned int refdiv;
|
||||
};
|
||||
|
||||
struct sg2044_pll_clock {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
unsigned int status_offset;
|
||||
unsigned int enable_offset;
|
||||
uint64_t default_rate;
|
||||
|
||||
struct sg2044_pll_ctrl pctrl_table[4];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -99,3 +99,4 @@ libsbi-objs-y += sbi_trap_v_ldst.o
|
||||
libsbi-objs-y += sbi_unpriv.o
|
||||
libsbi-objs-y += sbi_expected_trap.o
|
||||
libsbi-objs-y += sbi_cppc.o
|
||||
libsbi-objs-y += sbi_clk.o
|
||||
|
||||
64
lib/sbi/sbi_clk.c
Normal file
64
lib/sbi/sbi_clk.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#include <sbi/sbi_error.h>
|
||||
#include <sbi/sbi_clk.h>
|
||||
#include <sbi_utils/clk/fdt_clk.h>
|
||||
|
||||
static const struct sbi_clk_device *clk_dev = NULL;
|
||||
|
||||
const struct sbi_clk_device *sbi_clk_get_device(const void *fdt)
|
||||
{
|
||||
if (!clk_dev)
|
||||
fdt_clk_init(fdt);
|
||||
|
||||
return clk_dev ? clk_dev : NULL;
|
||||
}
|
||||
|
||||
void sbi_clk_set_device(const struct sbi_clk_device *dev)
|
||||
{
|
||||
if (!dev || clk_dev)
|
||||
return;
|
||||
|
||||
clk_dev = dev;
|
||||
}
|
||||
|
||||
int sbi_clk_set_rate(const char *name, uint64_t rate)
|
||||
{
|
||||
if (!clk_dev || !clk_dev->clk_set_rate)
|
||||
return SBI_EFAIL;
|
||||
|
||||
clk_dev->clk_set_rate(name, rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t sbi_clk_get_rate(const char *name)
|
||||
{
|
||||
if (!clk_dev || !clk_dev->clk_get_rate)
|
||||
return SBI_EFAIL;
|
||||
|
||||
return clk_dev->clk_get_rate(name);
|
||||
}
|
||||
|
||||
int sbi_clk_enable(const char *name)
|
||||
{
|
||||
if (!clk_dev || !clk_dev->clk_enable)
|
||||
return SBI_EFAIL;
|
||||
|
||||
return clk_dev->clk_enable(name);
|
||||
}
|
||||
|
||||
int sbi_clk_disable(const char *name)
|
||||
{
|
||||
if (!clk_dev || !clk_dev->clk_disable)
|
||||
return SBI_EFAIL;
|
||||
|
||||
return clk_dev->clk_disable(name);
|
||||
}
|
||||
@@ -79,12 +79,15 @@ static void sbi_tlb_local_hfence_gvma(struct sbi_tlb_info *tinfo)
|
||||
|
||||
static void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo)
|
||||
{
|
||||
#ifndef CONFIG_THEAD_C9XX_ERRATA_JTLB
|
||||
unsigned long start = tinfo->start;
|
||||
unsigned long size = tinfo->size;
|
||||
unsigned long i;
|
||||
#endif
|
||||
|
||||
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_SFENCE_VMA_RCVD);
|
||||
|
||||
#ifndef CONFIG_THEAD_C9XX_ERRATA_JTLB
|
||||
if ((start == 0 && size == 0) || (size == SBI_TLB_FLUSH_ALL)) {
|
||||
tlb_flush_all();
|
||||
return;
|
||||
@@ -96,6 +99,10 @@ static void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo)
|
||||
: "r"(start + i)
|
||||
: "memory");
|
||||
}
|
||||
#else
|
||||
tlb_flush_all();
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sbi_tlb_local_hfence_vvma_asid(struct sbi_tlb_info *tinfo)
|
||||
@@ -148,7 +155,9 @@ static void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo)
|
||||
unsigned long start = tinfo->start;
|
||||
unsigned long size = tinfo->size;
|
||||
unsigned long asid = tinfo->asid;
|
||||
#ifndef CONFIG_THEAD_C9XX_ERRATA_JTLB
|
||||
unsigned long i;
|
||||
#endif
|
||||
|
||||
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_SFENCE_VMA_ASID_RCVD);
|
||||
|
||||
@@ -161,12 +170,20 @@ static void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_THEAD_C9XX_ERRATA_JTLB
|
||||
for (i = 0; i < size; i += PAGE_SIZE) {
|
||||
__asm__ __volatile__("sfence.vma %0, %1"
|
||||
:
|
||||
: "r"(start + i), "r"(asid)
|
||||
: "memory");
|
||||
}
|
||||
#else
|
||||
__asm__ __volatile__("sfence.vma x0, %0"
|
||||
:
|
||||
: "r"(asid)
|
||||
: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sbi_tlb_local_fence_i(struct sbi_tlb_info *tinfo)
|
||||
|
||||
@@ -34,4 +34,6 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig"
|
||||
|
||||
source "$(OPENSBI_SRC_DIR)/lib/utils/mpxy/Kconfig"
|
||||
|
||||
source "$(OPENSBI_SRC_DIR)/lib/utils/clk/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
18
lib/utils/clk/Kconfig
Normal file
18
lib/utils/clk/Kconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
menu "Clock Support"
|
||||
|
||||
config FDT_CLK
|
||||
bool "FDT based CLK drivers"
|
||||
depends on FDT
|
||||
default n
|
||||
|
||||
if FDT_CLK
|
||||
|
||||
config FDT_CLK_SG2044
|
||||
bool "SG2044 clock drivers"
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
18
lib/utils/clk/fdt_clk.c
Normal file
18
lib/utils/clk/fdt_clk.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#include <sbi_utils/clk/fdt_clk.h>
|
||||
|
||||
/* List of FDT clock drivers generated at compile time */
|
||||
extern const struct fdt_driver *const fdt_clk_drivers[];
|
||||
|
||||
void fdt_clk_init(const void *fdt)
|
||||
{
|
||||
fdt_driver_init_all(fdt, fdt_clk_drivers);
|
||||
}
|
||||
3
lib/utils/clk/fdt_clk_drivers.carray
Normal file
3
lib/utils/clk/fdt_clk_drivers.carray
Normal file
@@ -0,0 +1,3 @@
|
||||
HEADER: sbi_utils/clk/fdt_clk.h
|
||||
TYPE: const struct fdt_driver
|
||||
NAME: fdt_clk_drivers
|
||||
14
lib/utils/clk/objects.mk
Normal file
14
lib/utils/clk/objects.mk
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (C) 2025 Sophgo Inc
|
||||
#
|
||||
# Authors:
|
||||
# Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
#
|
||||
|
||||
libsbiutils-objs-$(CONFIG_FDT_CLK) += clk/fdt_clk.o
|
||||
libsbiutils-objs-$(CONFIG_FDT_CLK) += clk/fdt_clk_drivers.carray.o
|
||||
|
||||
carray-fdt_clk_drivers-$(CONFIG_FDT_CLK_SG2044) += fdt_clk_sg2044
|
||||
libsbiutils-objs-$(CONFIG_FDT_CLK_SG2044) += clk/sg2044_clk.o
|
||||
553
lib/utils/clk/sg2044_clk.c
Normal file
553
lib/utils/clk/sg2044_clk.c
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <sbi/sbi_error.h>
|
||||
#include <sbi/sbi_string.h>
|
||||
#include <sbi/sbi_console.h>
|
||||
#include <sbi/sbi_timer.h>
|
||||
#include <sbi/sbi_clk.h>
|
||||
#include <sbi/riscv_io.h>
|
||||
#include <sbi_utils/fdt/fdt_driver.h>
|
||||
#include <sbi_utils/clk/sg2044_clk.h>
|
||||
|
||||
#define POSTDIV_RESULT_INDEX 2
|
||||
|
||||
static u64 top_base_addr;
|
||||
|
||||
static int sg2044_pll_mux[][2] = {
|
||||
{MPLL0_CLK, 0}, {MPLL1_CLK, 1}, {MPLL2_CLK, 2}, {MPLL3_CLK, 3},
|
||||
{MPLL4_CLK, 4}, {MPLL5_CLK, 5}, {FPLL1_CLK, 6}, {DPLL0_CLK, 7},
|
||||
{DPLL1_CLK, 8}, {DPLL2_CLK, 9}, {DPLL3_CLK, 10}, {DPLL4_CLK, 11},
|
||||
{DPLL5_CLK, 12}, {DPLL6_CLK, 13}, {DPLL7_CLK, 14}
|
||||
};
|
||||
|
||||
static int postdiv1_2[][3] = {
|
||||
{2, 4, 8}, {3, 3, 9}, {2, 5, 10}, {2, 6, 12},
|
||||
{2, 7, 14}, {3, 5, 15}, {4, 4, 16}, {3, 6, 18},
|
||||
{4, 5, 20}, {3, 7, 21}, {4, 6, 24}, {5, 5, 25},
|
||||
{4, 7, 28}, {5, 6, 30}, {5, 7, 35}, {6, 6, 36},
|
||||
{6, 7, 42}, {7, 7, 49}
|
||||
};
|
||||
|
||||
static inline unsigned long abs_diff(unsigned long a, unsigned long b)
|
||||
{
|
||||
return (a > b) ? (a - b) : (b - a);
|
||||
}
|
||||
|
||||
static struct sg2044_pll_clock sg2044_root_pll_clks[] = {
|
||||
{
|
||||
.id = MPLL0_CLK,
|
||||
.name = "mpll0-clock",
|
||||
.default_rate = 2000 * MHZ,
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = MPLL1_CLK,
|
||||
.name = "mpll1-clock",
|
||||
.default_rate = 2000 * MHZ,
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = MPLL2_CLK,
|
||||
.name = "mpll2-clock",
|
||||
.default_rate = 1000 * MHZ,
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = MPLL3_CLK,
|
||||
.name = "mpll3-clock",
|
||||
.default_rate = 2000 * MHZ,
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = MPLL4_CLK,
|
||||
.name = "mpll4-clock",
|
||||
.default_rate = 1050 * MHZ,
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = MPLL5_CLK,
|
||||
.name = "mpll5-clock",
|
||||
.default_rate = 900 * MHZ,
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = FPLL0_CLK,
|
||||
.name = "fpll0-clock",
|
||||
}, {
|
||||
.id = FPLL1_CLK,
|
||||
.name = "fpll1-clock",
|
||||
}, {
|
||||
.id = DPLL0_CLK,
|
||||
.name = "dpll0-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL1_CLK,
|
||||
.name = "dpll1-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL2_CLK,
|
||||
.name = "dpll2-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL3_CLK,
|
||||
.name = "dpll3-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL4_CLK,
|
||||
.name = "dpll4-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL5_CLK,
|
||||
.name = "dpll5-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL6_CLK,
|
||||
.name = "dpll6-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}, {
|
||||
.id = DPLL7_CLK,
|
||||
.name = "dpll7-clock",
|
||||
.status_offset = 0x98,
|
||||
.enable_offset = 0x9c,
|
||||
}
|
||||
};
|
||||
|
||||
static inline void top_misc_read(uintptr_t offset, uint32_t *value)
|
||||
{
|
||||
*value = readl((const volatile void *)top_base_addr + offset);
|
||||
}
|
||||
|
||||
static inline void top_misc_write(uintptr_t offset, uint32_t value)
|
||||
{
|
||||
writel(value, (volatile void *)(top_base_addr + offset));
|
||||
}
|
||||
|
||||
static void sg2044_pll_write_h(int id, int value)
|
||||
{
|
||||
top_misc_write(PLL_CTRL_OFFSET + (id << 3), value);
|
||||
}
|
||||
|
||||
static void sg2044_pll_read_h(int id, uint32_t *pvalue)
|
||||
{
|
||||
top_misc_read(PLL_CTRL_OFFSET + (id << 3), pvalue);
|
||||
}
|
||||
|
||||
static void sg2044_pll_write_l(int id, int value)
|
||||
{
|
||||
top_misc_write(PLL_CTRL_OFFSET + (id << 3) - 4, value);
|
||||
}
|
||||
|
||||
static void sg2044_pll_read_l(int id, uint32_t *pvalue)
|
||||
{
|
||||
top_misc_read(PLL_CTRL_OFFSET + (id << 3) - 4, pvalue);
|
||||
}
|
||||
|
||||
static int __pll_get_postdiv_1_2(uint64_t rate, uint64_t prate,
|
||||
uint32_t fbdiv, uint32_t refdiv,
|
||||
uint32_t *postdiv1, uint32_t *postdiv2)
|
||||
{
|
||||
int index = 0;
|
||||
int ret = 0;
|
||||
uint64_t tmp0;
|
||||
|
||||
/*
|
||||
* calculate (parent_rate/refdiv)
|
||||
* and result save to tmp0
|
||||
*/
|
||||
tmp0 = prate;
|
||||
do_div(tmp0, refdiv);
|
||||
|
||||
/*
|
||||
* calcuate ((parent_rate/REFDIV) x FBDIV)
|
||||
* and result save to prate
|
||||
*/
|
||||
tmp0 *= fbdiv;
|
||||
|
||||
/*
|
||||
* calcuate (((parent_rate/REFDIV) x FBDIV)/input_rate)
|
||||
* and result save to tmp0
|
||||
* here tmp0 is (POSTDIV1*POSTDIV2)
|
||||
*/
|
||||
do_div(tmp0, rate);
|
||||
|
||||
/* calculate div1 and div2 value */
|
||||
if (tmp0 <= 7) {
|
||||
/* (div1 * div2) <= 7, no need to use array search */
|
||||
*postdiv1 = tmp0;
|
||||
*postdiv2 = 1;
|
||||
} else {
|
||||
/* (div1 * div2) > 7, use array search */
|
||||
for (index = 0; index < array_size(postdiv1_2); index++) {
|
||||
if (tmp0 > postdiv1_2[index][POSTDIV_RESULT_INDEX]) {
|
||||
continue;
|
||||
} else {
|
||||
/* found it */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < array_size(postdiv1_2)) {
|
||||
*postdiv1 = postdiv1_2[index][1];
|
||||
*postdiv2 = postdiv1_2[index][0];
|
||||
} else {
|
||||
sbi_printf("%s out of postdiv array range!\n", __func__);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The function uses the following mapping for frequency range selection:
|
||||
* - 2'd2 (bit[17:16] = 0b10): for frequencies from 1.6 GHz to 2.4 GHz.
|
||||
* - 2'd3 (bit[17:16] = 0b11): for frequencies from 2.4 GHz to 3.2 GHz.
|
||||
*/
|
||||
static void __set_pll_vcosel(struct sg2044_pll_clock *sg2044_pll, uint64_t foutvco)
|
||||
{
|
||||
int vcosel;
|
||||
uint32_t value;
|
||||
|
||||
if (foutvco < (2400 * MHZ))
|
||||
vcosel = 0x2;
|
||||
else
|
||||
vcosel = 0x3;
|
||||
|
||||
sg2044_pll_read_l(sg2044_pll->id, &value);
|
||||
value &= ~(0x3 << 16);
|
||||
value |= (vcosel << 16);
|
||||
sg2044_pll_write_l(sg2044_pll->id, value);
|
||||
}
|
||||
|
||||
static inline int sg2044_pll_id2shift(uint32_t id)
|
||||
{
|
||||
for (int i = 0; i < 15; i++) {
|
||||
if (sg2044_pll_mux[i][0] == id)
|
||||
return sg2044_pll_mux[i][1];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int sg2044_pll_switch_mux(struct sg2044_pll_clock *pll, char en)
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t id = pll->id;
|
||||
int shift;
|
||||
|
||||
shift = sg2044_pll_id2shift(id);
|
||||
if (shift == -1) {
|
||||
sbi_printf("%s Unable to find a suitable shift!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
top_misc_read(PLL_SELECT_OFFSET, &value);
|
||||
if (en)
|
||||
top_misc_write(PLL_SELECT_OFFSET, value & (~(1 << shift)));
|
||||
else
|
||||
top_misc_write(PLL_SELECT_OFFSET, value | (1 << shift));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sg2044_pll_enable(struct sg2044_pll_clock *pll, char en)
|
||||
{
|
||||
uint32_t value;
|
||||
uint64_t wait = 0;
|
||||
uint32_t id = pll->id;
|
||||
|
||||
if (en) {
|
||||
/* wait pll lock */
|
||||
top_misc_read(pll->status_offset, &value);
|
||||
while (!((value >> (PLL_STAT_LOCK_OFFSET + id)) & 0x1)) {
|
||||
top_misc_read(pll->status_offset, &value);
|
||||
wait++;
|
||||
sbi_timer_udelay(10);
|
||||
if (wait > 10000)
|
||||
sbi_printf("%s not locked\n", pll->name);
|
||||
}
|
||||
|
||||
/* wait pll updating */
|
||||
wait = 0;
|
||||
top_misc_read(pll->status_offset, &value);
|
||||
while (((value >> id) & 0x1)) {
|
||||
top_misc_read(pll->status_offset, &value);
|
||||
wait++;
|
||||
sbi_timer_udelay(10);
|
||||
if (wait > 10000)
|
||||
sbi_printf("%s still updating\n", pll->name);
|
||||
}
|
||||
|
||||
/* enable pll */
|
||||
top_misc_read(pll->enable_offset, &value);
|
||||
top_misc_write(pll->enable_offset, value | (1 << id));
|
||||
} else {
|
||||
/* disable pll */
|
||||
top_misc_read(pll->enable_offset, &value);
|
||||
top_misc_write(pll->enable_offset, value & (~(1 << id)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The PLL output frequency calculation is based on the formula:
|
||||
* FOUTPOSTDIV = FREF * FBDIV / REFDIV / (POSTDIV1 + 1) * (POSTDIV2 + 1)
|
||||
* where:
|
||||
* - FREF: Reference Clock Input (12MHz to 1600MHz).
|
||||
* - FOUTPOSTDIV: Output Clock (25MHz to 3200MHz).
|
||||
* - REFDIV: Reference divide value (1 to 63).
|
||||
* - FBDIV: Feedback divide value (8 to 1066).
|
||||
* - POSTDIV1: Post Divide 1 setting (0 to 7).
|
||||
* - POSTDIV2: Post Divide 2 setting (0 to 7).
|
||||
*
|
||||
* Additionally, other check points inside PLL are listed here:
|
||||
* 1.FOUTVCO = FREF * FBDIV / REFDIV (1600MHz to 3200MHz)
|
||||
* - VCOSEL = 2'd2, FOUTVCO 1.6G~2.4G;
|
||||
* - VCOSEL = 2'd3, FOUTVCO 2.4G~3.2G
|
||||
* 2.POSTDIV1 >= POSTDIV2
|
||||
*/
|
||||
static int __get_pll_ctl_setting(struct sg2044_pll_ctrl *best,
|
||||
uint64_t req_rate, uint64_t parent_rate)
|
||||
{
|
||||
int ret;
|
||||
uint32_t fbdiv, refdiv, fref, postdiv1, postdiv2;
|
||||
uint64_t tmp = 0, foutvco;
|
||||
|
||||
fref = parent_rate;
|
||||
|
||||
for (refdiv = REFDIV_MIN; refdiv < REFDIV_MAX + 1; refdiv++) {
|
||||
for (fbdiv = FBDIV_MIN; fbdiv < FBDIV_MAX + 1; fbdiv++) {
|
||||
foutvco = fref * fbdiv / refdiv;
|
||||
/* check fpostdiv pfd */
|
||||
if (foutvco < PLL_FREQ_MIN || foutvco > PLL_FREQ_MAX
|
||||
|| (fref / refdiv) < 10)
|
||||
continue;
|
||||
|
||||
ret = __pll_get_postdiv_1_2(req_rate, fref, fbdiv,
|
||||
refdiv, &postdiv1, &postdiv2);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
tmp = foutvco / (postdiv1 * postdiv2);
|
||||
if (abs_diff(tmp, req_rate) < abs_diff(best->freq, req_rate)) {
|
||||
best->freq = tmp;
|
||||
best->refdiv = refdiv;
|
||||
best->fbdiv = fbdiv;
|
||||
best->postdiv1 = postdiv1;
|
||||
best->postdiv2 = postdiv2;
|
||||
if (tmp == req_rate)
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function performs the following steps:
|
||||
* 1. Switch the PLL source to fpll before modifying settings.
|
||||
* 2. Disable the MPLL to allow safe modifications to its configuration.
|
||||
* 3. Calculate the new PLL settings based on the desired rate and the parent rate.
|
||||
* 5. Set the frequency range based on the foutvco .
|
||||
* 6. Write the new settings to the PLL control register.
|
||||
* 7. Re-enable the PLL.
|
||||
* 8. Switch back the PLL source to mpll after modifications.
|
||||
*/
|
||||
static int sg2044_clk_pll_set_rate(struct sg2044_pll_clock *sg2044_pll,
|
||||
uint64_t rate, uint64_t parent_rate)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t value;
|
||||
uint64_t foutvco;
|
||||
struct sg2044_pll_ctrl pctrl_table;
|
||||
|
||||
sbi_memset(&pctrl_table, 0, sizeof(struct sg2044_pll_ctrl));
|
||||
|
||||
/* switch to fpll before modify mpll */
|
||||
ret = sg2044_pll_switch_mux(sg2044_pll, 1);
|
||||
if (ret == -1) {
|
||||
sbi_printf("switch to fpll fail!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sg2044_pll_enable(sg2044_pll, 0)) {
|
||||
sbi_printf("Can't disable pll(%s), status error\n", sg2044_pll->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg2044_pll_read_h(sg2044_pll->id, &value);
|
||||
__get_pll_ctl_setting(&pctrl_table, rate, parent_rate);
|
||||
if (!pctrl_table.freq) {
|
||||
sbi_printf("%s: Can't find a proper pll setting\n", sg2044_pll->name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = TOP_PLL_CTRL(pctrl_table.fbdiv, pctrl_table.postdiv1,
|
||||
pctrl_table.postdiv2, pctrl_table.refdiv);
|
||||
|
||||
foutvco = parent_rate * pctrl_table.fbdiv / pctrl_table.refdiv;
|
||||
__set_pll_vcosel(sg2044_pll, foutvco);
|
||||
|
||||
/* write the value to top register */
|
||||
sg2044_pll_write_h(sg2044_pll->id, value);
|
||||
sg2044_pll_enable(sg2044_pll, 1);
|
||||
|
||||
/* switch back to mpll after modify mpll */
|
||||
ret = sg2044_pll_switch_mux(sg2044_pll, 0);
|
||||
if (ret == -1) {
|
||||
sbi_printf("switch back to mpll fail!\n");
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint64_t sg2044_clk_pll_get_rate(struct sg2044_pll_clock *sg2044_pll,
|
||||
uint64_t parent_rate)
|
||||
{
|
||||
uint32_t value;
|
||||
uint64_t fref;
|
||||
int refdiv, fbdiv;
|
||||
int postdiv1, postdiv2;
|
||||
|
||||
sg2044_pll_read_h(sg2044_pll->id, &value);
|
||||
fref = parent_rate;
|
||||
fbdiv = (value >> FBDIV_SHIFT) & div_mask(FBDIV_WIDTH);
|
||||
refdiv = (value >> REFDIV_SHIFT) & div_mask(REFDIV_WIDTH);
|
||||
postdiv1 = (value >> POSTDIV1_SHIFT) & div_mask(POSTDIV1_WIDTH);
|
||||
postdiv2 = (value >> POSTDIV2_SHIFT) & div_mask(POSTDIV2_WIDTH);
|
||||
|
||||
return fref * fbdiv / refdiv / (postdiv1 + 1) * (postdiv2 + 1);
|
||||
}
|
||||
|
||||
static struct sg2044_pll_clock *sg2044_get_clk_by_name(const char *name)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < array_size(sg2044_root_pll_clks); index++) {
|
||||
if (!sbi_strcmp(name, sg2044_root_pll_clks[index].name))
|
||||
return &sg2044_root_pll_clks[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sg2044_clk_set_rate(const char *name, uint64_t rate)
|
||||
{
|
||||
int ret;
|
||||
struct sg2044_pll_clock *clk;
|
||||
|
||||
clk = sg2044_get_clk_by_name(name);
|
||||
if (!clk)
|
||||
return SBI_EINVAL;
|
||||
|
||||
ret = sg2044_clk_pll_set_rate(clk, rate, 25 * MHZ);
|
||||
if (ret != 0)
|
||||
sbi_printf("%s set rate fail, ret = %d\n", name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint64_t sg2044_clk_get_rate(const char *name)
|
||||
{
|
||||
struct sg2044_pll_clock *clk;
|
||||
|
||||
clk = sg2044_get_clk_by_name(name);
|
||||
if (!clk)
|
||||
return SBI_EINVAL;
|
||||
|
||||
return sg2044_clk_pll_get_rate(clk, 25 * MHZ);
|
||||
}
|
||||
|
||||
static int sg2044_clk_enable(const char *name)
|
||||
{
|
||||
struct sg2044_pll_clock *clk;
|
||||
|
||||
clk = sg2044_get_clk_by_name(name);
|
||||
if (!clk)
|
||||
return SBI_EINVAL;
|
||||
|
||||
sg2044_pll_enable(clk, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sg2044_clk_disable(const char *name)
|
||||
{
|
||||
struct sg2044_pll_clock *clk;
|
||||
|
||||
clk = sg2044_get_clk_by_name(name);
|
||||
if (!clk)
|
||||
return SBI_EINVAL;
|
||||
|
||||
sg2044_pll_enable(clk, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sbi_clk_device sbi_sg2044_clk = {
|
||||
.name = "sg2044-clk",
|
||||
.clk_set_rate = sg2044_clk_set_rate,
|
||||
.clk_get_rate = sg2044_clk_get_rate,
|
||||
.clk_enable = sg2044_clk_enable,
|
||||
.clk_disable = sg2044_clk_disable,
|
||||
};
|
||||
|
||||
static int sg2044_clk_init(const void *fdt, int nodeoff,
|
||||
const struct fdt_match *match)
|
||||
{
|
||||
int top_offset, len;
|
||||
const fdt32_t *phandle;
|
||||
const fdt32_t *reg;
|
||||
|
||||
if (top_base_addr)
|
||||
return 0;
|
||||
|
||||
phandle = fdt_getprop(fdt, nodeoff, "subctrl-syscon", &len);
|
||||
if (!phandle)
|
||||
return SBI_EINVAL;
|
||||
|
||||
top_offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*phandle));
|
||||
if (top_offset < 0)
|
||||
return top_offset;
|
||||
|
||||
reg = fdt_getprop(fdt, top_offset, "reg", &len);
|
||||
if (!reg || len <= 0)
|
||||
return SBI_EINVAL;
|
||||
|
||||
top_base_addr = fdt32_to_cpu(reg[0]);
|
||||
top_base_addr = (top_base_addr << 32) | fdt32_to_cpu(reg[1]);
|
||||
|
||||
sbi_clk_set_device(&sbi_sg2044_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fdt_match sg2044_clk_match[] = {
|
||||
{ .compatible = "sg2044, pll-clock" },
|
||||
{},
|
||||
};
|
||||
|
||||
struct fdt_driver fdt_clk_sg2044 = {
|
||||
.match_table = sg2044_clk_match,
|
||||
.init = sg2044_clk_init,
|
||||
};
|
||||
@@ -14,6 +14,11 @@ config FDT_CPPC_RPMI
|
||||
depends on FDT_MAILBOX && RPMI_MAILBOX
|
||||
default n
|
||||
|
||||
config FDT_CPPC_SG2044
|
||||
bool "FDT SG2044 CPPC driver"
|
||||
select FDT_CLK_SG2044
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
||||
115
lib/utils/cppc/fdt_cppc_sg2044.c
Normal file
115
lib/utils/cppc/fdt_cppc_sg2044.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Sophgo Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Haijiao Liu <haijiao.liu@sophgo.com>
|
||||
*/
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <sbi/sbi_error.h>
|
||||
#include <sbi/sbi_string.h>
|
||||
#include <sbi/sbi_console.h>
|
||||
#include <sbi/sbi_ecall_interface.h>
|
||||
#include <sbi/sbi_clk.h>
|
||||
#include <sbi/sbi_cppc.h>
|
||||
#include <sbi_utils/cppc/fdt_cppc.h>
|
||||
|
||||
#define CPPC_REGISTER_WIDTH 64
|
||||
#define CPPC_REGISTER_NOT_IMPLEMENTED 0
|
||||
|
||||
static char clock_names[64];
|
||||
static uint64_t clk_granularity;
|
||||
|
||||
static int sg2044_cppc_read(unsigned long reg, u64 *val)
|
||||
{
|
||||
int rc = SBI_SUCCESS;
|
||||
|
||||
switch (reg) {
|
||||
case SBI_CPPC_DESIRED_PERF:
|
||||
*val = sbi_clk_get_rate(clock_names) / clk_granularity;
|
||||
break;
|
||||
default:
|
||||
rc = SBI_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sg2044_cppc_write(unsigned long reg, u64 val)
|
||||
{
|
||||
int rc = SBI_SUCCESS;
|
||||
|
||||
switch (reg) {
|
||||
case SBI_CPPC_DESIRED_PERF:
|
||||
rc = sbi_clk_set_rate(clock_names, val * clk_granularity);
|
||||
break;
|
||||
default:
|
||||
rc = SBI_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sg2044_cppc_probe(unsigned long reg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (reg) {
|
||||
case SBI_CPPC_DESIRED_PERF:
|
||||
rc = CPPC_REGISTER_WIDTH;
|
||||
break;
|
||||
default:
|
||||
rc = CPPC_REGISTER_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct sbi_cppc_device sbi_sg2044_cppc = {
|
||||
.name = "sg2044-cppc",
|
||||
.cppc_read = sg2044_cppc_read,
|
||||
.cppc_write = sg2044_cppc_write,
|
||||
.cppc_probe = sg2044_cppc_probe,
|
||||
};
|
||||
|
||||
static int sg2044_cppc_cold_init(const void *fdt, int nodeoff,
|
||||
const struct fdt_match *match)
|
||||
{
|
||||
const struct sbi_clk_device *clk;
|
||||
const fdt32_t *val;
|
||||
const char *name;
|
||||
int len;
|
||||
|
||||
clk = sbi_clk_get_device(fdt);
|
||||
if (!clk)
|
||||
return SBI_ENODEV;
|
||||
|
||||
val = fdt_getprop(fdt, nodeoff, "step", &len);
|
||||
if (!val)
|
||||
return SBI_EINVAL;
|
||||
|
||||
clk_granularity = fdt32_to_cpu(val[0]);
|
||||
clk_granularity = (clk_granularity << 32) | fdt32_to_cpu(val[1]);
|
||||
|
||||
name = fdt_getprop(fdt, nodeoff, "clock-names", &len);
|
||||
if (!name)
|
||||
return SBI_EINVAL;
|
||||
|
||||
sbi_strncpy(clock_names, name, MIN(sizeof(clock_names), len));
|
||||
|
||||
sbi_cppc_set_device(&sbi_sg2044_cppc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fdt_match sg2044_cppc_match[] = {
|
||||
{ .compatible = "sophgo,sg2044-cppc" },
|
||||
{},
|
||||
};
|
||||
|
||||
struct fdt_driver fdt_cppc_sg2044 = {
|
||||
.match_table = sg2044_cppc_match,
|
||||
.init = sg2044_cppc_cold_init,
|
||||
};
|
||||
@@ -12,3 +12,6 @@ libsbiutils-objs-$(CONFIG_FDT_CPPC) += cppc/fdt_cppc_drivers.carray.o
|
||||
|
||||
carray-fdt_cppc_drivers-$(CONFIG_FDT_CPPC_RPMI) += fdt_cppc_rpmi
|
||||
libsbiutils-objs-$(CONFIG_FDT_CPPC_RPMI) += cppc/fdt_cppc_rpmi.o
|
||||
|
||||
carray-fdt_cppc_drivers-$(CONFIG_FDT_CPPC_SG2044) += fdt_cppc_sg2044
|
||||
libsbiutils-objs-$(CONFIG_FDT_CPPC_SG2044) += cppc/fdt_cppc_sg2044.o
|
||||
|
||||
@@ -56,6 +56,7 @@ static const struct fdt_match ipi_mswi_match[] = {
|
||||
{ .compatible = "riscv,clint0", .data = &clint_offset },
|
||||
{ .compatible = "sifive,clint0", .data = &clint_offset },
|
||||
{ .compatible = "thead,c900-clint", .data = &clint_offset },
|
||||
{ .compatible = "thead,c900-clint-mswi", .data = &clint_offset },
|
||||
{ .compatible = "thead,c900-aclint-mswi" },
|
||||
{ .compatible = "riscv,aclint-mswi" },
|
||||
{ },
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
#include <sbi_utils/reset/fdt_reset.h>
|
||||
#include <sbi_utils/i2c/fdt_i2c.h>
|
||||
|
||||
#define MANGO_BOARD_TYPE_MASK 0x80
|
||||
|
||||
#define REG_BOARD_TYPE 0x00
|
||||
#define REG_CMD 0x03
|
||||
|
||||
#define CMD_POWEROFF 0x02
|
||||
@@ -60,22 +57,6 @@ static struct sbi_system_reset_device sg2042_mcu_reset_device = {
|
||||
.system_reset = sg2042_mcu_reset
|
||||
};
|
||||
|
||||
static int sg2042_mcu_reset_check_board(struct i2c_adapter *adap, uint32_t reg)
|
||||
{
|
||||
static uint8_t val;
|
||||
int ret;
|
||||
|
||||
/* check board type */
|
||||
ret = i2c_adapter_reg_read(adap, reg, REG_BOARD_TYPE, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(val & MANGO_BOARD_TYPE_MASK))
|
||||
return SBI_ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sg2042_mcu_reset_init(const void *fdt, int nodeoff,
|
||||
const struct fdt_match *match)
|
||||
{
|
||||
@@ -96,8 +77,6 @@ static int sg2042_mcu_reset_init(const void *fdt, int nodeoff,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sg2042_mcu_reset_check_board(mcu_adapter, mcu_reg);
|
||||
|
||||
sbi_system_reset_add_device(&sg2042_mcu_reset_device);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -156,6 +156,8 @@ static const struct fdt_match timer_mtimer_match[] = {
|
||||
{ .compatible = "riscv,clint0", .data = &sifive_clint_quirks },
|
||||
{ .compatible = "sifive,clint0", .data = &sifive_clint_quirks },
|
||||
{ .compatible = "thead,c900-clint", .data = &thead_clint_quirks },
|
||||
{ .compatible = "thead,c900-clint-mtimer",
|
||||
.data = &thead_clint_quirks },
|
||||
{ .compatible = "thead,c900-aclint-mtimer",
|
||||
.data = &thead_aclint_quirks },
|
||||
{ .compatible = "riscv,aclint-mtimer" },
|
||||
|
||||
@@ -58,6 +58,13 @@ config PLATFORM_SOPHGO_SG2042
|
||||
select THEAD_C9XX_PMU
|
||||
default n
|
||||
|
||||
config PLATFORM_SOPHGO_SG2044
|
||||
bool "Sophgo sg2044 support"
|
||||
select THEAD_C9XX_ERRATA
|
||||
select THEAD_C9XX_ERRATA_JTLB
|
||||
select THEAD_C9XX_PMU
|
||||
default n
|
||||
|
||||
config PLATFORM_STARFIVE_JH7110
|
||||
bool "StarFive JH7110 support"
|
||||
default n
|
||||
|
||||
@@ -4,10 +4,14 @@ CONFIG_PLATFORM_RENESAS_RZFIVE=y
|
||||
CONFIG_PLATFORM_SIFIVE_FU540=y
|
||||
CONFIG_PLATFORM_SIFIVE_FU740=y
|
||||
CONFIG_PLATFORM_SOPHGO_SG2042=y
|
||||
CONFIG_PLATFORM_SOPHGO_SG2044=y
|
||||
CONFIG_PLATFORM_STARFIVE_JH7110=y
|
||||
CONFIG_PLATFORM_THEAD=y
|
||||
CONFIG_FDT_CPPC=y
|
||||
CONFIG_FDT_CPPC_RPMI=y
|
||||
CONFIG_FDT_CPPC_SG2044=y
|
||||
CONFIG_FDT_CLK=y
|
||||
CONFIG_FDT_CLK_SG2044=y
|
||||
CONFIG_FDT_GPIO=y
|
||||
CONFIG_FDT_GPIO_DESIGNWARE=y
|
||||
CONFIG_FDT_GPIO_SIFIVE=y
|
||||
|
||||
@@ -255,7 +255,7 @@ static int generic_early_init(bool cold_boot)
|
||||
else
|
||||
rc = fdt_serial_init(fdt);
|
||||
if (rc)
|
||||
return rc;
|
||||
return (rc == SBI_ENODEV) ? 0 : rc;
|
||||
|
||||
fdt_cppc_init(fdt);
|
||||
fdt_hsm_init(fdt);
|
||||
|
||||
@@ -7,3 +7,7 @@ config THEAD_C9XX_PMU
|
||||
config THEAD_C9XX_ERRATA
|
||||
bool "T-HEAD c9xx errata support"
|
||||
default n
|
||||
|
||||
config THEAD_C9XX_ERRATA_JTLB
|
||||
bool "T-HEAD c9xx errata(JTLB) support"
|
||||
default n
|
||||
|
||||
@@ -45,21 +45,18 @@ static struct thead_generic_quirks thead_th1520_quirks = {
|
||||
.errata = THEAD_QUIRK_ERRATA_TLB_FLUSH | THEAD_QUIRK_ERRATA_THEAD_PMU,
|
||||
};
|
||||
|
||||
static struct thead_generic_quirks canaan_k230_quirks = {
|
||||
.errata = THEAD_QUIRK_ERRATA_THEAD_PMU,
|
||||
};
|
||||
|
||||
static struct thead_generic_quirks sophgo_cv1800_quirks = {
|
||||
static struct thead_generic_quirks thead_pmu_quirks = {
|
||||
.errata = THEAD_QUIRK_ERRATA_THEAD_PMU,
|
||||
};
|
||||
|
||||
static const struct fdt_match thead_generic_match[] = {
|
||||
{ .compatible = "sophgo,cv1800b", .data = &sophgo_cv1800_quirks },
|
||||
{ .compatible = "sophgo,cv1812h", .data = &sophgo_cv1800_quirks },
|
||||
{ .compatible = "sophgo,sg2000", .data = &sophgo_cv1800_quirks },
|
||||
{ .compatible = "sophgo,sg2002", .data = &sophgo_cv1800_quirks },
|
||||
{ .compatible = "canaan,kendryte-k230", .data = &thead_pmu_quirks },
|
||||
{ .compatible = "sophgo,cv1800b", .data = &thead_pmu_quirks },
|
||||
{ .compatible = "sophgo,cv1812h", .data = &thead_pmu_quirks },
|
||||
{ .compatible = "sophgo,sg2000", .data = &thead_pmu_quirks },
|
||||
{ .compatible = "sophgo,sg2002", .data = &thead_pmu_quirks },
|
||||
{ .compatible = "sophgo,sg2044", .data = &thead_pmu_quirks },
|
||||
{ .compatible = "thead,th1520", .data = &thead_th1520_quirks },
|
||||
{ .compatible = "canaan,kendryte-k230", .data = &canaan_k230_quirks },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user