2022-12-03 04:20:27 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2022-12-05 17:58:23 +00:00
|
|
|
// SCSI Target Emulator PiSCSI
|
2022-12-03 04:20:27 +00:00
|
|
|
// for Raspberry Pi
|
|
|
|
//
|
|
|
|
// Copyright (C) 2022 akuker
|
|
|
|
//
|
|
|
|
// [ Utility functions for working with Allwinner CPUs ]
|
|
|
|
//
|
|
|
|
// This should include generic functions that can be applicable to
|
|
|
|
// different variants of the SunXI (Allwinner) SoCs
|
|
|
|
//
|
|
|
|
// Large portions of this functionality were derived from c_gpio.c, which
|
|
|
|
// is part of the RPI.GPIO library available here:
|
|
|
|
// https://github.com/BPI-SINOVOIP/RPi.GPIO/blob/master/source/c_gpio.c
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
// this software and associated documentation files (the "Software"), to deal in
|
|
|
|
// the Software without restriction, including without limitation the rights to
|
|
|
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
|
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
|
|
|
// so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
|
|
// copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
// SOFTWARE.
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#ifndef __arm__
|
|
|
|
#include <time.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
class SunXI
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static inline int GPIO_BANK(int pin)
|
|
|
|
{
|
|
|
|
return (pin >> 5);
|
|
|
|
}
|
|
|
|
static inline int GPIO_NUM(int pin)
|
|
|
|
{
|
|
|
|
return (pin & 0x1F);
|
|
|
|
}
|
|
|
|
static inline int GPIO_CFG_INDEX(int pin)
|
|
|
|
{
|
|
|
|
return ((pin & 0x1F) >> 3);
|
|
|
|
}
|
|
|
|
static inline int GPIO_CFG_OFFSET(int pin)
|
|
|
|
{
|
|
|
|
return (((pin & 0x1F) & 0x7) << 2);
|
|
|
|
}
|
|
|
|
static inline int GPIO_PUL_INDEX(int pin)
|
|
|
|
{
|
|
|
|
return ((pin & 0x1F) >> 4);
|
|
|
|
}
|
|
|
|
static inline int GPIO_PUL_OFFSET(int pin)
|
|
|
|
{
|
|
|
|
return ((pin & 0x0F) << 1);
|
|
|
|
}
|
|
|
|
static inline int GPIO_DRV_INDEX(int pin)
|
|
|
|
{
|
|
|
|
return ((pin & 0x1F) >> 4);
|
|
|
|
}
|
|
|
|
static inline int GPIO_DRV_OFFSET(int pin)
|
|
|
|
{
|
|
|
|
return ((pin & 0x0F) << 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void short_wait(void)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 150; i++) {
|
|
|
|
#ifndef __arm__
|
|
|
|
// Timing doesn't really matter if we're not on ARM.
|
|
|
|
// The SunXI SoCs are all ARM-based.
|
|
|
|
const timespec ts = {.tv_sec = 0, .tv_nsec = 1};
|
|
|
|
nanosleep(&ts, nullptr);
|
|
|
|
#else
|
|
|
|
// wait 150 cycles
|
|
|
|
asm volatile("nop");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class gpio_configure_values_e : uint8_t {
|
|
|
|
gpio_input = 0b000,
|
|
|
|
gpio_output = 0b001,
|
|
|
|
gpio_alt_func_1 = 0b010,
|
|
|
|
gpio_alt_func_2 = 0b011,
|
|
|
|
gpio_reserved_1 = 0b100,
|
|
|
|
gpio_reserved_2 = 0b101,
|
|
|
|
gpio_interupt = 0b110,
|
|
|
|
gpio_disable = 0b111
|
|
|
|
};
|
|
|
|
|
|
|
|
struct sunxi_gpio {
|
|
|
|
unsigned int CFG[4]; // NOSONAR: Intentionally using C style arrays for low level register access
|
|
|
|
unsigned int DAT;
|
|
|
|
unsigned int DRV[2]; // NOSONAR: Intentionally using C style arrays for low level register access
|
|
|
|
unsigned int PULL[2]; // NOSONAR: Intentionally using C style arrays for low level register access
|
|
|
|
};
|
|
|
|
using sunxi_gpio_t = struct sunxi_gpio;
|
|
|
|
|
|
|
|
/* gpio interrupt control */
|
|
|
|
struct sunxi_gpio_int {
|
|
|
|
unsigned int CFG[3]; // NOSONAR: Intentionally using C style arrays for low level register access
|
|
|
|
unsigned int CTL;
|
|
|
|
unsigned int STA;
|
|
|
|
unsigned int DEB;
|
|
|
|
};
|
|
|
|
using sunxi_gpio_int_t = struct sunxi_gpio_int;
|
|
|
|
|
|
|
|
struct sunxi_gpio_reg {
|
|
|
|
struct sunxi_gpio gpio_bank[9]; // NOSONAR: Intentionally using C style arrays for low level register access
|
|
|
|
unsigned char res[0xbc]; // NOSONAR: Intentionally using C style arrays for low level register access
|
|
|
|
struct sunxi_gpio_int gpio_int;
|
|
|
|
};
|
|
|
|
using sunxi_gpio_reg_t = struct sunxi_gpio_reg;
|
|
|
|
|
|
|
|
static const uint32_t PAGE_SIZE = (4 * 1024);
|
|
|
|
static const uint32_t BLOCK_SIZE = (4 * 1024);
|
|
|
|
|
|
|
|
static const int SETUP_DEVMEM_FAIL = 1;
|
|
|
|
static const int SETUP_MALLOC_FAIL = 2;
|
|
|
|
static const int SETUP_MMAP_FAIL = 3;
|
|
|
|
static const int SETUP_CPUINFO_FAIL = 4;
|
|
|
|
static const int SETUP_NOT_RPI_FAIL = 5;
|
|
|
|
static const int INPUT = 1;
|
|
|
|
static const int OUTPUT = 0;
|
|
|
|
static const int ALT0 = 4;
|
|
|
|
static const int HIGH = 1;
|
|
|
|
static const int LOW = 0;
|
|
|
|
static const int PUD_OFF = 0;
|
|
|
|
static const int PUD_DOWN = 1;
|
|
|
|
static const int PUD_UP = 2;
|
|
|
|
|
|
|
|
static const uint32_t SUNXI_R_GPIO_BASE = 0x01F02000;
|
|
|
|
static const uint32_t SUNXI_R_GPIO_REG_OFFSET = 0xC00;
|
|
|
|
static const uint32_t SUNXI_GPIO_BASE = 0x01C20000;
|
|
|
|
static const uint32_t SUNXI_GPIO_REG_OFFSET = 0x800;
|
|
|
|
static const uint32_t SUNXI_CFG_OFFSET = 0x00;
|
|
|
|
static const uint32_t SUNXI_DATA_OFFSET = 0x10;
|
|
|
|
static const uint32_t SUNXI_PUD_OFFSET = 0x1C;
|
|
|
|
static const uint32_t SUNXI_BANK_SIZE = 0x24;
|
|
|
|
|
|
|
|
static const uint32_t MAP_SIZE = (4096 * 2);
|
|
|
|
static const uint32_t MAP_MASK = (MAP_SIZE - 1);
|
|
|
|
|
|
|
|
static const int FSEL_OFFSET = 0; // 0x0000
|
|
|
|
static const int SET_OFFSET = 7; // 0x001c / 4
|
|
|
|
static const int CLR_OFFSET = 10; // 0x0028 / 4
|
|
|
|
static const int PINLEVEL_OFFSET = 13; // 0x0034 / 4
|
|
|
|
static const int EVENT_DETECT_OFFSET = 16; // 0x0040 / 4
|
|
|
|
static const int RISING_ED_OFFSET = 19; // 0x004c / 4
|
|
|
|
static const int FALLING_ED_OFFSET = 22; // 0x0058 / 4
|
|
|
|
static const int HIGH_DETECT_OFFSET = 25; // 0x0064 / 4
|
|
|
|
static const int LOW_DETECT_OFFSET = 28; // 0x0070 / 4
|
|
|
|
static const int PULLUPDN_OFFSET = 37; // 0x0094 / 4
|
|
|
|
static const int PULLUPDNCLK_OFFSET = 38; // 0x0098 / 4
|
|
|
|
|
|
|
|
static const uint32_t TMR_REGISTER_BASE = 0x01C20C00;
|
|
|
|
static const uint32_t TMR_IRQ_EN_REG = 0x0; // T imer IRQ Enable Register
|
|
|
|
static const uint32_t TMR_IRQ_STA_REG = 0x4; // Timer Status Register
|
|
|
|
static const uint32_t TMR0_CTRL_REG = 0x10; // Timer 0 Control Register
|
|
|
|
static const uint32_t TMR0_INTV_VALUE_REG = 0x14; // Timer 0 Interval Value Register
|
|
|
|
static const uint32_t TMR0_CUR_VALUE_REG = 0x18; // Timer 0 Current Value Register
|
|
|
|
static const uint32_t TMR1_CTRL_REG = 0x20; // Timer 1 Control Register
|
|
|
|
static const uint32_t TMR1_INTV_VALUE_REG = 0x24; // Timer 1 Interval Value Register
|
|
|
|
static const uint32_t TMR1_CUR_VALUE_REG = 0x28; // Timer 1 Current Value Register
|
|
|
|
static const uint32_t AVS_CNT_CTL_REG = 0x80; // AVS Control Register
|
|
|
|
static const uint32_t AVS_CNT0_REG = 0x84; // AVS Counter 0 Register
|
|
|
|
static const uint32_t AVS_CNT1_REG = 0x88; // AVS Counter 1 Register
|
|
|
|
static const uint32_t AVS_CNT_DIV_REG = 0x8C; // AVS Divisor Register
|
|
|
|
static const uint32_t WDOG0_IRQ_EN_REG = 0xA0; // Watchdog 0 IRQ Enable Register
|
|
|
|
static const uint32_t WDOG0_IRQ_STA_REG = 0xA4; // Watchdog 0 Status Register
|
|
|
|
static const uint32_t WDOG0_CTRL_REG = 0xB0; // Watchdog 0 Control Register
|
|
|
|
static const uint32_t WDOG0_CFG_REG = 0xB4; // Watchdog 0 Configuration Register
|
|
|
|
static const uint32_t WDOG0_MODE_REG = 0xB8; // Watchdog 0 Mode Register
|
|
|
|
};
|