129 lines
3.4 KiB
C
129 lines
3.4 KiB
C
/*
|
|
* Copyright (c) 2023 Antmicro <www.antmicro.com>
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT quicklogic_eos_s3_pinctrl
|
|
|
|
#include <zephyr/arch/cpu.h>
|
|
#include <zephyr/devicetree.h>
|
|
#include <zephyr/drivers/pinctrl.h>
|
|
#include <zephyr/logging/log.h>
|
|
#include <zephyr/dt-bindings/pinctrl/quicklogic-eos-s3-pinctrl.h>
|
|
#include <soc.h>
|
|
|
|
LOG_MODULE_REGISTER(pinctrl_eos_s3, CONFIG_PINCTRL_LOG_LEVEL);
|
|
|
|
#define FUNCTION_REGISTER(func) (func >> 13)
|
|
#define PAD_FUNC_SEL_MASK GENMASK(2, 0)
|
|
#define PAD_CTRL_SEL_BIT0 3
|
|
#define PAD_CTRL_SEL_BIT1 4
|
|
#define PAD_OUTPUT_EN_BIT 5
|
|
#define PAD_PULL_UP_BIT 6
|
|
#define PAD_PULL_DOWN_BIT 7
|
|
#define PAD_DRIVE_STRENGTH_BIT0 8
|
|
#define PAD_DRIVE_STRENGTH_BIT1 9
|
|
#define PAD_SLEW_RATE_BIT 10
|
|
#define PAD_INPUT_EN_BIT 11
|
|
#define PAD_SCHMITT_EN_BIT 12
|
|
|
|
/*
|
|
* Program IOMUX_func_SEL register.
|
|
*/
|
|
static int pinctrl_eos_s3_input_selection(uint32_t pin, uint32_t sel_reg)
|
|
{
|
|
volatile uint32_t *reg = (uint32_t *)IO_MUX_BASE;
|
|
|
|
if (sel_reg <= IO_MUX_MAX_PAD_NR || sel_reg > IO_MUX_REG_MAX_OFFSET) {
|
|
return -EINVAL;
|
|
}
|
|
reg += sel_reg;
|
|
*reg = pin;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Program IOMUX_PAD_x_CTRL register.
|
|
*/
|
|
static int pinctrl_eos_s3_set(uint32_t pin, uint32_t func)
|
|
{
|
|
volatile uint32_t *reg = (uint32_t *)IO_MUX_BASE;
|
|
|
|
if (pin > IO_MUX_REG_MAX_OFFSET) {
|
|
return -EINVAL;
|
|
}
|
|
reg += pin;
|
|
*reg = func;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int pinctrl_eos_s3_configure_pin(const pinctrl_soc_pin_t *pin)
|
|
{
|
|
uint32_t reg_value = 0;
|
|
|
|
/* Set function. */
|
|
reg_value |= (pin->iof & PAD_FUNC_SEL_MASK);
|
|
|
|
/* Output enable is active low. */
|
|
WRITE_BIT(reg_value, PAD_OUTPUT_EN_BIT, pin->output_enable ? 0 : 1);
|
|
|
|
/* These are active high. */
|
|
WRITE_BIT(reg_value, PAD_INPUT_EN_BIT, pin->input_enable);
|
|
WRITE_BIT(reg_value, PAD_SLEW_RATE_BIT, pin->slew_rate);
|
|
WRITE_BIT(reg_value, PAD_SCHMITT_EN_BIT, pin->schmitt_enable);
|
|
WRITE_BIT(reg_value, PAD_CTRL_SEL_BIT0, pin->control_selection & BIT(0));
|
|
WRITE_BIT(reg_value, PAD_CTRL_SEL_BIT1, pin->control_selection & BIT(1));
|
|
|
|
switch (pin->drive_strength) {
|
|
case 2:
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 0);
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 0);
|
|
break;
|
|
case 4:
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 1);
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 0);
|
|
break;
|
|
case 8:
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 0);
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 1);
|
|
break;
|
|
case 12:
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 1);
|
|
WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 1);
|
|
break;
|
|
default:
|
|
LOG_ERR("Selected drive-strength is not supported: %d\n", pin->drive_strength);
|
|
}
|
|
|
|
/* Enable pull-up by default; overwrite if any setting was chosen. */
|
|
WRITE_BIT(reg_value, PAD_PULL_UP_BIT, 1);
|
|
WRITE_BIT(reg_value, PAD_PULL_DOWN_BIT, 0);
|
|
if (pin->high_impedance) {
|
|
WRITE_BIT(reg_value, PAD_PULL_UP_BIT, 0);
|
|
} else if (pin->pull_up | pin->pull_down) {
|
|
WRITE_BIT(reg_value, PAD_PULL_UP_BIT, pin->pull_up);
|
|
WRITE_BIT(reg_value, PAD_PULL_DOWN_BIT, pin->pull_down);
|
|
}
|
|
|
|
/* Program registers. */
|
|
pinctrl_eos_s3_set(pin->pin, reg_value);
|
|
if (pin->input_enable && FUNCTION_REGISTER(pin->iof)) {
|
|
pinctrl_eos_s3_input_selection(pin->pin, FUNCTION_REGISTER(pin->iof));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
|
|
{
|
|
ARG_UNUSED(reg);
|
|
|
|
for (int i = 0; i < pin_cnt; i++) {
|
|
pinctrl_eos_s3_configure_pin(&pins[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|