WiringPi: Add support for Odroid-HC4
Signed-off-by: Deokgyu Yang <secugyu@gmail.com> Change-Id: If64c712eef681a2a9aa4b7828d95b612a1de91db
This commit is contained in:
@@ -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
|
||||
|
||||
155
gpio/readall.c
155
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -54,6 +54,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern void init_odroidc4 (struct libodroid *libwiring);
|
||||
extern void init_odroidhc4 (struct libodroid *libwiring);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
577
wiringPi/odroidhc4.c
Normal file
577
wiringPi/odroidhc4.c
Normal file
@@ -0,0 +1,577 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
//
|
||||
//
|
||||
// WiringPi ODROID-C4 Board Control file (AMLogic 64Bits Platform)
|
||||
//
|
||||
//
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <asm/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#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;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user