blob: 7a152053c80d94dff60e80090845260a0a5a7322 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/silicon_creator/lib/drivers/pinmux.h"
#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/hardened.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/silicon_creator/lib/base/chip.h"
#include "sw/device/silicon_creator/lib/drivers/otp.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "otp_ctrl_regs.h"
#include "pinmux_regs.h"
enum {
/**
* Base address of the pinmux registers.
*/
kBase = TOP_EARLGREY_PINMUX_AON_BASE_ADDR,
};
/**
* A peripheral input and MIO pad to link it to.
*/
typedef struct pinmux_input {
top_earlgrey_pinmux_peripheral_in_t periph;
top_earlgrey_pinmux_insel_t insel;
top_earlgrey_muxed_pads_t pad;
} pinmux_input_t;
/**
* An MIO pad and a peripheral output to link it to.
*/
typedef struct pinmux_output {
top_earlgrey_pinmux_mio_out_t mio;
top_earlgrey_pinmux_outsel_t outsel;
top_earlgrey_muxed_pads_t pad;
} pinmux_output_t;
/**
* UART RX pin.
*/
static const pinmux_input_t kInputUart0 = {
.periph = kTopEarlgreyPinmuxPeripheralInUart0Rx,
.insel = kTopEarlgreyPinmuxInselIoc3,
.pad = kTopEarlgreyMuxedPadsIoc3,
};
/**
* UART TX pin.
*/
static const pinmux_output_t kOutputUart0 = {
.mio = kTopEarlgreyPinmuxMioOutIoc4,
.outsel = kTopEarlgreyPinmuxOutselUart0Tx,
.pad = kTopEarlgreyMuxedPadsIoc4,
};
/**
* SW strap pins.
*/
#define PINMUX_ASSERT_EQ_(a, b) \
static_assert((a) == (b), "Unexpected software strap configuration.")
PINMUX_ASSERT_EQ_(SW_STRAP_0_PERIPH, kTopEarlgreyPinmuxPeripheralInGpioGpio22);
PINMUX_ASSERT_EQ_(SW_STRAP_0_INSEL, kTopEarlgreyPinmuxInselIoc0);
PINMUX_ASSERT_EQ_(SW_STRAP_0_PAD, kTopEarlgreyMuxedPadsIoc0);
static const pinmux_input_t kInputSwStrap0 = {
.periph = SW_STRAP_0_PERIPH,
.insel = SW_STRAP_0_INSEL,
.pad = SW_STRAP_0_PAD,
};
PINMUX_ASSERT_EQ_(SW_STRAP_1_PERIPH, kTopEarlgreyPinmuxPeripheralInGpioGpio23);
PINMUX_ASSERT_EQ_(SW_STRAP_1_INSEL, kTopEarlgreyPinmuxInselIoc1);
PINMUX_ASSERT_EQ_(SW_STRAP_1_PAD, kTopEarlgreyMuxedPadsIoc1);
static const pinmux_input_t kInputSwStrap1 = {
.periph = SW_STRAP_1_PERIPH,
.insel = SW_STRAP_1_INSEL,
.pad = SW_STRAP_1_PAD,
};
PINMUX_ASSERT_EQ_(SW_STRAP_2_PERIPH, kTopEarlgreyPinmuxPeripheralInGpioGpio24);
PINMUX_ASSERT_EQ_(SW_STRAP_2_INSEL, kTopEarlgreyPinmuxInselIoc2);
PINMUX_ASSERT_EQ_(SW_STRAP_2_PAD, kTopEarlgreyMuxedPadsIoc2);
static const pinmux_input_t kInputSwStrap2 = {
.periph = SW_STRAP_2_PERIPH,
.insel = SW_STRAP_2_INSEL,
.pad = SW_STRAP_2_PAD,
};
/**
* Sets the input pad for the specified peripheral input.
*
* @param input A peripheral input and MIO pad to link it to.
*/
static void configure_input(pinmux_input_t input) {
abs_mmio_write32(kBase + PINMUX_MIO_PERIPH_INSEL_0_REG_OFFSET +
input.periph * sizeof(uint32_t),
input.insel);
}
/**
* Enables pull-down for the specified pad.
*
* @param pad A MIO pad.
*/
static void enable_pull_down(top_earlgrey_muxed_pads_t pad) {
uint32_t reg =
bitfield_bit32_write(0, PINMUX_MIO_PAD_ATTR_0_PULL_EN_0_BIT, true);
abs_mmio_write32(
kBase + PINMUX_MIO_PAD_ATTR_0_REG_OFFSET + pad * sizeof(uint32_t), reg);
}
/**
* Sets the peripheral output for each specified output pad.
*
* @param output An MIO pad and a peripheral output to link it to.
*/
static void configure_output(pinmux_output_t output) {
abs_mmio_write32(
kBase + PINMUX_MIO_OUTSEL_0_REG_OFFSET + output.mio * sizeof(uint32_t),
output.outsel);
}
void pinmux_init(void) {
uint32_t bootstrap_en =
otp_read32(OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_EN_OFFSET);
if (launder32(bootstrap_en) == kHardenedBoolTrue) {
HARDENED_CHECK_EQ(bootstrap_en, kHardenedBoolTrue);
// Note: attributes should be configured before the pinmux matrix to avoid
// "undesired electrical behavior and/or contention at the pads".
enable_pull_down(kInputSwStrap0.pad);
enable_pull_down(kInputSwStrap1.pad);
enable_pull_down(kInputSwStrap2.pad);
configure_input(kInputSwStrap0);
configure_input(kInputSwStrap1);
configure_input(kInputSwStrap2);
}
configure_input(kInputUart0);
configure_output(kOutputUart0);
}