From ff8ad5174149eb09dde878ead2b9713754ad2761 Mon Sep 17 00:00:00 2001 From: zouboan Date: Tue, 16 Jul 2024 21:19:44 +0800 Subject: [PATCH 1/2] zynq-mpsoc: add support for mio/emio --- arch/arm64/src/zynq-mpsoc/Make.defs | 2 +- arch/arm64/src/zynq-mpsoc/zynq_mio.c | 561 +++++++++++++++++++++++++++ arch/arm64/src/zynq-mpsoc/zynq_mio.h | 272 +++++++++++++ 3 files changed, 834 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/src/zynq-mpsoc/zynq_mio.c create mode 100644 arch/arm64/src/zynq-mpsoc/zynq_mio.h diff --git a/arch/arm64/src/zynq-mpsoc/Make.defs b/arch/arm64/src/zynq-mpsoc/Make.defs index e600d84807e35..4c857c4e59b43 100644 --- a/arch/arm64/src/zynq-mpsoc/Make.defs +++ b/arch/arm64/src/zynq-mpsoc/Make.defs @@ -21,7 +21,7 @@ include common/Make.defs # Rockchip zynq mpsoc specific C source files -CHIP_CSRCS = zynq_boot.c zynq_serial.c +CHIP_CSRCS = zynq_boot.c zynq_serial.c zynq_mio.c ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) CHIP_ASRCS = zynq_lowputc.S diff --git a/arch/arm64/src/zynq-mpsoc/zynq_mio.c b/arch/arm64/src/zynq-mpsoc/zynq_mio.c new file mode 100644 index 0000000000000..ee8513315a52e --- /dev/null +++ b/arch/arm64/src/zynq-mpsoc/zynq_mio.c @@ -0,0 +1,561 @@ +/**************************************************************************** + * arch/arm64/src/zynq-mpsoc/zynq_mio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "arm64_internal.h" +#include "chip.h" +#include "zynq_mio.h" + +/* Register offsets for the GPIO. Each register is 32 bits. */ + +#define ZYNQ_MIO_DATA_LSW_OFFSET 0x00000000 /* Mask and Data Register LSW */ +#define ZYNQ_MIO_DATA_MSW_OFFSET 0x00000004 /* Mask and Data Register MSW */ +#define ZYNQ_MIO_DATA_OFFSET 0x00000040 /* Data Register */ +#define ZYNQ_MIO_DATA_RO_OFFSET 0x00000060 /* Data Register - Input */ +#define ZYNQ_MIO_DIRM_OFFSET 0x00000204 /* Direction Mode Register */ +#define ZYNQ_MIO_OUTEN_OFFSET 0x00000208 /* Output Enable Register */ +#define ZYNQ_MIO_INTMASK_OFFSET 0x0000020C /* Interrupt Mask Register */ +#define ZYNQ_MIO_INTEN_OFFSET 0x00000210 /* Interrupt Enable Register */ +#define ZYNQ_MIO_INTDIS_OFFSET 0x00000214 /* Interrupt Disable Register */ +#define ZYNQ_MIO_INTSTS_OFFSET 0x00000218 /* Interrupt Status Register */ +#define ZYNQ_MIO_INTTYPE_OFFSET 0x0000021C /* Interrupt Type Register */ +#define ZYNQ_MIO_INTPOL_OFFSET 0x00000220 /* Interrupt Polarity Register */ +#define ZYNQ_MIO_INTANY_OFFSET 0x00000224 /* Interrupt On Any Register */ + +/* Register offsets for each Bank. */ + +#define ZYNQ_MIO_DATA_MASK_OFFSET 0x00000008 /* Data/Mask Registers offset */ +#define ZYNQ_MIO_DATA_BANK_OFFSET 0x00000004 /* Data Registers offset */ +#define ZYNQ_MIO_REG_MASK_OFFSET 0x00000040 /* Registers offset */ + +#define ZYNQ_MIO_MID_PIN_NUM (16) +#define ZYNQ_MIO_UPPER_MASK 0xFFFF0000 /* GPIO upper 16 bit mask */ +#define ZYNQ_MIO_INTTYPE_BANK012_RESET 0x03ffffff /* Resets value */ +#define ZYNQ_MIO_INTTYPE_BANK345_RESET 0xffffffff /* Resets value */ + +/**************************************************************************** + * + * This macro reads the given register. + * + * BaseAddr is the base address of the device. + * reg_offset is the register offset to be read. + * + * return The 32-bit value of the register + * + ****************************************************************************/ + +#define mio_read_reg(reg_offset) \ +getreg32(ZYNQ_MPSOC_GPIO_ADDR + (uint32_t)(reg_offset)) + +/**************************************************************************** + * + * This macro writes to the given register. + * + * BaseAddr is the base address of the device. + * reg_offset is the offset of the register to be written. + * data is the 32-bit value to write to the register. + * + ****************************************************************************/ + +#define mio_write_reg(reg_offset, data) \ +putreg32(data, ZYNQ_MPSOC_GPIO_ADDR + (uint32_t)(reg_offset)) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * + * Get the bank number and the pin number in the bank, for the given pinnum + * in the GPIO device. + * + * pinnum is the pin number in the GPIO device. + * bank returns the bank in which this GPIO pin is present. + * Valid values are 0 to ZYNQ_MIO_MAX_BANKS - 1. + * pin_in_bank returns the pin Number within the bank. + * + ****************************************************************************/ + +static void mio_get_bank_pin(uint32_t pinnum, + uint32_t *bank, uint32_t *pin_in_bank) +{ + uint32_t pin_table[6]; + + /* This structure defines the mapping of the pin numbers to the banks when + * the driver APIs are used for working on the individual pins. + */ + + pin_table[0] = 25; /* 0 - 25, bank 0 */ + pin_table[1] = 51; /* 26 - 51, bank 1 */ + pin_table[2] = 77; /* 52 - 77, bank 2 */ + pin_table[3] = 109; /* 78 - 109, bank 3 */ + pin_table[4] = 141; /* 110 - 141, bank 4 */ + pin_table[5] = 173; /* 142 - 173 bank 5 */ + + *bank = 0; + while (*bank < ZYNQ_MIO_MAX_BANK) + { + if (pinnum <= pin_table[*bank]) + { + break; + } + + (*bank)++; + } + + if (*bank == 0) + { + *pin_in_bank = pinnum; + } + else + { + *pin_in_bank = pinnum % (pin_table[*bank - 1] + 1); + } +} + +/**************************************************************************** + * + * This function resets the GPIO module by writing reset values to all + * registers + * + ****************************************************************************/ + +void zynq_mio_initialize(void) +{ + uint32_t bank; + + /* Write reset values to all mask data registers */ + + for (bank = 2; bank < ZYNQ_MIO_MAX_BANK; bank++) + { + mio_write_reg(((bank * ZYNQ_MIO_DATA_MASK_OFFSET) + + ZYNQ_MIO_DATA_LSW_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_DATA_MASK_OFFSET) + + ZYNQ_MIO_DATA_MSW_OFFSET), 0x0); + } + + /* Write reset values to all output data registers */ + + for (bank = 2; bank < ZYNQ_MIO_MAX_BANK; bank++) + { + mio_write_reg(((bank * ZYNQ_MIO_DATA_BANK_OFFSET) + + ZYNQ_MIO_DATA_OFFSET), 0x0); + } + + /* Reset all registers of all GPIO banks */ + + for (bank = 0; bank < ZYNQ_MIO_MAX_BANK; bank++) + { + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_DIRM_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_OUTEN_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTMASK_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTEN_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTDIS_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTSTS_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTPOL_OFFSET), 0x0); + mio_write_reg(((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTANY_OFFSET), 0x0); + } + + /* By default, interrupts are not masked in GPIO. Disable + * interrupts for all pins in all the 4 banks. + */ + + for (bank = 0; bank < 3; bank++) + { + mio_write_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTDIS_OFFSET, ZYNQ_MIO_INTTYPE_BANK012_RESET); + } + + for (bank = 3; bank < ZYNQ_MIO_MAX_BANK; bank++) + { + mio_write_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_INTDIS_OFFSET, ZYNQ_MIO_INTTYPE_BANK345_RESET); + } +} + +/**************************************************************************** + * + * read the data register of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * + * return Current value of the data register. + * + * note: This function is used for reading the state of all the GPIO pins + * of specified bank. + * + ****************************************************************************/ + +uint32_t zynq_mio_read(uint32_t bank) +{ + DEBUGASSERT(bank < ZYNQ_MIO_MAX_BANK); + + return mio_read_reg((bank * ZYNQ_MIO_DATA_BANK_OFFSET) + + ZYNQ_MIO_DATA_RO_OFFSET); +} + +/**************************************************************************** + * + * read data from the specified pin. + * + * pin is the pin number for which the data has to be read. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * + * return Current value of the pin (0 or 1). + * + * note: This function is used for reading the state of the specified + * GPIO pin. + * + ****************************************************************************/ + +bool zynq_mio_readpin(uint32_t pin) +{ + uint32_t bank; + uint32_t pinnum; + + DEBUGASSERT(pin < ZYNQ_MIO_PIN_MAX); + + /* Get the bank number and pin number within the bank. */ + + mio_get_bank_pin(pin, &bank, &pinnum); + + return (bool)(zynq_mio_read(bank) >> pinnum); +} + +/**************************************************************************** + * + * write to the data register of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * data is the value to be written to the data register. + * + * note: This function is used for writing to all the GPIO pins of + * the bank. The previous state of the pins is not maintained. + * + ****************************************************************************/ + +void zynq_mio_write(uint32_t bank, uint32_t data) +{ + DEBUGASSERT(bank < ZYNQ_MIO_MAX_BANK); + + mio_write_reg((bank * ZYNQ_MIO_DATA_BANK_OFFSET) + + ZYNQ_MIO_DATA_OFFSET, data); +} + +/**************************************************************************** + * + * write data to the specified pin. + * + * pin is the pin number to which the data is to be written. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * data is the data to be written to the specified pin (0 or 1). + * + * note: This function does a masked write to the specified pin of + * the specified GPIO bank. The previous state of other pins + * is maintained. + * + ****************************************************************************/ + +void zynq_mio_writepin(uint32_t pin, bool data) +{ + uint32_t reg_offset; + uint32_t value; + uint32_t bank; + uint32_t pinnum; + uint32_t data_var = (uint32_t)data; + + DEBUGASSERT(pin < ZYNQ_MIO_PIN_MAX); + + /* Get the bank number and pin number within the bank. */ + + mio_get_bank_pin(pin, &bank, &pinnum); + + if (pinnum >= ZYNQ_MIO_MID_PIN_NUM) + { + /* There are only 16 data bits in bit maskable register. */ + + pinnum -= ZYNQ_MIO_MID_PIN_NUM; + reg_offset = ZYNQ_MIO_DATA_MSW_OFFSET; + } + else + { + reg_offset = ZYNQ_MIO_DATA_LSW_OFFSET; + } + + /* Get the 32 bit value to be written to the Mask/data register where + * the upper 16 bits is the mask and lower 16 bits is the data. + */ + + value = ~(0x1 << (pinnum + ZYNQ_MIO_MID_PIN_NUM)) & + ((data_var << pinnum) | ZYNQ_MIO_UPPER_MASK); + mio_write_reg((bank * ZYNQ_MIO_DATA_MASK_OFFSET) + reg_offset, value); +} + +/**************************************************************************** + * + * Set the dir of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * dir is the 32 bit mask of the pin direction to be set for + * all the pins in the bank. Bits with 0 are set to Input mode, + * bits with 1 are set to Output Mode. + * + * note: This function is used for setting the direction of all the pins + * in the specified bank. The previous state of the pins is + * not maintained. + * + ****************************************************************************/ + +void zynq_mio_setdir(uint32_t bank, uint32_t dir) +{ + DEBUGASSERT(bank < ZYNQ_MIO_MAX_BANK); + + mio_write_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_DIRM_OFFSET, dir); +} + +/**************************************************************************** + * + * Set the dir of the specified pin. + * + * pin is the pin number to which the data is to be written. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * dir is the direction to be set for the specified pin. + * Valid values are 0 for Input dir, 1 for Output dir. + * + ****************************************************************************/ + +void zynq_mio_setdirpin(uint32_t pin, bool dir) +{ + uint32_t bank; + uint32_t pinnum; + uint32_t dir_mode; + + DEBUGASSERT(pin < ZYNQ_MIO_PIN_MAX); + + /* Get the bank number and pin number within the bank. */ + + mio_get_bank_pin(pin, &bank, &pinnum); + + dir_mode = mio_read_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_DIRM_OFFSET); + + if (dir) + { + dir_mode |= (1 << pinnum); /* Output dir */ + } + else + { + dir_mode &= ~ (1 << pinnum); /* Input dir */ + } + + mio_write_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_DIRM_OFFSET, dir_mode); +} + +/**************************************************************************** + * + * Get the dir of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * + * return Returns a 32 bit mask of the dir register. Bits with 0 are + * in Input mode, bits with 1 are in Output Mode. + * + ****************************************************************************/ + +uint32_t zynq_mio_getdir(uint32_t bank) +{ + DEBUGASSERT(bank < ZYNQ_MIO_MAX_BANK); + + return mio_read_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_DIRM_OFFSET); +} + +/**************************************************************************** + * + * Get the dir of the specified pin. + * + * pin is the pin number for which the dir is to be + * retrieved. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * + * return dir of the specified pin. + * - 0 for Input dir + * - 1 for Output dir + * + ****************************************************************************/ + +uint32_t zynq_mio_getdirpin(uint32_t pin) +{ + uint32_t bank; + uint32_t pinnum; + + DEBUGASSERT(pin < ZYNQ_MIO_PIN_MAX); + + /* Get the bank number and pin number within the bank. */ + + mio_get_bank_pin(pin, &bank, &pinnum); + + return (mio_read_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_DIRM_OFFSET) >> pinnum) & 1; +} + +/**************************************************************************** + * + * Set the Output Enable of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * outen is the 32 bit mask of the Output Enables to be set for + * all the pins in the bank. The Output Enable of bits with 0 are + * disabled, the Output Enable of bits with 1 are enabled. + * + * return None. + * + * note: This function is used for setting the Output Enables of all the + * pins in the specified bank. The previous state of the Output + * Enables is not maintained. + * + ****************************************************************************/ + +void zynq_mio_setouten(uint32_t bank, uint32_t outen) +{ + DEBUGASSERT(bank < ZYNQ_MIO_MAX_BANK); + + mio_write_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_OUTEN_OFFSET, outen); +} + +/**************************************************************************** + * + * Set the Output Enable of the specified pin. + * + * pin is the pin number to which the data is to be written. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * outen specifies whether the Output Enable for the specified + * pin should be enabled. + * Valid values are 0 for Disabling Output Enable, + * 1 for Enabling Output Enable. + * + ****************************************************************************/ + +void zynq_mio_setoutenpin(uint32_t pin, bool outen) +{ + uint32_t bank; + uint32_t pinnum; + uint32_t outen_reg; + + DEBUGASSERT(pin < ZYNQ_MIO_PIN_MAX); + + /* Get the bank number and pin number within the bank. */ + + mio_get_bank_pin(pin, &bank, &pinnum); + + outen_reg = mio_read_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_OUTEN_OFFSET); + + if (outen) + { + outen_reg |= (1 << pinnum); /* Enable Output Enable */ + } + else + { + outen_reg &= ~ (1 << pinnum); /* Disable Output Enable */ + } + + mio_write_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_OUTEN_OFFSET, outen_reg); +} + +/**************************************************************************** + * + * Get the Output Enable status of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * + * return Returns a a 32 bit mask of the Output Enable register. + * Bits with 0 are in Disabled state, bits with 1 are in + * Enabled State. + * + ****************************************************************************/ + +uint32_t zynq_mio_getouten(uint32_t bank) +{ + DEBUGASSERT(bank < ZYNQ_MIO_MAX_BANK); + + return mio_read_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_OUTEN_OFFSET); +} + +/**************************************************************************** + * + * Get the Output Enable status of the specified pin. + * + * pin is the pin number for which the Output Enable status is to + * be retrieved. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * + * return Output Enable of the specified pin. + * - 0 if Output Enable is disabled for this pin + * - 1 if Output Enable is enabled for this pin + * + ****************************************************************************/ + +uint32_t zynq_mio_getoutenpin(uint32_t pin) +{ + uint32_t bank; + uint32_t pinnum; + + DEBUGASSERT(pin < ZYNQ_MIO_PIN_MAX); + + /* Get the bank number and pin number within the bank. */ + + mio_get_bank_pin(pin, &bank, &pinnum); + + return (mio_read_reg((bank * ZYNQ_MIO_REG_MASK_OFFSET) + + ZYNQ_MIO_OUTEN_OFFSET) >> pinnum) & 1; +} diff --git a/arch/arm64/src/zynq-mpsoc/zynq_mio.h b/arch/arm64/src/zynq-mpsoc/zynq_mio.h new file mode 100644 index 0000000000000..883467088ea0f --- /dev/null +++ b/arch/arm64/src/zynq-mpsoc/zynq_mio.h @@ -0,0 +1,272 @@ +/**************************************************************************** + * arch/arm64/src/zynq-mpsoc/zynq_mio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_ZYNQ_MPSOC_ZYNQ_MIO_H +#define __ARCH_ARM64_ZYNQ_MPSOC_ZYNQ_MIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm64_internal.h" +#include "hardware/zynq_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ZYNQ_MIO_MAX_BANK (6) /* MIO+EMIO MAX bank number */ +#define ZYNQ_MIO_PIN_MAX (174) /* MIO+EMIO MAX pin number */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * + * This function resets the GPIO module by writing reset values to all + * registers + * + ****************************************************************************/ + +void zynq_mio_initialize(void); + +/**************************************************************************** + * + * read the data register of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * + * return Current value of the data register. + * + * note: This function is used for reading the state of all the GPIO pins + * of specified bank. + * + ****************************************************************************/ + +uint32_t zynq_mio_read(uint32_t bank); + +/**************************************************************************** + * + * read data from the specified pin. + * + * pin is the pin number for which the data has to be read. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * + * return Current value of the pin (0 or 1). + * + * note: This function is used for reading the state of the specified + * GPIO pin. + * + ****************************************************************************/ + +bool zynq_mio_readpin(uint32_t pin); + +/**************************************************************************** + * + * write to the data register of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * data is the value to be written to the data register. + * + * note: This function is used for writing to all the GPIO pins of + * the bank. The previous state of the pins is not maintained. + * + ****************************************************************************/ + +void zynq_mio_write(uint32_t bank, uint32_t data); + +/**************************************************************************** + * + * write data to the specified pin. + * + * pin is the pin number to which the data is to be written. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * data is the data to be written to the specified pin (0 or 1). + * + * note: This function does a masked write to the specified pin of + * the specified GPIO bank. The previous state of other pins + * is maintained. + * + ****************************************************************************/ + +void zynq_mio_writepin(uint32_t pin, bool data); + +/**************************************************************************** + * + * Set the dir of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * dir is the 32 bit mask of the pin direction to be set for + * all the pins in the bank. Bits with 0 are set to Input mode, + * bits with 1 are set to Output Mode. + * + * note: This function is used for setting the direction of all the pins + * in the specified bank. The previous state of the pins is + * not maintained. + * + ****************************************************************************/ + +void zynq_mio_setdir(uint32_t bank, uint32_t dir); + +/**************************************************************************** + * + * Set the dir of the specified pin. + * + * pin is the pin number to which the data is to be written. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * dir is the direction to be set for the specified pin. + * Valid values are 0 for Input dir, 1 for Output dir. + * + ****************************************************************************/ + +void zynq_mio_setdirpin(uint32_t pin, bool dir); + +/**************************************************************************** + * + * Get the dir of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * + * return Returns a 32 bit mask of the dir register. Bits with 0 are + * in Input mode, bits with 1 are in Output Mode. + * + ****************************************************************************/ + +uint32_t zynq_mio_getdir(uint32_t bank); + +/**************************************************************************** + * + * Get the dir of the specified pin. + * + * pin is the pin number for which the dir is to be + * retrieved. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * + * return dir of the specified pin. + * - 0 for Input dir + * - 1 for Output dir + * + ****************************************************************************/ + +uint32_t zynq_mio_getdirpin(uint32_t pin); + +/**************************************************************************** + * + * Set the Output Enable of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * outen is the 32 bit mask of the Output Enables to be set for + * all the pins in the bank. The Output Enable of bits with 0 are + * disabled, the Output Enable of bits with 1 are enabled. + * + * return None. + * + * note: This function is used for setting the Output Enables of all the + * pins in the specified bank. The previous state of the Output + * Enables is not maintained. + * + ****************************************************************************/ + +void zynq_mio_setouten(uint32_t bank, uint32_t outen); + +/**************************************************************************** + * + * Set the Output Enable of the specified pin. + * + * pin is the pin number to which the data is to be written. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * outen specifies whether the Output Enable for the specified + * pin should be enabled. + * Valid values are 0 for Disabling Output Enable, + * 1 for Enabling Output Enable. + * + ****************************************************************************/ + +void zynq_mio_setoutenpin(uint32_t pin, bool outen); + +/**************************************************************************** + * + * Get the Output Enable status of the pins of the specified GPIO bank. + * + * bank is the bank number of the GPIO to operate on. + * Valid values are 0-5 in Zynq Ultrascale+ MP. + * + * return Returns a a 32 bit mask of the Output Enable register. + * Bits with 0 are in Disabled state, bits with 1 are in + * Enabled State. + * + ****************************************************************************/ + +uint32_t zynq_mio_getouten(uint32_t bank); + +/**************************************************************************** + * + * Get the Output Enable status of the specified pin. + * + * pin is the pin number for which the Output Enable status is to + * be retrieved. + * Valid values are 0-173 in Zynq Ultrascale+ MP. + * + * return Output Enable of the specified pin. + * - 0 if Output Enable is disabled for this pin + * - 1 if Output Enable is enabled for this pin + * + ****************************************************************************/ + +uint32_t zynq_mio_getoutenpin(uint32_t pin); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM64_ZYNQ_MPSOC_ZYNQ_MIO_H */ From 4484923d258e0747b84f065fa58bc0ca87c99859 Mon Sep 17 00:00:00 2001 From: zouboan Date: Tue, 16 Jul 2024 21:24:01 +0800 Subject: [PATCH 2/2] zcu111: add support for board led --- .../zynq-mpsoc/zcu111/configs/nsh/defconfig | 1 - .../arm64/zynq-mpsoc/zcu111/include/board.h | 42 ++++++++++ boards/arm64/zynq-mpsoc/zcu111/src/Makefile | 4 + boards/arm64/zynq-mpsoc/zcu111/src/zcu111.h | 14 ++++ .../zynq-mpsoc/zcu111/src/zcu111_autoleds.c | 81 +++++++++++++++++++ .../zynq-mpsoc/zcu111/src/zcu111_boardinit.c | 5 +- 6 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 boards/arm64/zynq-mpsoc/zcu111/src/zcu111_autoleds.c diff --git a/boards/arm64/zynq-mpsoc/zcu111/configs/nsh/defconfig b/boards/arm64/zynq-mpsoc/zcu111/configs/nsh/defconfig index 2eafe59f17755..f49d030838a51 100644 --- a/boards/arm64/zynq-mpsoc/zcu111/configs/nsh/defconfig +++ b/boards/arm64/zynq-mpsoc/zcu111/configs/nsh/defconfig @@ -5,7 +5,6 @@ # You can then do "make savedefconfig" to generate a new defconfig file that includes your # modifications. # -# CONFIG_ARCH_LEDS is not set # CONFIG_DEBUG_OPT_UNUSED_SECTIONS is not set CONFIG_ARCH="arm64" CONFIG_ARCH_ARM64=y diff --git a/boards/arm64/zynq-mpsoc/zcu111/include/board.h b/boards/arm64/zynq-mpsoc/zcu111/include/board.h index a652b6e4ef0a4..4932c5cef768b 100644 --- a/boards/arm64/zynq-mpsoc/zcu111/include/board.h +++ b/boards/arm64/zynq-mpsoc/zcu111/include/board.h @@ -31,4 +31,46 @@ * Pre-processor Definitions ****************************************************************************/ +/* LED definitions **********************************************************/ + +/* The ZCU111 PL has only one MIO LEDs, Others LED connected to PL. + * + * If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs in + * any way. The following definitions are used to access individual LEDs. + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_LED1 0 +#define BOARD_NLEDS 1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) + +/* If CONFIG_ARCH_LEDs is defined, then NuttX will control the LED on board + * The following definitions describe how NuttX controls the LED: + * + * SYMBOL Meaning LED1 state + * ------------------ ----------------------- ---------- + * LED_STARTED NuttX has been started OFF + * LED_HEAPALLOCATE Heap has been allocated OFF + * LED_IRQSENABLED Interrupts enabled OFF + * LED_STACKCREATED Idle stack created ON + * LED_INIRQ In an interrupt No change + * LED_SIGNAL In a signal handler No change + * LED_ASSERTION An assertion failed No change + * LED_PANIC The system has crashed Blinking + * LED_IDLE STM32 is is sleep mode Not used + */ + +#define LED_STARTED 0 +#define LED_HEAPALLOCATE 0 +#define LED_IRQSENABLED 0 +#define LED_STACKCREATED 1 +#define LED_INIRQ 2 +#define LED_SIGNAL 2 +#define LED_ASSERTION 2 +#define LED_PANIC 1 + #endif /* __BOARDS_ARM64_ZYNQ_MPSOC_ZCU111_INCLUDE_BOARD_H */ diff --git a/boards/arm64/zynq-mpsoc/zcu111/src/Makefile b/boards/arm64/zynq-mpsoc/zcu111/src/Makefile index efa6c65ab4165..d59058840ddc0 100644 --- a/boards/arm64/zynq-mpsoc/zcu111/src/Makefile +++ b/boards/arm64/zynq-mpsoc/zcu111/src/Makefile @@ -23,6 +23,10 @@ include $(TOPDIR)/Make.defs CSRCS = zcu111_boardinit.c CSRCS += zcu111_appinit.c +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += zcu111_autoleds.c +endif + ifeq ($(CONFIG_ETC_ROMFS),y) RCSRCS = etc/init.d/rc.sysinit etc/init.d/rcS endif diff --git a/boards/arm64/zynq-mpsoc/zcu111/src/zcu111.h b/boards/arm64/zynq-mpsoc/zcu111/src/zcu111.h index 7f5445e2884e1..57ff7b1e34135 100644 --- a/boards/arm64/zynq-mpsoc/zcu111/src/zcu111.h +++ b/boards/arm64/zynq-mpsoc/zcu111/src/zcu111.h @@ -27,6 +27,20 @@ #include #include +#include "zynq_mio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* LEDs *********************************************************************/ + +/* Green LED on MIO23 */ + +#define LED_DS50 23 + #ifndef __ASSEMBLY__ /**************************************************************************** diff --git a/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_autoleds.c b/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_autoleds.c new file mode 100644 index 0000000000000..404b317463b50 --- /dev/null +++ b/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_autoleds.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * boards/arm64/zynq-mpsoc/zcu111/src/zcu111_autoleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "arm64_internal.h" +#include "zcu111.h" + +#if defined(CONFIG_ARCH_LEDS) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + /* Configure LED GPIOs for output */ + + zynq_mio_setdirpin(LED_DS50, 1); + zynq_mio_setoutenpin(LED_DS50, 1); + zynq_mio_writepin(LED_DS50, false); +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + if (led == BOARD_LED1) + { + zynq_mio_writepin(LED_DS50, true); + } +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + if (led == BOARD_LED1) + { + zynq_mio_writepin(LED_DS50, false); + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_boardinit.c b/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_boardinit.c index 957a897737f96..5caadf593018a 100644 --- a/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_boardinit.c +++ b/boards/arm64/zynq-mpsoc/zcu111/src/zcu111_boardinit.c @@ -76,10 +76,13 @@ void zynq_memory_initialize(void) void zynq_board_initialize(void) { + /* resets the GPIO module by writing reset values to all registers */ + + zynq_mio_initialize(); #ifdef CONFIG_ARCH_LEDS /* Configure on-board LEDs if LED support has been selected. */ - /* board_autoled_initialize(); */ + board_autoled_initialize(); #endif }