diff --git a/Makefile.am b/Makefile.am index 6b9d242a..95da2d52 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ nobase_include_HEADERS += \ metal/drivers/sifive_gpio-leds.h \ metal/drivers/sifive_gpio-switches.h \ metal/drivers/sifive_gpio0.h \ + metal/drivers/sifive_gpio2.h \ metal/drivers/sifive_i2c0.h \ metal/drivers/sifive_l2pf0.h \ metal/drivers/sifive_l2pf1.h \ @@ -129,6 +130,7 @@ libmetal_a_SOURCES = \ src/drivers/sifive_gpio-leds.c \ src/drivers/sifive_gpio-switches.c \ src/drivers/sifive_gpio0.c \ + src/drivers/sifive_gpio2.c \ src/drivers/sifive_i2c0.c \ src/drivers/sifive_l2pf0.c \ src/drivers/sifive_l2pf1.c \ diff --git a/Makefile.in b/Makefile.in index 58c623b8..793d2c57 100644 --- a/Makefile.in +++ b/Makefile.in @@ -240,6 +240,7 @@ am_libmetal_a_OBJECTS = src/drivers/fixed-clock.$(OBJEXT) \ src/drivers/sifive_gpio-leds.$(OBJEXT) \ src/drivers/sifive_gpio-switches.$(OBJEXT) \ src/drivers/sifive_gpio0.$(OBJEXT) \ + src/drivers/sifive_gpio2.$(OBJEXT) \ src/drivers/sifive_i2c0.$(OBJEXT) \ src/drivers/sifive_l2pf0.$(OBJEXT) \ src/drivers/sifive_l2pf1.$(OBJEXT) \ @@ -254,18 +255,18 @@ am_libmetal_a_OBJECTS = src/drivers/fixed-clock.$(OBJEXT) \ src/drivers/sifive_uart0.$(OBJEXT) \ src/drivers/sifive_simuart0.$(OBJEXT) \ src/drivers/sifive_wdog0.$(OBJEXT) \ - src/drivers/ucb_htif0.$(OBJEXT) src/atomic.$(OBJEXT) \ - src/button.$(OBJEXT) src/cache.$(OBJEXT) src/clock.$(OBJEXT) \ - src/cpu.$(OBJEXT) src/entry.$(OBJEXT) src/scrub.$(OBJEXT) \ - src/trap.$(OBJEXT) src/gpio.$(OBJEXT) src/hpm.$(OBJEXT) \ - src/i2c.$(OBJEXT) src/init.$(OBJEXT) src/interrupt.$(OBJEXT) \ - src/led.$(OBJEXT) src/lock.$(OBJEXT) src/memory.$(OBJEXT) \ - src/pmp.$(OBJEXT) src/privilege.$(OBJEXT) src/prci.$(OBJEXT) \ - src/pwm.$(OBJEXT) src/rtc.$(OBJEXT) src/shutdown.$(OBJEXT) \ - src/spi.$(OBJEXT) src/switch.$(OBJEXT) src/synchronize_harts.$(OBJEXT) \ - src/timer.$(OBJEXT) src/time.$(OBJEXT) src/trap.$(OBJEXT) \ - src/tty.$(OBJEXT) src/uart.$(OBJEXT) src/vector.$(OBJEXT) \ - src/watchdog.$(OBJEXT) src/remapper.$(OBJEXT) + src/drivers/ucb_htif0.$(OBJEXT) src/remapper.$(OBJEXT) \ + src/atomic.$(OBJEXT) src/button.$(OBJEXT) src/cache.$(OBJEXT) \ + src/clock.$(OBJEXT) src/cpu.$(OBJEXT) src/entry.$(OBJEXT) \ + src/scrub.$(OBJEXT) src/trap.$(OBJEXT) src/gpio.$(OBJEXT) \ + src/hpm.$(OBJEXT) src/i2c.$(OBJEXT) src/init.$(OBJEXT) \ + src/interrupt.$(OBJEXT) src/led.$(OBJEXT) src/lock.$(OBJEXT) \ + src/memory.$(OBJEXT) src/pmp.$(OBJEXT) src/prci.$(OBJEXT) \ + src/privilege.$(OBJEXT) src/pwm.$(OBJEXT) src/rtc.$(OBJEXT) \ + src/shutdown.$(OBJEXT) src/spi.$(OBJEXT) src/switch.$(OBJEXT) \ + src/synchronize_harts.$(OBJEXT) src/timer.$(OBJEXT) \ + src/time.$(OBJEXT) src/trap.$(OBJEXT) src/tty.$(OBJEXT) \ + src/uart.$(OBJEXT) src/vector.$(OBJEXT) src/watchdog.$(OBJEXT) libmetal_a_OBJECTS = $(am_libmetal_a_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -462,8 +463,8 @@ nobase_include_HEADERS = metal/machine.h metal/machine/inline.h \ metal/machine/platform.h metal/drivers/fixed-clock.h \ metal/drivers/fixed-factor-clock.h \ metal/drivers/riscv_clint0.h metal/drivers/riscv_cpu.h \ - metal/drivers/sifive_remapper2.h \ - metal/drivers/riscv_plic0.h metal/drivers/sifive_buserror0.h \ + metal/drivers/riscv_plic0.h metal/drivers/sifive_remapper2.h \ + metal/drivers/sifive_buserror0.h \ metal/drivers/sifive_ccache0.h metal/drivers/sifive_clic0.h \ metal/drivers/sifive_fe310-g000_hfrosc.h \ metal/drivers/sifive_fe310-g000_hfxosc.h \ @@ -474,26 +475,24 @@ nobase_include_HEADERS = metal/machine.h metal/machine/inline.h \ metal/drivers/sifive_gpio-buttons.h \ metal/drivers/sifive_gpio-leds.h \ metal/drivers/sifive_gpio-switches.h \ - metal/drivers/sifive_gpio0.h metal/drivers/sifive_i2c0.h \ - metal/drivers/sifive_l2pf0.h \ + metal/drivers/sifive_gpio0.h metal/drivers/sifive_gpio2.h \ + metal/drivers/sifive_i2c0.h metal/drivers/sifive_l2pf0.h \ metal/drivers/sifive_l2pf1.h \ metal/drivers/sifive_local-external-interrupts0.h \ - metal/drivers/sifive_pl2cache0.h \ - metal/drivers/sifive_prci0.h \ + metal/drivers/sifive_pl2cache0.h metal/drivers/sifive_prci0.h \ metal/drivers/sifive_pwm0.h metal/drivers/sifive_rtc0.h \ metal/drivers/sifive_spi0.h metal/drivers/sifive_test0.h \ metal/drivers/sifive_trace.h metal/drivers/sifive_uart0.h \ metal/drivers/sifive_simuart0.h metal/drivers/sifive_wdog0.h \ - metal/drivers/ucb_htif0.h metal/drivers/sifive_hca1_regs.h \ - metal/atomic.h metal/button.h metal/cache.h metal/clock.h \ - metal/compiler.h metal/cpu.h metal/csr.h metal/gpio.h \ - metal/hpm.h metal/i2c.h metal/init.h \ - metal/interrupt.h metal/io.h metal/itim.h metal/led.h \ - metal/lim.h metal/lock.h metal/memory.h metal/nmi.h metal/pmp.h \ - metal/prci.h metal/privilege.h metal/pwm.h metal/rtc.h \ - metal/shutdown.h metal/scrub.h metal/spi.h metal/switch.h \ - metal/timer.h metal/time.h metal/tty.h metal/uart.h metal/watchdog.h \ - metal/remapper.h + metal/drivers/ucb_htif0.h metal/remapper.h metal/atomic.h \ + metal/button.h metal/cache.h metal/clock.h metal/compiler.h \ + metal/cpu.h metal/csr.h metal/gpio.h metal/hpm.h metal/i2c.h \ + metal/init.h metal/interrupt.h metal/io.h metal/itim.h \ + metal/led.h metal/lim.h metal/lock.h metal/memory.h \ + metal/nmi.h metal/pmp.h metal/prci.h metal/privilege.h \ + metal/pwm.h metal/rtc.h metal/shutdown.h metal/scrub.h \ + metal/spi.h metal/switch.h metal/timer.h metal/time.h \ + metal/tty.h metal/uart.h metal/watchdog.h # This will generate these sources before the compilation step BUILT_SOURCES = \ @@ -527,6 +526,7 @@ libmetal_a_SOURCES = \ src/drivers/sifive_gpio-leds.c \ src/drivers/sifive_gpio-switches.c \ src/drivers/sifive_gpio0.c \ + src/drivers/sifive_gpio2.c \ src/drivers/sifive_i2c0.c \ src/drivers/sifive_l2pf0.c \ src/drivers/sifive_l2pf1.c \ @@ -831,6 +831,8 @@ src/drivers/sifive_gpio-switches.$(OBJEXT): \ src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/sifive_gpio0.$(OBJEXT): src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) +src/drivers/sifive_gpio2.$(OBJEXT): src/drivers/$(am__dirstamp) \ + src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/sifive_i2c0.$(OBJEXT): src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/sifive_l2pf0.$(OBJEXT): src/drivers/$(am__dirstamp) \ @@ -891,6 +893,7 @@ src/lock.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/memory.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/pmp.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/prci.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/privilege.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/pwm.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) @@ -961,7 +964,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@gloss/$(DEPDIR)/sys_wait.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gloss/$(DEPDIR)/sys_write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@segger/$(DEPDIR)/SEGGER_target_metal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/remapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/atomic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/button.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cache.Po@am__quote@ @@ -977,8 +979,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/lock.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/memory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prci.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/privilege.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pwm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/remapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rtc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/scrub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/shutdown.Po@am__quote@ @@ -998,7 +1002,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/riscv_clint0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/riscv_cpu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/riscv_plic0.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_remapper2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_buserror0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_ccache0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_clic0.Po@am__quote@ @@ -1012,6 +1015,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio-leds.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio-switches.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_i2c0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_l2pf0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_l2pf1.Po@am__quote@ @@ -1019,6 +1023,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_pl2cache0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_prci0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_pwm0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_remapper2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_rtc0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_simuart0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_spi0.Po@am__quote@ diff --git a/metal/drivers/sifive_gpio2.h b/metal/drivers/sifive_gpio2.h new file mode 100644 index 00000000..869fcafa --- /dev/null +++ b/metal/drivers/sifive_gpio2.h @@ -0,0 +1,20 @@ +/* Copyright 2021 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_GPI02_H +#define METAL__DRIVERS__SIFIVE_GPI02_H + +#include +#include + +struct __metal_driver_vtable_sifive_gpio2 { + const struct __metal_gpio_vtable gpio; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_gpio2) + +struct __metal_driver_sifive_gpio2 { + struct metal_gpio gpio; +}; + +#endif diff --git a/metal/drivers/sifive_l2pf0.h b/metal/drivers/sifive_l2pf0.h index 63c8e653..6b6923c0 100644 --- a/metal/drivers/sifive_l2pf0.h +++ b/metal/drivers/sifive_l2pf0.h @@ -12,46 +12,94 @@ #include +/** + * Structure type Basic Control Register + */ +typedef union _L2PF0_BCR { + struct { + uint32_t + ScalaLoadSupportEn : 1; /**< bit: 0 - Enable hardware prefetcher */ + uint32_t CrossPageOptmDis : 1; /**< bit: 1 - Only works when CrossPageEn + ===0 */ + uint32_t Dist : 6; /**< bit: 2..7 - Initial prefetch distance */ + uint32_t MaxAllowedDist : 6; /**< bit: 8..13 - Maximum allowed Distance: + 1<< maxAllowedDistance */ + uint32_t LinToExpThrd : 6; /**< bit: 14..19 - Linear to exponential + threshold */ + uint32_t AgeOutEn : 1; /**< bit: 20 - Ageout mechanism enable */ + uint32_t NumLdsToAgeOut : 7; /**< bit: 21..27 - Num of non-matching + loads to edge out an entry */ + uint32_t + CrossPageEn : 1; /**< bit: 28 - Enable prefetches to cross pages */ + uint32_t _reserved0 : 3; /**< (reserved) */ + } b; /**< Structure used for bit access */ + uint32_t w; /**< Structure used for word access */ +} sifive_l2pf0_bcr; + +/* L2PF0 Basic Control Register*/ +#define L2PF0_BCR_SCALALOADSUPPORTEN_Pos 0U +#define L2PF0_BCR_SCALALOADSUPPORTEN_Msk \ + (1U << L2PF0_BCR_SCALALOADSUPPORTEN_Pos) + +#define L2PF0_BCR_CROSSPAGEOPTMDIS_Pos 1U +#define L2PF0_BCR_CROSSPAGEOPTMDIS_Msk (1U << L2PF0_BCR_CROSSPAGEOPTMDIS_Pos) + +#define L2PF0_BCR_DIST_Pos 2U +#define L2PF0_BCR_DIST_Msk (63U << L2PF0_BCR_DIST_Pos) + +#define L2PF0_BCR_MAXALLOWEDDIST_Pos 8U +#define L2PF0_BCR_MAXALLOWEDDIST_Msk (63U << L2PF0_BCR_MAXALLOWEDDIST_Pos) + +#define L2PF0_BCR_LINTOEXPTHRD_Pos 14U +#define L2PF0_BCR_LINTOEXPTHRD_Msk (63U << L2PF0_BCR_LINTOEXPTHRD_Pos) + +#define L2PF0_BCR_AGEOUTEN_Pos 20U +#define L2PF0_BCR_AGEOUTEN_Msk (1U << L2PF0_BCR_AGEOUTEN_Pos) + +#define L2PF0_BCR_NUMLDSTOAGEOUT_Pos 21U +#define L2PF0_BCR_NUMLDSTOAGEOUT_Msk (127U << L2PF0_BCR_NUMLDSTOAGEOUT_Pos) + +#define L2PF0_BCR_CROSSPAGEEN_Pos 28U +#define L2PF0_BCR_CROSSPAGEEN_Msk (1U << L2PF0_BCR_CROSSPAGEEN_Pos) + +/** + * Structure type L2 User Bits Control Register + */ +typedef union _L2PF0_L2UBCR { + struct { + uint32_t QFullnessThrd : 4; /**< bit: 0..3 - Threshold # of Fullness (L2 + MSHRs used/ total available) to stop + sending hits */ + uint32_t HitCacheThrd : 5; /**< bit 4..8 - (1 << hitCacheThrd) of + CacheHits for evicting SPF entry */ + uint32_t HitMSHRThrd : 4; /**> bit 9..12 - Threshold # of MSHR hits for + increasing SPF distance */ + uint32_t Window : 6; /**< bit: 13..18 - Size of the comparison window + for address matching */ + } b; /**< Structure used for bit access */ + uint32_t w; /**< Structure used for word access */ +} sifive_l2pf0_l2ubcr; + +/* L2 User Bits Control Register*/ +#define L2PF0_L2UBCR_QFULLNESTHRD_Pos 0U +#define L2PF0_L2UBCR_QFULLNESSTHRD_Msk (15U << L2PF0_L2UBCR_QFULLNESTHRD_Pos) + +#define L2PF0_L2UBCR_HITCACHETHRD_Pos 4U +#define L2PF0_L2UBCR_HITCACHETHRD_Msk (31U << L2PF0_L2UBCR_HITCACHETHRD_Pos) + +#define L2PF0_L2UBCR_HITMSHRTHRD_Pos 9U +#define L2PF0_L2UBCR_HITMSHRTHRD_Msk (15U << L2PF0_L2UBCR_HITMSHRTHRD_Pos) + +#define L2PF0_L2UBCR_WINDOW_Pos 13U +#define L2PF0_L2UBCR_WINDOW_Msk (63U << L2PF0_L2UBCR_WINDOW_Pos) + /*! @brief L2 prefetcher configuration */ typedef struct { - /* Enable L2 hardware prefetcher */ - uint8_t HwPrefetchEnable; - - /* Only works when CrossPageEn === 0. - Cross Page optimization disable: - 0 -> Entry goes into Pause state while crossing Page boundary. - Next time when the demand miss happens on the same page, it doesn’t need - to train again. 1 -> The entry is invalidated in case of a cross page. */ - uint8_t CrossPageOptmDisable; - - /* Enable prefetches to cross pages */ - uint8_t CrossPageEn; - - /* Age-out mechanism enable */ - uint8_t AgeOutEn; - - uint32_t PrefetchDistance; - - uint32_t MaxAllowedDistance; - - /* Linear to exponential threshold */ - uint32_t LinToExpThreshold; - - /* No. of non-matching loads to edge out an entry */ - uint32_t NumLdsToAgeOut; - - /* Threshold no. of Fullness (L2 MSHRs used/ total available) to stop - * sending hits */ - uint32_t QFullnessThreshold; - - /* Threshold no. of CacheHits for evicting SPF entry */ - uint32_t HitCacheThreshold; - - /* Threshold no. of MSHR hits for increasing SPF distance */ - uint32_t hitMSHRThreshold; + /* Basic Control Register */ + sifive_l2pf0_bcr bcr; - /* Size of the comparison window for address matching */ - uint32_t Window; + /* L2 user Bits Control Register */ + sifive_l2pf0_l2ubcr l2ubcr; } sifive_l2pf0_config; diff --git a/src/drivers/sifive_gpio2.c b/src/drivers/sifive_gpio2.c new file mode 100644 index 00000000..26f315a0 --- /dev/null +++ b/src/drivers/sifive_gpio2.c @@ -0,0 +1,257 @@ +/* Copyright 2021 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_GPIO2 + +#include +#include +#include + +int __metal_driver_sifive_gpio2_enable_input(struct metal_gpio *ggpio, + long source) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_INPUT_EN)) |= source; + + return 0; +} + +int __metal_driver_sifive_gpio2_disable_input(struct metal_gpio *ggpio, + long source) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_INPUT_EN)) &= ~source; + + return 0; +} + +long __metal_driver_sifive_gpio2_input(struct metal_gpio *ggpio) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + return __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_VALUE)); +} + +long __metal_driver_sifive_gpio2_output(struct metal_gpio *ggpio) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + +#if 0 + return __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_PORT)); +#endif + return 0; +} + +int __metal_driver_sifive_gpio2_disable_output(struct metal_gpio *ggpio, + long source) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_OUTPUT_EN)) &= ~source; + + return 0; +} + +int __metal_driver_sifive_gpio2_enable_output(struct metal_gpio *ggpio, + long source) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_OUTPUT_EN)) |= source; + + return 0; +} + +int __metal_driver_sifive_gpio2_output_set(struct metal_gpio *ggpio, + long value) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_OUTPUT_VALUE)) |= value; + + return 0; +} + +int __metal_driver_sifive_gpio2_output_clear(struct metal_gpio *ggpio, + long value) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_OUTPUT_VALUE)) &= ~value; + + return 0; +} + +int __metal_driver_sifive_gpio2_output_toggle(struct metal_gpio *ggpio, + long value) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_OUTPUT_VALUE)) = + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_OUTPUT_VALUE)) ^ + value; + + return 0; +} + +int __metal_driver_sifive_gpio2_enable_io(struct metal_gpio *ggpio, long source, + long dest) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_IOF_EN)) |= + dest; + + return 0; +} + +int __metal_driver_sifive_gpio2_disable_io(struct metal_gpio *ggpio, + long source) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_IOF_EN)) &= + ~source; + + return 0; +} + +int __metal_driver_sifive_gpio2_config_int(struct metal_gpio *ggpio, + long source, int intr_type) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + switch (intr_type) { + case METAL_GPIO_INT_DISABLE: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IE)) &= ~source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IE)) &= ~source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IE)) &= ~source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IE)) &= ~source; + break; + case METAL_GPIO_INT_RISING: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IE)) |= source; + break; + case METAL_GPIO_INT_FALLING: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IE)) |= source; + break; + case METAL_GPIO_INT_BOTH_EDGE: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IE)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IE)) |= source; + break; + case METAL_GPIO_INT_HIGH: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IE)) |= source; + break; + case METAL_GPIO_INT_LOW: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IE)) |= source; + break; + case METAL_GPIO_INT_BOTH_LEVEL: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IE)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IE)) |= source; + break; + case METAL_GPIO_INT_MAX: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IE)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IE)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IE)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IE)) |= source; + break; + } + return 0; +} + +int __metal_driver_sifive_gpio2_clear_int(struct metal_gpio *ggpio, long source, + int intr_type) { + long base = __metal_driver_sifive_gpio2_base(ggpio); + + switch (intr_type) { + case METAL_GPIO_INT_RISING: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IP)) |= source; + break; + case METAL_GPIO_INT_FALLING: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IP)) |= source; + break; + case METAL_GPIO_INT_BOTH_EDGE: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IP)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IP)) |= source; + break; + case METAL_GPIO_INT_HIGH: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IP)) |= source; + break; + case METAL_GPIO_INT_LOW: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IP)) |= source; + break; + case METAL_GPIO_INT_BOTH_LEVEL: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IP)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IP)) |= source; + break; + case METAL_GPIO_INT_MAX: + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_RISE_IP)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_FALL_IP)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_HIGH_IP)) |= source; + __METAL_ACCESS_ONCE( + (__metal_io_u32 *)(base + METAL_SIFIVE_GPIO2_LOW_IP)) |= source; + break; + } + return 0; +} + +struct metal_interrupt * +__metal_driver_gpio_interrupt_controller(struct metal_gpio *gpio) { + return __metal_driver_sifive_gpio2_interrupt_parent(gpio); +} + +int __metal_driver_gpio_get_interrupt_id(struct metal_gpio *gpio, int pin) { + int irq; + irq = __metal_driver_sifive_gpio2_interrupt_lines(gpio, pin); + return irq; +} + +__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_gpio2) = { + .gpio.disable_input = __metal_driver_sifive_gpio2_disable_input, + .gpio.enable_input = __metal_driver_sifive_gpio2_enable_input, + .gpio.input = __metal_driver_sifive_gpio2_input, + .gpio.output = __metal_driver_sifive_gpio2_output, + .gpio.disable_output = __metal_driver_sifive_gpio2_disable_output, + .gpio.enable_output = __metal_driver_sifive_gpio2_enable_output, + .gpio.output_set = __metal_driver_sifive_gpio2_output_set, + .gpio.output_clear = __metal_driver_sifive_gpio2_output_clear, + .gpio.output_toggle = __metal_driver_sifive_gpio2_output_toggle, + .gpio.enable_io = __metal_driver_sifive_gpio2_enable_io, + .gpio.disable_io = __metal_driver_sifive_gpio2_disable_io, + .gpio.config_int = __metal_driver_sifive_gpio2_config_int, + .gpio.clear_int = __metal_driver_sifive_gpio2_clear_int, + .gpio.interrupt_controller = __metal_driver_gpio_interrupt_controller, + .gpio.get_interrupt_id = __metal_driver_gpio_get_interrupt_id, +}; + +#endif /* METAL_SIFIVE_GPIO2 */ + +typedef int no_empty_translation_units;