blob: 61b44bbed30b0400a8be204e95ada7a92474c1f7 [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/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 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 pad;
top_earlgrey_pinmux_outsel_t periph;
} pinmux_output_t;
/**
* UART RX pin.
*/
static const pinmux_input_t kInputUart0 = {
.periph = kTopEarlgreyPinmuxPeripheralInUart0Rx,
.pad = kTopEarlgreyPinmuxInselIoc3,
};
/**
* UART TX pin.
*/
static const pinmux_output_t kOutputUart0 = {
.pad = kTopEarlgreyPinmuxMioOutIoc4,
.periph = kTopEarlgreyPinmuxOutselUart0Tx,
};
/**
* SW strap pins.
*
*/
static const pinmux_input_t kInputSwStrap0 = {
.periph = kTopEarlgreyPinmuxPeripheralInGpioGpio22,
.pad = kTopEarlgreyPinmuxInselIoc0,
};
static const pinmux_input_t kInputSwStrap1 = {
.periph = kTopEarlgreyPinmuxPeripheralInGpioGpio23,
.pad = kTopEarlgreyPinmuxInselIoc1,
};
static const pinmux_input_t kInputSwStrap2 = {
.periph = kTopEarlgreyPinmuxPeripheralInGpioGpio24,
.pad = kTopEarlgreyPinmuxInselIoc2,
};
/**
* 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.pad);
}
/**
* Enables pull-down for the specified pad.
*
* @param pad A MIO pad.
*/
static void enable_pull_down(top_earlgrey_pinmux_insel_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);
}
/**
* Configures the given pin as input and enables the internal pull-down.
*
* We enable internal pull-downs since we expect strong pull-ups on the strap
* pins.
*
* @param input A peripheral input and MIO pad to link it to.
*/
static void configure_strap_pin(pinmux_input_t input) {
configure_input(input);
enable_pull_down(input.pad);
}
/**
* 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.pad * sizeof(uint32_t),
output.periph);
}
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);
configure_strap_pin(kInputSwStrap0);
configure_strap_pin(kInputSwStrap1);
configure_strap_pin(kInputSwStrap2);
}
configure_input(kInputUart0);
configure_output(kOutputUart0);
}