blob: 82c9052ff88438d1f9e5003bc881aa06d4ccf78d [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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();
}