Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion arch/riscv/include/asm/timex.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,26 @@ typedef unsigned long cycles_t;
#ifdef CONFIG_64BIT
static inline cycles_t get_cycles(void)
{
if (riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR))
return csr_read(CSR_TIME);

return readq_relaxed(clint_time_val);
}
#else /* !CONFIG_64BIT */
static inline u32 get_cycles(void)
{
if (riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR))
return csr_read(CSR_TIME);

return readl_relaxed(((u32 *)clint_time_val));
}
#define get_cycles get_cycles

static inline u32 get_cycles_hi(void)
{
if (riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR))
return csr_read(CSR_TIMEH);

return readl_relaxed(((u32 *)clint_time_val) + 1);
}
#define get_cycles_hi get_cycles_hi
Expand All @@ -40,7 +49,8 @@ static inline u32 get_cycles_hi(void)
*/
static inline unsigned long random_get_entropy(void)
{
if (unlikely(clint_time_val == NULL))
if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR) &&
(unlikely(clint_time_val == NULL)))
return random_get_entropy_fallback();
return get_cycles();
}
Expand Down
82 changes: 78 additions & 4 deletions drivers/clocksource/timer-clint.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static u64 __iomem *clint_timer_cmp;
static u64 __iomem *clint_timer_val;
static unsigned long clint_timer_freq;
static unsigned int clint_timer_irq;
static bool is_c900_clint;

#ifdef CONFIG_RISCV_M_MODE
u64 __iomem *clint_time_val;
Expand Down Expand Up @@ -81,6 +82,12 @@ static u64 notrace clint_get_cycles64(void)
{
return clint_get_cycles();
}

static u64 notrace csr_get_cycles64(void)
{
return csr_read(CSR_TIME);
}

#else /* CONFIG_64BIT */
static u64 notrace clint_get_cycles64(void)
{
Expand All @@ -93,8 +100,26 @@ static u64 notrace clint_get_cycles64(void)

return ((u64)hi << 32) | lo;
}

static u64 notrace csr_get_cycles64(void)
{
u32 hi, lo;

do {
hi = csr_read(CSR_TIMEH);
lo = csr_read(CSR_TIME);
} while (hi != csr_read(CSR_TIMEH));

return ((u64)hi << 32) | lo;
}

#endif /* CONFIG_64BIT */

static u64 csr_rdtime(struct clocksource *cs)
{
return csr_get_cycles64();
}

static u64 clint_rdtime(struct clocksource *cs)
{
return clint_get_cycles64();
Expand All @@ -105,9 +130,20 @@ static struct clocksource clint_clocksource = {
.rating = 300,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.read = clint_rdtime,
.read = csr_rdtime,
};

static int csr_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
void __iomem *r = clint_timer_cmp +
cpuid_to_hartid_map(smp_processor_id());

csr_set(CSR_IE, IE_TIE);
writeq_relaxed(csr_get_cycles64() + delta, r);
return 0;
}

static int clint_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
Expand All @@ -119,17 +155,36 @@ static int clint_clock_next_event(unsigned long delta,
return 0;
}

static int c900_clint_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
void __iomem *r = clint_timer_cmp +
cpuid_to_hartid_map(smp_processor_id());
u64 val = csr_get_cycles64() + delta;

csr_set(CSR_IE, IE_TIE);
writel_relaxed(val, r);
writel_relaxed(val >> 32, r + 4);
return 0;
}

static DEFINE_PER_CPU(struct clock_event_device, clint_clock_event) = {
.name = "clint_clockevent",
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 100,
.set_next_event = clint_clock_next_event,
.set_next_event = csr_clock_next_event,
};

static int clint_timer_starting_cpu(unsigned int cpu)
{
struct clock_event_device *ce = per_cpu_ptr(&clint_clock_event, cpu);

if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR))
ce->set_next_event = clint_clock_next_event;

if (is_c900_clint)
ce->set_next_event = c900_clint_clock_next_event;

ce->cpumask = cpumask_of(cpu);
clockevents_config_and_register(ce, clint_timer_freq, 100, ULONG_MAX);

Expand Down Expand Up @@ -161,7 +216,7 @@ static irqreturn_t clint_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}

static int __init clint_timer_init_dt(struct device_node *np)
static int __init clint_timer_init(struct device_node *np)
{
int rc;
u32 i, nr_irqs;
Expand Down Expand Up @@ -227,13 +282,19 @@ static int __init clint_timer_init_dt(struct device_node *np)

pr_info("%pOFP: timer running at %ld Hz\n", np, clint_timer_freq);

if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR))
clint_clocksource.read = clint_rdtime;

rc = clocksource_register_hz(&clint_clocksource, clint_timer_freq);
if (rc) {
pr_err("%pOFP: clocksource register failed [%d]\n", np, rc);
goto fail_iounmap;
}

sched_clock_register(clint_get_cycles64, 64, clint_timer_freq);
if (riscv_has_extension_likely(RISCV_ISA_EXT_ZICNTR))
sched_clock_register(csr_get_cycles64, 64, clint_timer_freq);
else
sched_clock_register(clint_get_cycles64, 64, clint_timer_freq);

rc = request_percpu_irq(clint_timer_irq, clint_timer_interrupt,
"clint-timer", &clint_clock_event);
Expand Down Expand Up @@ -273,5 +334,18 @@ static int __init clint_timer_init_dt(struct device_node *np)
return rc;
}

static int __init clint_timer_init_dt(struct device_node *np)
{
is_c900_clint = false;
return clint_timer_init(np);
}

static int __init c900_clint_timer_init_dt(struct device_node *np)
{
is_c900_clint = true;
return clint_timer_init(np);
}

TIMER_OF_DECLARE(clint_timer, "riscv,clint0", clint_timer_init_dt);
TIMER_OF_DECLARE(clint_timer1, "sifive,clint0", clint_timer_init_dt);
TIMER_OF_DECLARE(clint_timer2, "thead,c900-clint", c900_clint_timer_init_dt);
Loading