blob: 324382b9d883cbaf95b535641b64d2c4e439221c [file] [log] [blame]
/* Copyright 2019 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#include <metal/machine/platform.h>
#ifdef METAL_SIFIVE_FE310_G000_LFROSC
#include <metal/drivers/sifive_fe310-g000_lfrosc.h>
#include <metal/machine.h>
/* LFROSCCFG */
#define METAL_LFROSCCFG_DIV_MASK 0x3F
#define METAL_LFROSCCFG_TRIM_SHIFT 16
#define METAL_LFROSCCFG_TRIM_MASK (0x1F << METAL_LFROSCCFG_TRIM_SHIFT)
#define METAL_LFROSCCFG_EN (1 << 30)
#define METAL_LFROSCCFG_RDY (1 << 31)
/* LFCLKMUX */
#define METAL_LFCLKMUX_SEL 1
#define METAL_LFCLKMUX_EXT_MUX_STATUS (1 << 31)
#define LFROSC_REGW(addr) (__METAL_ACCESS_ONCE((__metal_io_u32 *)addr))
long __metal_driver_sifive_fe310_g000_lfrosc_get_rate_hz(const struct metal_clock *clock)
{
struct metal_clock *internal_ref = __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(clock);
struct metal_clock *external_ref = __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(clock);
unsigned long int cfg_reg = __metal_driver_sifive_fe310_g000_lfrosc_config_reg(clock);
unsigned long int mux_reg = __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(clock);
if(LFROSC_REGW(mux_reg) & METAL_LFCLKMUX_EXT_MUX_STATUS) {
return metal_clock_get_rate_hz(external_ref);
}
const unsigned long int div = (LFROSC_REGW(cfg_reg) & METAL_LFROSCCFG_DIV_MASK) + 1;
return metal_clock_get_rate_hz(internal_ref) / div;
}
long __metal_driver_sifive_fe310_g000_lfrosc_set_rate_hz(struct metal_clock *clock, long rate)
{
return __metal_driver_sifive_fe310_g000_lfrosc_get_rate_hz(clock);
}
__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_lfrosc) = {
.clock.get_rate_hz = &__metal_driver_sifive_fe310_g000_lfrosc_get_rate_hz,
.clock.set_rate_hz = &__metal_driver_sifive_fe310_g000_lfrosc_set_rate_hz,
};
#endif /* METAL_SIFIVE_FE310_G000_LFROSC */
typedef int no_empty_translation_units;