blob: ca0a7235a7f6751ffeda2463246ad4d04f8002a6 [file]
// Copyright 2023 Google LLC.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/dif/dif_gpio.h"
#include "sw/device/lib/dif/dif_pinmux.h"
#include "sw/device/lib/dif/dif_rv_plic.h"
#include "sw/device/lib/dif/dif_uart.h"
#include "sw/device/lib/runtime/hart.h"
#include "sw/device/lib/runtime/irq.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"
#include "sw/device/lib/testing/test_framework/test_util.h"
static dif_gpio_t gpio;
static dif_pinmux_t pinmux;
static dif_rv_plic_t plic;
static dif_uart_t uart;
// GPIOs 0-7 will be connected to LEDs.
// GPIOs 8-13 will be connected to switches.
// For more details on the port assignments, please consult
// hw/top_matcha/data/pins_nexus.xdc.
static dif_pinmux_index_t leds[] = {
kTopMatchaPinmuxMioOutIoa8, kTopMatchaPinmuxMioOutIob0,
kTopMatchaPinmuxMioOutIob1, kTopMatchaPinmuxMioOutIob2,
kTopMatchaPinmuxMioOutIob3, kTopMatchaPinmuxMioOutIob4,
kTopMatchaPinmuxMioOutIob5, kTopMatchaPinmuxMioOutIob6,
};
static dif_pinmux_index_t switches[] = {
kTopMatchaPinmuxInselIor5, kTopMatchaPinmuxInselIor6,
kTopMatchaPinmuxInselIor7, kTopMatchaPinmuxInselIor10,
kTopMatchaPinmuxInselIor11, kTopMatchaPinmuxInselIor12,
};
OTTF_DEFINE_TEST_CONFIG();
void ottf_external_isr(void) {
dif_rv_plic_irq_id_t interrupt_id;
CHECK_DIF_OK(
dif_rv_plic_irq_claim(&plic, kTopMatchaPlicTargetIbex0, &interrupt_id));
top_matcha_plic_peripheral_t peripheral_id =
top_matcha_plic_interrupt_for_peripheral[interrupt_id];
CHECK(peripheral_id == kTopMatchaPlicPeripheralGpio,
"ISR got an interrupt from a non-GPIO");
dif_gpio_irq_t gpio_num = interrupt_id - kTopMatchaPlicIrqIdGpioGpio0;
CHECK_DIF_OK(dif_gpio_irq_acknowledge(&gpio, gpio_num));
bool gpio_state;
CHECK_DIF_OK(dif_gpio_read(&gpio, gpio_num, &gpio_state));
CHECK_DIF_OK(dif_gpio_write(&gpio, gpio_num - ARRAYSIZE(leds), !gpio_state));
CHECK_DIF_OK(
dif_rv_plic_irq_complete(&plic, kTopMatchaPlicTargetIbex0, interrupt_id));
}
void _ottf_main(void) {
// Initialize the UART to enable logging for non-DV simulation platforms.
if (kDeviceType != kDeviceSimDV) {
init_uart(TOP_MATCHA_UART0_BASE_ADDR, &uart);
}
CHECK_DIF_OK(
dif_gpio_init(mmio_region_from_addr(TOP_MATCHA_GPIO_BASE_ADDR), &gpio));
CHECK_DIF_OK(dif_pinmux_init(
mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
CHECK_DIF_OK(dif_rv_plic_init(
mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
for (size_t i = 0; i < ARRAYSIZE(leds); ++i) {
dif_pinmux_index_t pin = kTopMatchaPinmuxOutselGpioGpio0 + i;
CHECK_DIF_OK(dif_pinmux_output_select(&pinmux, leds[i], pin));
CHECK_DIF_OK(dif_gpio_output_set_enabled(&gpio, i, kDifToggleEnabled));
CHECK_DIF_OK(dif_gpio_write(&gpio, i, false));
}
for (size_t i = ARRAYSIZE(leds); i < ARRAYSIZE(switches) + ARRAYSIZE(leds);
++i) {
dif_pinmux_index_t pin = kTopMatchaPinmuxPeripheralInGpioGpio0 + i;
int switch_index = (i - ARRAYSIZE(leds));
CHECK_DIF_OK(dif_pinmux_input_select(&pinmux, pin, switches[switch_index]));
CHECK_DIF_OK(dif_gpio_output_set_enabled(&gpio, i, kDifToggleDisabled));
CHECK_DIF_OK(dif_gpio_irq_set_trigger(&gpio, 1 << i,
kDifGpioIrqTriggerEdgeRisingFalling));
CHECK_DIF_OK(dif_gpio_irq_set_enabled(&gpio, kDifGpioIrqGpio0 + i,
kDifToggleEnabled));
CHECK_DIF_OK(dif_rv_plic_irq_set_priority(
&plic, kTopMatchaPlicIrqIdGpioGpio0 + i, kDifRvPlicMaxPriority));
CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
&plic, kTopMatchaPlicIrqIdGpioGpio0 + i, kTopMatchaPlicTargetIbex0,
kDifToggleEnabled));
}
for (size_t i = ARRAYSIZE(leds) + ARRAYSIZE(switches); i < 32; ++i) {
dif_pinmux_index_t in_pin = kTopMatchaPinmuxPeripheralInGpioGpio0 + i;
dif_pinmux_index_t out_pin = kTopMatchaPinmuxOutselGpioGpio0 + i;
CHECK_DIF_OK(dif_pinmux_input_select(&pinmux, in_pin,
kTopMatchaPinmuxInselConstantZero));
CHECK_DIF_OK(dif_pinmux_output_select(
&pinmux, kTopMatchaPinmuxOutselConstantHighZ, out_pin));
}
irq_global_ctrl(true);
irq_external_ctrl(true);
int led_a = 6, led_b = 7;
while (true) {
CHECK_DIF_OK(dif_gpio_write(&gpio, led_a, false));
CHECK_DIF_OK(dif_gpio_write(&gpio, led_b, true));
led_a ^= led_b;
led_b ^= led_a;
led_a ^= led_b;
busy_spin_micros(100 * 1000);
}
__builtin_unreachable();
}