mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 23:41:23 +01:00

To make the framework suit all Andes CPUs, change all occurrences of andes45 to andes. In addition, we fix some coding style problems and remove an unused macro in andes.h. Signed-off-by: Ben Zong-You Xie <ben717@andestech.com> Reviewed-by: Anup Patel <anup@brainfault.org>
94 lines
2.4 KiB
C
94 lines
2.4 KiB
C
// SPDX-License-Identifier: BSD-2-Clause
|
|
/*
|
|
* andes_pmu.c - Andes PMU device callbacks and platform overrides
|
|
*
|
|
* Copyright (C) 2023 Andes Technology Corporation
|
|
*/
|
|
|
|
#include <andes/andes.h>
|
|
#include <andes/andes_pmu.h>
|
|
#include <sbi/sbi_bitops.h>
|
|
#include <sbi/sbi_error.h>
|
|
#include <sbi/sbi_pmu.h>
|
|
#include <libfdt.h>
|
|
|
|
static void andes_hw_counter_enable_irq(uint32_t ctr_idx)
|
|
{
|
|
unsigned long mip_val;
|
|
|
|
if (ctr_idx >= SBI_PMU_HW_CTR_MAX)
|
|
return;
|
|
|
|
mip_val = csr_read(CSR_MIP);
|
|
if (!(mip_val & MIP_PMOVI))
|
|
csr_clear(CSR_MCOUNTEROVF, BIT(ctr_idx));
|
|
|
|
csr_set(CSR_MCOUNTERINTEN, BIT(ctr_idx));
|
|
}
|
|
|
|
static void andes_hw_counter_disable_irq(uint32_t ctr_idx)
|
|
{
|
|
csr_clear(CSR_MCOUNTERINTEN, BIT(ctr_idx));
|
|
}
|
|
|
|
static void andes_hw_counter_filter_mode(unsigned long flags, int ctr_idx)
|
|
{
|
|
if (flags & SBI_PMU_CFG_FLAG_SET_UINH)
|
|
csr_set(CSR_MCOUNTERMASK_U, BIT(ctr_idx));
|
|
else
|
|
csr_clear(CSR_MCOUNTERMASK_U, BIT(ctr_idx));
|
|
|
|
if (flags & SBI_PMU_CFG_FLAG_SET_SINH)
|
|
csr_set(CSR_MCOUNTERMASK_S, BIT(ctr_idx));
|
|
else
|
|
csr_clear(CSR_MCOUNTERMASK_S, BIT(ctr_idx));
|
|
}
|
|
|
|
static struct sbi_pmu_device andes_pmu = {
|
|
.name = "andes_pmu",
|
|
.hw_counter_enable_irq = andes_hw_counter_enable_irq,
|
|
.hw_counter_disable_irq = andes_hw_counter_disable_irq,
|
|
/*
|
|
* We set delegation of supervisor local interrupts via
|
|
* 18th bit on mslideleg instead of mideleg, so leave
|
|
* hw_counter_irq_bit() callback unimplemented.
|
|
*/
|
|
.hw_counter_irq_bit = NULL,
|
|
.hw_counter_filter_mode = andes_hw_counter_filter_mode
|
|
};
|
|
|
|
int andes_pmu_extensions_init(const struct fdt_match *match,
|
|
struct sbi_hart_features *hfeatures)
|
|
{
|
|
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
|
|
|
|
if (!has_andes_pmu())
|
|
return 0;
|
|
|
|
/*
|
|
* Don't expect both Andes PMU and standard Sscofpmf/Smcntrpmf,
|
|
* are supported as they serve the same purpose.
|
|
*/
|
|
if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCOFPMF) ||
|
|
sbi_hart_has_extension(scratch, SBI_HART_EXT_SMCNTRPMF))
|
|
return SBI_EINVAL;
|
|
sbi_hart_update_extension(scratch, SBI_HART_EXT_XANDESPMU, true);
|
|
|
|
/* Inhibit all HPM counters in M-mode */
|
|
csr_write(CSR_MCOUNTERMASK_M, 0xfffffffd);
|
|
/* Delegate counter overflow interrupt to S-mode */
|
|
csr_write(CSR_MSLIDELEG, MIP_PMOVI);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int andes_pmu_init(const struct fdt_match *match)
|
|
{
|
|
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
|
|
|
|
if (sbi_hart_has_extension(scratch, SBI_HART_EXT_XANDESPMU))
|
|
sbi_pmu_set_device(&andes_pmu);
|
|
|
|
return 0;
|
|
}
|