diff --git a/cpp/hal/gpiobus_bananam2p.cpp b/cpp/hal/gpiobus_bananam2p.cpp index 9ff30ac8..a1e1a332 100644 --- a/cpp/hal/gpiobus_bananam2p.cpp +++ b/cpp/hal/gpiobus_bananam2p.cpp @@ -77,6 +77,8 @@ bool GPIOBUS_BananaM2p::Init(mode_e mode) InitializeGpio(); + MakeTable(); + // SetupSelEvent needs to be called AFTER Initialize GPIO. This function // reconfigures the SEL signal. if (!SetupSelEvent()) { @@ -533,8 +535,8 @@ void GPIOBUS_BananaM2p::SetREQ(bool ast) uint8_t GPIOBUS_BananaM2p::GetDAT() { GPIO_FUNCTION_TRACE - (void)Acquire(); - // TODO: This is inefficient, but it works... + + Acquire(); uint32_t data = ((GetSignal(BPI_PIN_DT0) ? 0x01 : 0x00) << 0) | ((GetSignal(BPI_PIN_DT1) ? 0x01 : 0x00) << 1) | ((GetSignal(BPI_PIN_DT2) ? 0x01 : 0x00) << 2) | ((GetSignal(BPI_PIN_DT3) ? 0x01 : 0x00) << 3) | @@ -549,27 +551,27 @@ void GPIOBUS_BananaM2p::SetDAT(uint8_t dat) { GPIO_FUNCTION_TRACE - SetMode(BPI_PIN_DT0, OUT); - SetMode(BPI_PIN_DT1, OUT); - SetMode(BPI_PIN_DT2, OUT); - SetMode(BPI_PIN_DT3, OUT); - SetMode(BPI_PIN_DT4, OUT); - SetMode(BPI_PIN_DT5, OUT); - SetMode(BPI_PIN_DT6, OUT); - SetMode(BPI_PIN_DT7, OUT); - SetMode(BPI_PIN_DP, OUT); + array gpio_reg_values = {0}; - // TODO: This is inefficient, but it works... - PinSetSignal(BPI_PIN_DT0, (dat & (1 << 0)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT1, (dat & (1 << 1)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT2, (dat & (1 << 2)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT3, (dat & (1 << 3)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT4, (dat & (1 << 4)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT5, (dat & (1 << 5)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT6, (dat & (1 << 6)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte - PinSetSignal(BPI_PIN_DT7, (dat & (1 << 7)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte + for (size_t gpio_num = 0; gpio_num < pintbl.size(); gpio_num++) { + bool value; + if (gpio_num < 8) { + // data bits + value = !(dat & (1 << gpio_num)); // NOSONAR: GCC 10 doesn't support shift operations on std::byte + } else { + // parity bit + value = (__builtin_parity(dat) == 1); + } - PinSetSignal(BPI_PIN_DP, __builtin_parity(dat) == 1); + if (value) { + uint32_t this_gpio = pintbl[gpio_num]; + int bank = SunXI::GPIO_BANK(this_gpio); + int offset = SunXI::GPIO_NUM(this_gpio); + gpio_reg_values[bank] |= (1 << offset); + } + } + + sunxi_set_all_gpios(gpio_data_masks, gpio_reg_values); } //--------------------------------------------------------------------------- @@ -589,89 +591,12 @@ const array GPIOBUS_BananaM2p::SignalTable = {BPI_PIN_DT0, BPI_PIN_DT1, //--------------------------------------------------------------------------- void GPIOBUS_BananaM2p::MakeTable(void) { - const array pintbl = {BPI_PIN_DT0, BPI_PIN_DT1, BPI_PIN_DT2, BPI_PIN_DT3, BPI_PIN_DT4, - BPI_PIN_DT5, BPI_PIN_DT6, BPI_PIN_DT7, BPI_PIN_DP}; + for (auto this_gpio : pintbl) { + int bank = SunXI::GPIO_BANK(this_gpio); + int offset = (SunXI::GPIO_NUM(this_gpio)); - array tblParity; - - // Create parity table - for (uint32_t i = 0; i < 0x100; i++) { - uint32_t bits = i; - uint32_t parity = 0; - for (int j = 0; j < 8; j++) { - parity ^= bits & 1; - bits >>= 1; - } - parity = ~parity; - tblParity[i] = parity & 1; + gpio_data_masks[bank] |= (1 << offset); } - -#if SIGNAL_CONTROL_MODE == 0 - // Mask and setting data generation - for (auto &tbl : tblDatMsk) { - tbl.fill(-1); - } - for (auto &tbl : tblDatSet) { - tbl.fill(0); - } - - for (uint32_t i = 0; i < 0x100; i++) { - // Bit string for inspection - uint32_t bits = i; - - // Get parity - if (tblParity[i]) { - bits |= (1 << 8); - } - - // Bit check - for (int j = 0; j < 9; j++) { - // Index and shift amount calculation - int index = pintbl[j] / 10; - int shift = (pintbl[j] % 10) * 3; - - // Mask data - tblDatMsk[index][i] &= ~(0x7 << shift); - - // Setting data - if (bits & 1) { - tblDatSet[index][i] |= (1 << shift); - } - - bits >>= 1; - } - } -#else - for (uint32_t i = 0; i < 0x100; i++) { - // Bit string for inspection - uint32_t bits = i; - - // Get parity - if (tblParity[i]) { - bits |= (1 << 8); - } - -#if SIGNAL_CONTROL_MODE == 1 - // Negative logic is inverted - bits = ~bits; -#endif - - // Create GPIO register information - uint32_t gpclr = 0; - uint32_t gpset = 0; - for (int j = 0; j < 9; j++) { - if (bits & 1) { - gpset |= (1 << pintbl[j]); - } else { - gpclr |= (1 << pintbl[j]); - } - bits >>= 1; - } - - tblDatMsk[i] = gpclr; - tblDatSet[i] = gpset; - } -#endif } bool GPIOBUS_BananaM2p::GetDP() const @@ -1058,6 +983,28 @@ void GPIOBUS_BananaM2p::sunxi_output_gpio(int pin, int value) pio->DAT |= (1 << num); } +void GPIOBUS_BananaM2p::sunxi_set_all_gpios(array &mask, array &value) +{ + GPIO_FUNCTION_TRACE + for (size_t bank = 0; bank < mask.size(); bank++) { + if (mask[bank] == 0) { + continue; + } + + volatile SunXI::sunxi_gpio_t *pio; + if (bank < 11) { + pio = &(pio_map->gpio_bank[bank]); + } else { + pio = &(r_pio_map->gpio_bank[bank - 11]); + } + + uint32_t reg_val = pio->DAT; + reg_val &= ~mask[bank]; + reg_val |= value[bank]; + pio->DAT = reg_val; + } +} + int GPIOBUS_BananaM2p::sunxi_input_gpio(int pin) const { GPIO_FUNCTION_TRACE diff --git a/cpp/hal/gpiobus_bananam2p.h b/cpp/hal/gpiobus_bananam2p.h index db99364f..2da28f7a 100644 --- a/cpp/hal/gpiobus_bananam2p.h +++ b/cpp/hal/gpiobus_bananam2p.h @@ -124,7 +124,7 @@ class GPIOBUS_BananaM2p : public GPIOBUS // Set SCSI I/O mode int GetMode(int pin) override; - bool GetSignal(int pin) const override; + inline bool GetSignal(int pin) const override; // Set SCSI output signal value void SetSignal(int pin, bool ast) override; @@ -153,35 +153,12 @@ class GPIOBUS_BananaM2p : public GPIOBUS bool SetupSelEvent(); -#if !defined(__x86_64__) && !defined(__X86__) - uint32_t baseaddr = 0; // Base address -#endif - volatile uint32_t *gpio_map = nullptr; // Timer control register volatile uint32_t *tmr_ctrl; - -#if !defined(__x86_64__) && !defined(__X86__) - volatile uint32_t *gicd = nullptr; // GIC Interrupt distributor register -#endif - - volatile uint32_t *gicc = nullptr; // GIC CPU interface register - - array gpfsel; // GPFSEL0-4 backup values - array signals = {0}; // All bus signals -#if SIGNAL_CONTROL_MODE == 0 - array, 3> tblDatMsk; // Data mask table - - array, 3> tblDatSet; // Data setting table -#else - array tblDatMsk = {}; // Data mask table - - array tblDatSet = {}; // Table setting table -#endif - int sunxi_setup(void); void sunxi_set_pullupdn(int gpio, int pud); @@ -206,13 +183,19 @@ class GPIOBUS_BananaM2p : public GPIOBUS SBC_Version::sbc_version_type sbc_version; - SunXI::sunxi_gpio_reg_t saved_gpio_config; - static const array SignalTable; void InitializeGpio(); std::vector gpio_banks; + // Note: These MUST be in order from bit 0 to bit 7 with parity as the last item in the array + const array pintbl = {BPI_PIN_DT0, BPI_PIN_DT1, BPI_PIN_DT2, BPI_PIN_DT3, BPI_PIN_DT4, + BPI_PIN_DT5, BPI_PIN_DT6, BPI_PIN_DT7, BPI_PIN_DP}; + + void sunxi_set_all_gpios(array &mask, array &value); + + array gpio_data_masks = {0}; + #if defined(__x86_64__) || defined(__X86__) || defined(__aarch64__) // The SEL_EVENT functions need to do something to prevent SonarCloud from // claiming they should be const