#ifndef IO_H #define IO_H #include #include #include #include "ioregs.h" #include "picorv32.h" #include "irq.h" #define barrier() do { asm volatile("" : : : "memory"); } while (0) static __always_inline void relax(void) { /* Placeholder for anything that might want to be done while waiting */ } static __always_inline void set_leds(unsigned int leds) { SYS_LED = leds; } static __always_inline void set_led(unsigned int led, bool on) { unsigned int leds = SYS_LED; unsigned int mask = 1 << led; leds &= ~mask; leds |= on ? mask : 0; SYS_LED = leds; } enum leds { LED_SDCARD, LED_DISKIO, LED_ABCBUS }; static __always_inline no_return reset(unsigned int type) { disable_irqs(); for (;;) SYS_RESET = type; } extern const uint32_t time_zero; static __always_inline uint32_t rdtime(void) { uint32_t t; asm volatile("rdtime %0" : "=r" (t)); return t; } static __always_inline uint64_t rdtimeq(void) { uint32_t l, h1, h0; asm volatile("rdtimeh %0; rdtime %1; %rdtimeh %2" : "=r" (h1), "=r" (l), "=r" (h0)); return ((uint64_t)(((int32_t)l < 0) ? h1 : h0) << 32) + l; } static __always_inline void cdelay(uint32_t cycles) { if (!__builtin_constant_p(cycles) || cycles >= 4) { uint32_t start = rdtime(); while (rdtime() - start < cycles) relax(); } } static __always_inline void udelay(uint32_t us) { cdelay(us * (CPU_HZ / 1000000)); } static __always_inline void mdelay(uint32_t ms) { cdelay(ms * (CPU_HZ / 1000)); } static inline void i2c_set_speed(unsigned int khz) { I2C_DIVISOR = ((CPU_HZ/4000)-1)/khz; } static __always_inline void wait_romcopy_done(void) { while (~irqmask() & (1 << ROMCOPY_IRQ)) relax(); barrier(); } /* Read a random 32-bit number */ static inline uint32_t rdrand(void) { waitfor(RANDOM_IRQ); return RANDOM_DATA; } /* Send EOI for some interrupt(s) */ static inline void eoi_mask(uint32_t mask) { SYS_EOI = mask; } static inline void eoi(unsigned int irq) { SYS_EOI = 1 << irq; } #endif /* IO_H */