diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index d06c8e6aebc..43006e99a3e 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -22,3 +22,4 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_NXP_IOCON pinctrl_lpc_iocon.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_CC13XX_CC26XX pinctrl_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_ESP32 pinctrl_esp32.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_RV32M1 pinctrl_rv32m1.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_XLNX_ZYNQ pinctrl_xlnx_zynq.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 4c472fa14ed..a216cf41d6d 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -6,6 +6,10 @@ menuconfig PINCTRL if PINCTRL +module = PINCTRL +module-str = PINCTRL +source "subsys/logging/Kconfig.template.log_config" + config PINCTRL_STORE_REG bool help @@ -47,5 +51,6 @@ source "drivers/pinctrl/Kconfig.lpc_iocon" source "drivers/pinctrl/Kconfig.cc13xx_cc26xx" source "drivers/pinctrl/Kconfig.esp32" source "drivers/pinctrl/Kconfig.rv32m1" +source "drivers/pinctrl/Kconfig.xlnx" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.xlnx b/drivers/pinctrl/Kconfig.xlnx new file mode 100644 index 00000000000..c76b757208b --- /dev/null +++ b/drivers/pinctrl/Kconfig.xlnx @@ -0,0 +1,12 @@ +# Copyright (c) 2022 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_XLNX_PINCTRL_ZYNQ := xlnx,pinctrl-zynq + +config PINCTRL_XLNX_ZYNQ + bool "Xilinx Zynq 7000 processor system MIO pin controller driver" + depends on SOC_FAMILY_XILINX_ZYNQ7000 + default $(dt_compat_enabled,$(DT_COMPAT_XLNX_PINCTRL_ZYNQ)) + select SYSCON + help + Enable the Xilinx Zynq 7000 processor system MIO pin controller driver. diff --git a/drivers/pinctrl/pinctrl_xlnx_zynq.c b/drivers/pinctrl/pinctrl_xlnx_zynq.c new file mode 100644 index 00000000000..e19524ef85d --- /dev/null +++ b/drivers/pinctrl/pinctrl_xlnx_zynq.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(pinctrl_xlnx_zynq, CONFIG_PINCTRL_LOG_LEVEL); + +#define DT_DRV_COMPAT xlnx_pinctrl_zynq + +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, + "Unsupported number of instances"); + +/* Relative SLCR register offsets for use in asserts */ +#define MIO_PIN_53_OFFSET 0x00d4 +#define SD0_WP_CD_SEL_OFFSET 0x0130 +#define SD1_WP_CD_SEL_OFFSET 0x0134 + +static const struct device *slcr = DEVICE_DT_GET(DT_INST_PHANDLE(0, syscon)); +static mm_reg_t base = DT_INST_REG_ADDR(0); +K_SEM_DEFINE(pinctrl_lock, 1, 1); + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + uint16_t addr; + uint32_t val; + uint8_t i; + int err = 0; + + ARG_UNUSED(reg); + + if (!device_is_ready(slcr)) { + LOG_ERR("SLCR device not ready"); + return -ENODEV; + } + + /* Guard the read-modify-write operations */ + k_sem_take(&pinctrl_lock, K_FOREVER); + + for (i = 0; i < pin_cnt; i++) { + __ASSERT_NO_MSG(pins[i].offset <= MIO_PIN_53_OFFSET || + pins[i].offset == SD0_WP_CD_SEL_OFFSET || + pins[i].offset == SD1_WP_CD_SEL_OFFSET); + + addr = base + pins[i].offset; + + err = syscon_read_reg(slcr, addr, &val); + if (err != 0) { + LOG_ERR("failed to read SLCR addr 0x%04x (err %d)", addr, err); + break; + } + + LOG_DBG("0x%04x: mask 0x%08x, val 0x%08x", addr, pins[i].mask, pins[i].val); + LOG_DBG("0x%04x r: 0x%08x", addr, val); + + val &= ~(pins[i].mask); + val |= pins[i].val; + + LOG_DBG("0x%04x w: 0x%08x", addr, val); + + err = syscon_write_reg(slcr, addr, val); + if (err != 0) { + LOG_ERR("failed to write SLCR addr 0x%04x (err %d)", addr, err); + break; + } + } + + k_sem_give(&pinctrl_lock); + + return err; +}