blob: 087b62cdb1a53a85cd8d524f5932eb7bda8b9900 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* Copyright lowRISC contributors
*
* 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 "sw/device/lib/testing/pinmux_testutils.h"
#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_gpio.h"
#include "sw/device/lib/dif/dif_pinmux.h"
#include "sw/device/lib/runtime/hart.h"
#include "sw/device/lib/testing/test_framework/check.h"
// NB: Keep these definitions aligned with
// hw/top_matcha/rtl/chip_matcha_verilator.sv and
// hw/top_matcha/dv/env/chip_if.sv
const dif_pinmux_index_t kPinmuxTestutilsGpioInselPins[kDifGpioNumPins] = {
kTopMatchaPinmuxInselIoa0, kTopMatchaPinmuxInselIoa1,
kTopMatchaPinmuxInselIoa2, kTopMatchaPinmuxInselIoa3,
kTopMatchaPinmuxInselIoa4, kTopMatchaPinmuxInselIoa5,
kTopMatchaPinmuxInselIoa6, kTopMatchaPinmuxInselIoa7,
kTopMatchaPinmuxInselIoa8, kTopMatchaPinmuxInselIob0,
kTopMatchaPinmuxInselIob1, kTopMatchaPinmuxInselIob2,
kTopMatchaPinmuxInselIob3, kTopMatchaPinmuxInselIob4,
kTopMatchaPinmuxInselIob5, kTopMatchaPinmuxInselIob6,
kTopMatchaPinmuxInselIob7, kTopMatchaPinmuxInselIob8,
kTopMatchaPinmuxInselIob10, kTopMatchaPinmuxInselIob11,
kTopMatchaPinmuxInselIob12, kTopMatchaPinmuxInselIoc6,
kTopMatchaPinmuxInselIoc0, kTopMatchaPinmuxInselIoc1,
kTopMatchaPinmuxInselIoc2, kTopMatchaPinmuxInselIoc7,
kTopMatchaPinmuxInselIoc9, kTopMatchaPinmuxInselIod0,
kTopMatchaPinmuxInselIor6, kTopMatchaPinmuxInselIor7,
kTopMatchaPinmuxInselIod1, kTopMatchaPinmuxInselIor10,
};
const dif_pinmux_index_t kPinmuxTestutilsGpioMioOutPins[kDifGpioNumPins] = {
kTopMatchaPinmuxMioOutIoa0, kTopMatchaPinmuxMioOutIoa1,
kTopMatchaPinmuxMioOutIoa2, kTopMatchaPinmuxMioOutIoa3,
kTopMatchaPinmuxMioOutIoa4, kTopMatchaPinmuxMioOutIoa5,
kTopMatchaPinmuxMioOutIoa6, kTopMatchaPinmuxMioOutIoa7,
kTopMatchaPinmuxMioOutIoa8, kTopMatchaPinmuxMioOutIob0,
kTopMatchaPinmuxMioOutIob1, kTopMatchaPinmuxMioOutIob2,
kTopMatchaPinmuxMioOutIob3, kTopMatchaPinmuxMioOutIob4,
kTopMatchaPinmuxMioOutIob5, kTopMatchaPinmuxMioOutIob6,
kTopMatchaPinmuxMioOutIob7, kTopMatchaPinmuxMioOutIob8,
kTopMatchaPinmuxMioOutIob10, kTopMatchaPinmuxMioOutIob11,
kTopMatchaPinmuxMioOutIob12, kTopMatchaPinmuxMioOutIoc6,
kTopMatchaPinmuxMioOutIoc0, kTopMatchaPinmuxMioOutIoc1,
kTopMatchaPinmuxMioOutIoc2, kTopMatchaPinmuxMioOutIoc7,
kTopMatchaPinmuxMioOutIoc9, kTopMatchaPinmuxMioOutIod0,
kTopMatchaPinmuxMioOutIor6, kTopMatchaPinmuxMioOutIor7,
kTopMatchaPinmuxMioOutIod1, kTopMatchaPinmuxMioOutIor10,
};
void pinmux_testutils_init(dif_pinmux_t *pinmux) {
for (int i = 0; i < kDifGpioNumPins; ++i) {
dif_pinmux_index_t mio = kPinmuxTestutilsGpioInselPins[i];
dif_pinmux_index_t gpio = kTopMatchaPinmuxPeripheralInGpioGpio0 + i;
CHECK_DIF_OK(dif_pinmux_input_select(pinmux, gpio, mio));
}
for (int i = 0; i < kDifGpioNumPins; ++i) {
dif_pinmux_index_t mio = kPinmuxTestutilsGpioMioOutPins[i];
dif_pinmux_index_t gpio = kTopMatchaPinmuxOutselGpioGpio0 + i;
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, mio, gpio));
}
// Configure UART0 RX input to connect to MIO pad IOC3
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInUart0Rx, kTopMatchaPinmuxInselIoc3));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoc3,
kTopMatchaPinmuxOutselConstantHighZ));
// Configure UART0 TX output to connect to MIO pad IOC4
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoc4,
kTopMatchaPinmuxOutselUart0Tx));
// Enable pull-ups on UART0 RX
// Pull-ups are available only on certain platforms.
if (kDeviceType == kDeviceSimDV) {
dif_pinmux_pad_attr_t out_attr;
dif_pinmux_pad_attr_t in_attr = {
.slew_rate = 0,
.drive_strength = 0,
.flags = kDifPinmuxPadAttrPullResistorEnable |
kDifPinmuxPadAttrPullResistorUp};
CHECK_DIF_OK(dif_pinmux_pad_write_attrs(pinmux, kTopMatchaMuxedPadsIoc3,
kDifPinmuxPadKindMio, in_attr,
&out_attr));
CHECK_DIF_OK(dif_pinmux_pad_write_attrs(pinmux, kTopMatchaMuxedPadsIoc10,
kDifPinmuxPadKindMio, in_attr,
&out_attr));
};
// Configure SMC_UART RX input to connect to MIO pad IOC10
CHECK_DIF_OK(dif_pinmux_input_select(pinmux,
kTopMatchaPinmuxPeripheralInSmcUartRx,
kTopMatchaPinmuxInselIoc10));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoc10,
kTopMatchaPinmuxOutselConstantHighZ));
// Configure SMC_UART TX output to connect to MIO pad IOC11
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoc11,
kTopMatchaPinmuxOutselSmcUartTx));
}
uint32_t pinmux_testutils_get_testable_gpios_mask(void) { return 0xffffffff; }
void pinmux_testutils_configure_pads(const dif_pinmux_t *pinmux,
const pinmux_pad_attributes_t *attrs,
size_t num_attrs) {
for (size_t i = 0; i < num_attrs; ++i) {
dif_pinmux_pad_attr_t desired_attr, actual_attr;
CHECK_DIF_OK(dif_pinmux_pad_get_attrs(pinmux, attrs[i].pad, attrs[i].kind,
&desired_attr));
desired_attr.flags = attrs[i].flags;
CHECK_DIF_OK(dif_pinmux_pad_write_attrs(pinmux, attrs[i].pad, attrs[i].kind,
desired_attr, &actual_attr));
}
}
dif_result_t pinmux_testutils_configure_i2s_tx(const dif_pinmux_t *pinmux) {
if (pinmux == NULL) {
return kDifBadArg;
}
// Mux I2S Tx
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIod3,
kTopMatchaPinmuxOutselI2s0TxSclk));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIod4,
kTopMatchaPinmuxOutselI2s0TxWs));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIod5,
kTopMatchaPinmuxOutselI2s0TxSd));
return kDifOk;
}
dif_result_t pinmux_testutils_configure_i2s_rx(const dif_pinmux_t *pinmux) {
if (pinmux == NULL) {
return kDifBadArg;
}
// Mux I2S Rx
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIod0,
kTopMatchaPinmuxOutselI2s0RxSclk));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIod1,
kTopMatchaPinmuxOutselI2s0RxWs));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInI2s0RxSd, kTopMatchaPinmuxInselIod2));
return kDifOk;
}
dif_result_t pinmux_testutils_configure_cam_i2c(const dif_pinmux_t *pinmux) {
if (pinmux == NULL) {
return kDifBadArg;
}
// Mux Cam I2C
CHECK_DIF_OK(dif_pinmux_input_select(pinmux,
kTopMatchaPinmuxPeripheralInCamI2cSda,
kTopMatchaPinmuxInselIoa5));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoa5,
kTopMatchaPinmuxOutselCamI2cSda));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoa4,
kTopMatchaPinmuxOutselCamI2cScl));
CHECK_DIF_OK(dif_pinmux_input_select(pinmux,
kTopMatchaPinmuxPeripheralInCamI2cScl,
kTopMatchaPinmuxInselIoa4));
return kDifOk;
}
dif_result_t pinmux_testutils_configure_isp_wrapper(
const dif_pinmux_t *pinmux) {
if (pinmux == NULL) {
return kDifBadArg;
}
// Mux ISP wrapper
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData0,
kTopMatchaPinmuxInselIob0));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData1,
kTopMatchaPinmuxInselIob1));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData2,
kTopMatchaPinmuxInselIob2));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData3,
kTopMatchaPinmuxInselIob3));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData4,
kTopMatchaPinmuxInselIob4));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData5,
kTopMatchaPinmuxInselIob5));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData6,
kTopMatchaPinmuxInselIob6));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSData7,
kTopMatchaPinmuxInselIob7));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSVsync,
kTopMatchaPinmuxInselIoa2));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSHsync,
kTopMatchaPinmuxInselIoa3));
CHECK_DIF_OK(dif_pinmux_input_select(
pinmux, kTopMatchaPinmuxPeripheralInIspWrapperSPclk,
kTopMatchaPinmuxInselIob8));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoa2,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoa3,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob0,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob1,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob2,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob3,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob4,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob5,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob6,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob7,
kTopMatchaPinmuxOutselConstantHighZ));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIob8,
kTopMatchaPinmuxOutselConstantHighZ));
return kDifOk;
}
dif_result_t pinmux_testutils_configure_cam_ctrl(const dif_pinmux_t *pinmux) {
if (pinmux == NULL) {
return kDifBadArg;
}
// Mux cam CTRL / TRIG
CHECK_DIF_OK(
dif_pinmux_input_select(pinmux, kTopMatchaPinmuxPeripheralInCamCtrlCamInt,
kTopMatchaPinmuxInselIoa6));
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoa7,
kTopMatchaPinmuxOutselCamCtrlCamTrig));
return kDifOk;
}