From e94695fd9483d2c969c178cdb23b444bf056ebfd Mon Sep 17 00:00:00 2001 From: Deokgyu Yang Date: Fri, 13 Nov 2020 12:56:17 +0900 Subject: [PATCH] WiringPi: Add support for Odroid-HC4 Signed-off-by: Deokgyu Yang Change-Id: If64c712eef681a2a9aa4b7828d95b612a1de91db --- gpio/gpio.c | 1 + gpio/readall.c | 155 ++++++++++- wiringPi/Makefile | 4 +- wiringPi/odroidc4.h | 1 + wiringPi/odroidhc4.c | 577 +++++++++++++++++++++++++++++++++++++++++ wiringPi/wiringPi.c | 9 + wiringPi/wiringPi.h | 1 + wiringPi/wiringPiI2C.c | 1 + wiringPi/wiringPiSPI.c | 9 +- 9 files changed, 749 insertions(+), 9 deletions(-) create mode 100644 wiringPi/odroidhc4.c diff --git a/gpio/gpio.c b/gpio/gpio.c index b2f5b0f..b1f60a0 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -220,6 +220,7 @@ static void doI2Cdetect (UNU int argc, char *argv []) break; case MODEL_ODROID_N2: case MODEL_ODROID_C4: + case MODEL_ODROID_HC4: if (cmpKernelVersion(KERN_NUM_TO_REVISION, 4, 9, 230)) port = 0; else diff --git a/gpio/readall.c b/gpio/readall.c index 462a22f..db9c764 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -109,6 +109,15 @@ static const int physToWpi [64] = -1, -1, -1, -1, -1, -1, -1, -1, -1 } ; +/*----------------------------------------------------------------------------*/ +static const int physToWpiHC4 [64] = +{ + -1, // 0 + -1, 0, // 1, 2 + 1, 2, + -1, +} ; + /*----------------------------------------------------------------------------*/ static const char *physNamesOdroidC1All [64] = { @@ -543,6 +552,44 @@ static const char *physNamesOdroidC4 [64] = NULL,NULL,NULL, }; +/*----------------------------------------------------------------------------*/ +static const char *physNamesOdroidHC4All [64] = +{ + NULL, + + " 3.3V", + " SDA.2", + " SCL.2", + "GPIO.481", + " 0V", + + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, +}; + +/*----------------------------------------------------------------------------*/ +static const char *physNamesOdroidHC4 [64] = +{ + NULL, + + " 3.3V", + " SDA.2", + " SCL.2", + " IO.481", + " 0V", + + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, +}; + /*----------------------------------------------------------------------------*/ static void readallPhys(int model, int UNU rev, int physPin, const char *physNames[], int isAll) { int pin ; @@ -670,7 +717,6 @@ static void readallPhys(int model, int UNU rev, int physPin, const char *physNam printf (" |\n") ; } -/*----------------------------------------------------------------------------*/ static void printHeader(const char *headerName, int isAll) { const char *headerLeft = " +-----+-----+---------+------+---+"; const char *headerRight = "+---+------+---------+-----+-----+\n"; @@ -702,6 +748,94 @@ static void printBody(int model, int rev, const char *physNames[], int isAll) { " | GPIO | wPi | Name | Mode | V | DS | PU/PD | Physical | PU/PD | DS | V | Mode | Name | wPi | GPIO |\n"); } +/*----------------------------------------------------------------------------*/ +static void readallPhysHC4(int model, int UNU rev, int physPin, const char *physNames[], int isAll) { + int pin ; + + // GPIO, wPi pin number + if (isAll == TRUE) { + if ((physPinToGpio (physPin) == -1) && (physToWpiHC4 [physPin] == -1)) + printf(" | | "); + else if (physPinToGpio (physPin) != -1) { + printf(" | %3d | %3d", physPinToGpio(physPin), physToWpiHC4[physPin]); + } else + printf(" | | %3d", physToWpiHC4 [physPin]); + } else { + if ((physPinToGpio (physPin) == -1) && (physToWpiHC4 [physPin] == -1)) + printf(" | | "); + else if (physPinToGpio (physPin) != -1) { + printf(" | %3d | %3d", physPinToGpio(physPin), physToWpiHC4[physPin]); + } else + printf(" | | %3d", physToWpiHC4 [physPin]); + } + + // GPIO pin name + printf (" | %s", physNames [physPin]) ; + + // GPIO pin mode, value + if ((physToWpiHC4 [physPin] == -1) || (physPinToGpio (physPin) == -1)) { + printf(" | | "); + if (isAll == TRUE) + printf(" | | "); + } else { + if (wpMode == MODE_GPIO) + pin = physPinToGpio (physPin); + else if (wpMode == MODE_PHYS) + pin = physPin ; + else + pin = physToWpiHC4 [physPin]; + + printf (" | %4s", alts [getAlt (pin)]) ; + printf (" | %d", digitalRead (pin)) ; + + // GPIO pin drive strength, pu/pd + if (isAll == TRUE) { + switch (model) { + case MODEL_ODROID_HC4: + printf (" | %2d | %5s", getDrive(pin), pupd[getPUPD(pin)]); + break; + default: + break; + } + } + } + + // Physical pin number + printf(" | %2d |\n", physPin); +} + +/*----------------------------------------------------------------------------*/ +static void printHeaderHC4(const char *headerName, int isAll) { + const char *header = " +-----+-----+---------+------+---+-----+"; + const char *headerAll = " +------+-----+----------+------+---+----+-------+-----+"; + + (isAll == FALSE) ? printf("%s\n", header) : printf("%s\n", headerAll); + (isAll == FALSE) + ? printf(" | %s |\n", headerName) + : printf(" | %s |\n", headerName); + (isAll == FALSE) ? printf("%s\n", header) : printf("%s\n", headerAll); +} + +/*----------------------------------------------------------------------------*/ +static void printBodyHC4(int model, int rev, const char *physNames[], int isAll) { + (isAll == FALSE) + ? printf( + " | I/O | wPi | Name | Mode | V | Phy |\n" + " +-----+-----+---------+------+---+-----+\n") + : printf( + " | GPIO | wPi | Name | Mode | V | DS | PU/PD | Phy |\n" + " +------+-----+----------+------+---+----+-------+-----+\n"); + for (int pin = 1; pin <= 5; pin ++) + readallPhysHC4(model, rev, pin, physNames, isAll); + (isAll == FALSE) + ? printf( + " +-----+-----+---------+------+---+-----+\n" + " | I/O | wPi | Name | Mode | V | Phy |\n") + : printf( + " +------+-----+----------+------+---+----+-------+-----+\n" + " | GPIO | wPi | Name | Mode | V | DS | PU/PD | Phy |\n"); +} + /*----------------------------------------------------------------------------*/ /* * doReadall: @@ -764,14 +898,27 @@ void doReadall(int argc, char *argv[]) { headerName = (isAll == FALSE) ? "--- C4 ---" : "---- Model ODROID-C4 ----"; physNames = (char *) ((isAll == FALSE) ? physNamesOdroidC4 : physNamesOdroidC4All); break; + case MODEL_ODROID_HC4: + headerName = (isAll == FALSE) ? " HC4 " : " Model ODROID-HC4 "; + physNames = (char *) ((isAll == FALSE) ? physNamesOdroidHC4 : physNamesOdroidHC4All); + break; default: printf("Oops - unknown model: %d\n", model); return; } - printHeader((const char *) headerName, isAll); - printBody(model, rev, (const char **) physNames, isAll); - printHeader((const char *) headerName, isAll); + switch (model) { + case MODEL_ODROID_HC4: + printHeaderHC4((const char *) headerName, isAll); + printBodyHC4(model, rev, (const char **) physNames, isAll); + printHeaderHC4((const char *) headerName, isAll); + break; + default: + printHeader((const char *) headerName, isAll); + printBody(model, rev, (const char **) physNames, isAll); + printHeader((const char *) headerName, isAll); + break; + } } /*----------------------------------------------------------------------------*/ diff --git a/wiringPi/Makefile b/wiringPi/Makefile index 2598a4c..3031a30 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -68,7 +68,8 @@ SRC = wiringPi.c \ odroidxu3.c \ odroidn1.c \ odroidn2.c \ - odroidc4.c + odroidc4.c \ + odroidhc4.c HEADERS = $(shell ls *.h) @@ -182,3 +183,4 @@ odroidxu3.o : wiringPi.h odroidxu3.h odroidn1.o : wiringPi.h odroidn1.h odroidn2.o : wiringPi.h odroidn2.h odroidc4.o : wiringPi.h odroidc4.h +odroidhc4.o : wiringPi.h odroidc4.h diff --git a/wiringPi/odroidc4.h b/wiringPi/odroidc4.h index bb43962..77ee6c5 100644 --- a/wiringPi/odroidc4.h +++ b/wiringPi/odroidc4.h @@ -54,6 +54,7 @@ extern "C" { #endif extern void init_odroidc4 (struct libodroid *libwiring); +extern void init_odroidhc4 (struct libodroid *libwiring); #ifdef __cplusplus } diff --git a/wiringPi/odroidhc4.c b/wiringPi/odroidhc4.c new file mode 100644 index 0000000..ea714c7 --- /dev/null +++ b/wiringPi/odroidhc4.c @@ -0,0 +1,577 @@ +/*----------------------------------------------------------------------------*/ +// +// +// WiringPi ODROID-C4 Board Control file (AMLogic 64Bits Platform) +// +// +/*----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------------*/ +#include "softPwm.h" +#include "softTone.h" + +/*----------------------------------------------------------------------------*/ +#include "wiringPi.h" +#include "odroidc4.h" + +/*----------------------------------------------------------------------------*/ +// wiringPi gpio map define +/*----------------------------------------------------------------------------*/ +static const int pinToGpio[64] = { + // wiringPi number to native gpio number + 493, 494, // 0 | 1 : GPIOX.17(I2C-2_SDA), GPIOX.18(I2C-2_SCL) + 481, -1, // 2 | 3 : , GPIOX.5 + -1, -1, // 4 | 5 : + -1, -1, // 6 | 7 : + -1, -1, // 8 | 9 : + -1, -1, // 10 | 11 : + -1, -1, // 12 | 13 : + -1, -1, // 14 | 15 : + -1, -1, // 16 | 17 : + -1, -1, // 18 | 19 : + -1, -1, // 20 | 21 : + -1, -1, // 22 | 23 : + -1, -1, // 24 | 25 : + -1, -1, // 26 | 27 : + -1, -1, // 28 | 29 : + -1, -1, // 30 | 31 : + // Padding: + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32...47 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48...63 +}; + +static const int phyToGpio[64] = { + // physical header pin number to native gpio number + -1, // 0 + -1, 493, // 1 | 2 : 3.3V, GPIOX.17(I2C-2_SDA) + 494, 481, // 3 | 4 : GPIOX.18(I2C-2_SCL), GPIOX.5 + -1, -1, // 5 | 6 : GND, + -1, -1, // 7 | 8 : + -1, -1, // 9 | 10 : + -1, -1, // 11 | 12 : + -1, -1, // 13 | 14 : + -1, -1, // 15 | 16 : + -1, -1, // 17 | 18 : + -1, -1, // 19 | 20 : + -1, -1, // 21 | 22 : + -1, -1, // 23 | 24 : + -1, -1, // 25 | 26 : + -1, -1, // 27 | 28 : + -1, -1, // 29 | 30 : + -1, -1, // 31 | 32 : + -1, -1, // 33 | 34 : + -1, -1, // 35 | 36 : + -1, -1, // 37 | 38 : + -1, -1, // 39 | 40 : + // Not used + -1, -1, -1, -1, -1, -1, -1, -1, // 41...48 + -1, -1, -1, -1, -1, -1, -1, -1, // 49...56 + -1, -1, -1, -1, -1, -1, -1 // 57...63 +}; + +/*----------------------------------------------------------------------------*/ +// +// Global variable define +// +/*----------------------------------------------------------------------------*/ +// wiringPi Pinmap control arrary +/*----------------------------------------------------------------------------*/ +/* GPIO mmap control */ +static volatile uint32_t *gpio; + +/* wiringPi Global library */ +static struct libodroid *lib = NULL; + +/*----------------------------------------------------------------------------*/ +// Function prototype define +/*----------------------------------------------------------------------------*/ +static int gpioToGPSETReg (int pin); +static int gpioToGPLEVReg (int pin); +static int gpioToPUENReg (int pin); +static int gpioToPUPDReg (int pin); +static int gpioToShiftReg (int pin); +static int gpioToGPFSELReg (int pin); +static int gpioToDSReg (int pin); +static int gpioToMuxReg (int pin); + +/*----------------------------------------------------------------------------*/ +// wiringPi core function +/*----------------------------------------------------------------------------*/ +static int _getModeToGpio (int mode, int pin); +static int _setDrive (int pin, int value); +static int _getDrive (int pin); +static int _pinMode (int pin, int mode); +static int _getAlt (int pin); +static int _getPUPD (int pin); +static int _pullUpDnControl (int pin, int pud); +static int _digitalRead (int pin); +static int _digitalWrite (int pin, int value); + +/*----------------------------------------------------------------------------*/ +// board init function +/*----------------------------------------------------------------------------*/ +static void init_gpio_mmap (void); + + void init_odroidhc4 (struct libodroid *libwiring); + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Set regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToGPSETReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_OUTP_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_OUTP_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_OUTP_REG_OFFSET; + return -1; +} + +/*---------------------------------------------------------------------------r-*/ +// +// offset to the GPIO Input regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToGPLEVReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_INP_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_INP_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_INP_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pull up/down enable regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToPUENReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_PUEN_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_PUEN_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_PUEN_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pull up/down regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToPUPDReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_PUPD_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_PUPD_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_PUPD_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO bit +// +/*----------------------------------------------------------------------------*/ +static int gpioToShiftReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return pin - C4_GPIOH_PIN_START; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return pin - C4_GPIOA_PIN_START; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return pin - C4_GPIOX_PIN_START; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Function register +// +/*----------------------------------------------------------------------------*/ +static int gpioToGPFSELReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_FSEL_REG_OFFSET; + if(pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_FSEL_REG_OFFSET; + if(pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_FSEL_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Drive Strength register +// +/*----------------------------------------------------------------------------*/ +static int gpioToDSReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_DS_REG_3A_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_DS_REG_5A_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_MID) + return C4_GPIOX_DS_REG_2A_OFFSET; + if (pin > C4_GPIOX_PIN_MID && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_DS_REG_2B_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pin Mux register +// +/*----------------------------------------------------------------------------*/ +static int gpioToMuxReg (int pin) +{ + switch (pin) { + case C4_GPIOH_PIN_START ...C4_GPIOH_PIN_END: + return C4_GPIOH_MUX_B_REG_OFFSET; + case C4_GPIOA_PIN_START ...C4_GPIOA_PIN_START + 7: + return C4_GPIOA_MUX_D_REG_OFFSET; + case C4_GPIOA_PIN_START + 8 ...C4_GPIOA_PIN_END: + return C4_GPIOA_MUX_E_REG_OFFSET; + case C4_GPIOX_PIN_START ...C4_GPIOX_PIN_START + 7: + return C4_GPIOX_MUX_3_REG_OFFSET; + case C4_GPIOX_PIN_START + 8 ...C4_GPIOX_PIN_START + 15: + return C4_GPIOX_MUX_4_REG_OFFSET; + case C4_GPIOX_PIN_START + 16 ...C4_GPIOX_PIN_END: + return C4_GPIOX_MUX_5_REG_OFFSET; + default: + return -1; + } +} + +/*----------------------------------------------------------------------------*/ +static int _getModeToGpio (int mode, int pin) +{ + int retPin = -1; + + switch (mode) { + /* Native gpio number */ + case MODE_GPIO: + retPin = pin; + break; + /* Native gpio number for sysfs */ + case MODE_GPIO_SYS: + retPin = lib->sysFds[pin] != -1 ? pin : -1; + break; + /* wiringPi number */ + case MODE_PINS: + retPin = pin < 64 ? pinToGpio[pin] : -1; + break; + /* header pin number */ + case MODE_PHYS: + retPin = pin < 64 ? phyToGpio[pin] : -1; + break; + default : + msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode); + return -1; + } + + return retPin; +} + +/*----------------------------------------------------------------------------*/ +static int _setDrive (int pin, int value) +{ + int ds, shift; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + if (value < 0 || value > 3) { + msg(MSG_WARN, "%s : Invalid value %d (Must be 0 ~ 3)\n", __func__, value); + return -1; + } + + ds = gpioToDSReg(pin); + shift = gpioToShiftReg(pin); + shift = pin > C4_GPIOX_PIN_MID ? (shift - 16) * 2 : shift * 2; + + *(gpio + ds) &= ~(0b11 << shift); + *(gpio + ds) |= (value << shift); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _getDrive (int pin) +{ + int ds, shift; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + ds = gpioToDSReg(pin); + shift = gpioToShiftReg(pin); + shift = pin > C4_GPIOX_PIN_MID ? (shift - 16) * 2 : shift * 2; + + return (*(gpio + ds) >> shift) & 0b11; +} + +/*----------------------------------------------------------------------------*/ +static int _pinMode (int pin, int mode) +{ + int fsel, shift, origPin = pin; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + softPwmStop (origPin); + softToneStop (origPin); + + fsel = gpioToGPFSELReg(pin); + shift = gpioToShiftReg (pin); + + switch (mode) { + case INPUT: + *(gpio + fsel) = (*(gpio + fsel) | (1 << shift)); + break; + case OUTPUT: + *(gpio + fsel) = (*(gpio + fsel) & ~(1 << shift)); + break; + case SOFT_PWM_OUTPUT: + softPwmCreate (pin, 0, 100); + break; + case SOFT_TONE_OUTPUT: + softToneCreate (pin); + break; + default: + msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _getAlt (int pin) +{ + int fsel, mux, shift, target, mode; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + fsel = gpioToGPFSELReg(pin); + mux = gpioToMuxReg(pin); + target = shift = gpioToShiftReg(pin); + + while (target >= 8) { + target -= 8; + } + + mode = (*(gpio + mux) >> (target * 4)) & 0xF; + return mode ? mode + 1 : (*(gpio + fsel) & (1 << shift)) ? 0 : 1; +} + +/*----------------------------------------------------------------------------*/ +static int _getPUPD (int pin) +{ + int puen, pupd, shift; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + puen = gpioToPUENReg(pin); + pupd = gpioToPUPDReg(pin); + shift = gpioToShiftReg(pin); + + if (*(gpio + puen) & (1 << shift)) + return *(gpio + pupd) & (1 << shift) ? 1 : 2; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _pullUpDnControl (int pin, int pud) +{ + int shift = 0; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + shift = gpioToShiftReg(pin); + + if (pud) { + // Enable Pull/Pull-down resister + *(gpio + gpioToPUENReg(pin)) = + (*(gpio + gpioToPUENReg(pin)) | (1 << shift)); + + if (pud == PUD_UP) + *(gpio + gpioToPUPDReg(pin)) = + (*(gpio + gpioToPUPDReg(pin)) | (1 << shift)); + else + *(gpio + gpioToPUPDReg(pin)) = + (*(gpio + gpioToPUPDReg(pin)) & ~(1 << shift)); + } else // Disable Pull/Pull-down resister + *(gpio + gpioToPUENReg(pin)) = + (*(gpio + gpioToPUENReg(pin)) & ~(1 << shift)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _digitalRead (int pin) +{ + char c ; + + if (lib->mode == MODE_GPIO_SYS) { + if (lib->sysFds[pin] == -1) + return -1; + + lseek (lib->sysFds[pin], 0L, SEEK_SET); + if (read(lib->sysFds[pin], &c, 1) < 0) { + msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__); + return -1; + } + + return (c == '0') ? LOW : HIGH; + } + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + if ((*(gpio + gpioToGPLEVReg(pin)) & (1 << gpioToShiftReg(pin))) != 0) + return HIGH ; + else + return LOW ; +} + +/*----------------------------------------------------------------------------*/ +static int _digitalWrite (int pin, int value) +{ + if (lib->mode == MODE_GPIO_SYS) { + if (lib->sysFds[pin] != -1) { + if (value == LOW) { + if (write(lib->sysFds[pin], "0\n", 2) < 0) + msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__); + } else { + if (write(lib->sysFds[pin], "1\n", 2) < 0) + msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__); + } + } + return -1; + } + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + if (value == LOW) + *(gpio + gpioToGPSETReg(pin)) &= ~(1 << gpioToShiftReg(pin)); + else + *(gpio + gpioToGPSETReg(pin)) |= (1 << gpioToShiftReg(pin)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static void init_gpio_mmap (void) +{ + int fd = -1; + void *mapped; + + /* GPIO mmap setup */ + if (!getuid()) { + if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) + msg (MSG_ERR, + "wiringPiSetup: Unable to open /dev/mem: %s\n", + strerror (errno)); + } else { + if (access("/dev/gpiomem",0) == 0) { + if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) + msg (MSG_ERR, + "wiringPiSetup: Unable to open /dev/gpiomem: %s\n", + strerror (errno)); + setUsingGpiomem(TRUE); + } else + msg (MSG_ERR, + "wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n"); + } + + if (fd < 0) { + msg(MSG_ERR, "wiringPiSetup: Cannot open memory area for GPIO use. \n"); + } else { + // #define C4_GPIO_BASE 0xff634000 +#ifdef ANDROID +#if defined(__aarch64__) + mapped = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, C4_GPIO_BASE); +#else + mapped = mmap64(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off64_t)C4_GPIO_BASE); +#endif +#else + mapped = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, C4_GPIO_BASE); +#endif + + if (mapped == MAP_FAILED) + msg(MSG_ERR, "wiringPiSetup: mmap (GPIO) failed: %s \n", strerror (errno)); + else + gpio = (uint32_t *) mapped; + } +} + +/*----------------------------------------------------------------------------*/ +void init_odroidhc4 (struct libodroid *libwiring) +{ + init_gpio_mmap(); + + /* wiringPi Core function initialize */ + libwiring->getModeToGpio = _getModeToGpio; + libwiring->setDrive = _setDrive; + libwiring->getDrive = _getDrive; + libwiring->pinMode = _pinMode; + libwiring->getAlt = _getAlt; + libwiring->getPUPD = _getPUPD; + libwiring->pullUpDnControl = _pullUpDnControl; + libwiring->digitalRead = _digitalRead; + libwiring->digitalWrite = _digitalWrite; + + /* specify pin base number */ + libwiring->pinBase = C4_GPIO_PIN_BASE; + + /* global variable setup */ + lib = libwiring; +} + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 768298a..29bc162 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -60,6 +60,7 @@ const char *piModelNames [16] = "ODROID-N1", "ODROID-N2/N2Plus", "ODROID-C4", + "ODROID-HC4", }; const char *piRevisionNames [16] = @@ -501,6 +502,11 @@ int piGpioLayout (void) { libwiring.mem = 4; libwiring.rev = 1; break; + case MODEL_ODROID_HC4: + libwiring.maker = MAKER_AMLOGIC; + libwiring.mem = 4; + libwiring.rev = 1; + break; case MODEL_UNKNOWN: default: libwiring.model = MAKER_UNKNOWN; @@ -1208,6 +1214,9 @@ int wiringPiSetup (void) case MODEL_ODROID_C4: init_odroidc4(&libwiring); break; + case MODEL_ODROID_HC4: + init_odroidhc4(&libwiring); + break; default: return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unknown model\n"); diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index e02778b..0f72ec7 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -59,6 +59,7 @@ #define MODEL_ODROID_N1 4 #define MODEL_ODROID_N2 5 #define MODEL_ODROID_C4 6 +#define MODEL_ODROID_HC4 7 #define MAKER_UNKNOWN 0 #define MAKER_AMLOGIC 1 diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c index bb948fa..43161d7 100644 --- a/wiringPi/wiringPiI2C.c +++ b/wiringPi/wiringPiI2C.c @@ -260,6 +260,7 @@ int wiringPiI2CSetup (const int devId) break; case MODEL_ODROID_N2: case MODEL_ODROID_C4: + case MODEL_ODROID_HC4: if (cmpKernelVersion(KERN_NUM_TO_REVISION, 4, 9, 230)) device = "/dev/i2c-0"; else diff --git a/wiringPi/wiringPiSPI.c b/wiringPi/wiringPiSPI.c index e860ed6..e2122bb 100644 --- a/wiringPi/wiringPiSPI.c +++ b/wiringPi/wiringPiSPI.c @@ -138,12 +138,13 @@ int wiringPiSPISetupMode (int channel, int speed, int mode) piBoardId (&model, &temp, &temp, &temp, &temp) ; - if (model == MODEL_ODROID_C2) { + switch(model) { + case MODEL_ODROID_C2: return wiringPiFailure (WPI_ALMOST, "ODROID C2 does not support hardware SPI. Check out the SPI bitbang and use wiringPiSPISetupInterface.\n"); - } - - switch(model) { + case MODEL_ODROID_HC4: + return wiringPiFailure (WPI_ALMOST, + "ODROID HC4 does not support hardware SPI.\n"); case MODEL_ODROID_C1: case MODEL_ODROID_N2: case MODEL_ODROID_C4: