From 827072123bf033418447b99556f3c51414cc2f73 Mon Sep 17 00:00:00 2001 From: joshua-yang Date: Mon, 7 Jan 2019 12:28:15 +0900 Subject: [PATCH] ODROID-N2: Implement get pin MUX, PU/PD mode, get/set drive strength Change-Id: I75099b4e2919860f7190ef9cdcd841b1d38844a7 --- gpio/gpio_odroid.c | 25 +++----- gpio/readall_odroid.c | 42 +++++++++----- wiringPi/odroidn2.c | 123 +++++++++++++++++++++++++++++++++++++++- wiringPi/odroidn2.h | 17 ++++-- wiringPi/wiringOdroid.c | 44 +++++++++++++- wiringPi/wiringOdroid.h | 3 + 6 files changed, 215 insertions(+), 39 deletions(-) diff --git a/gpio/gpio_odroid.c b/gpio/gpio_odroid.c index 72b9006..916dbfa 100755 --- a/gpio/gpio_odroid.c +++ b/gpio/gpio_odroid.c @@ -72,7 +72,7 @@ char *usage = "Usage: gpio -v\n" " gpio unexportall/exports\n" " gpio export/edge/unexport ...\n" " gpio wfi \n" - " gpio drive \n" + " gpio drive \n" " gpio pwm-bal/pwm-ms \n" " gpio pwmr \n" " gpio pwmc \n" @@ -598,32 +598,23 @@ void doMode (int argc, char *argv []) /* * doPadDrive: - * gpio drive group value + * gpio drive pin value for ODROIDs since it depends on the SoC ********************************************************************************* */ static void doPadDrive (int argc, char *argv []) { - int group, val ; + int pin, val; if (argc != 4) { - fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ; + fprintf (stderr, "Usage: %s drive pin value\n", argv [0]) ; exit (1) ; } - group = atoi (argv [2]) ; - val = atoi (argv [3]) ; + pin = atoi (argv [2]) ; + val = atoi (argv [3]) ; - if ((group < 0) || (group > 2)) { - fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ; - exit (1) ; - } - - if ((val < 0) || (val > 7)) { - fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ; - exit (1) ; - } - setPadDrive (group, val) ; + setPadDrive (pin, val) ; } @@ -1214,7 +1205,7 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "pwmr" ) == 0) doNothing (argc, argv) ; else if (strcasecmp (argv [1], "pwmc" ) == 0) doNothing (argc, argv) ; else if (strcasecmp (argv [1], "pwmTone" ) == 0) doNothing (argc, argv) ; - else if (strcasecmp (argv [1], "drive" ) == 0) doNothing (argc, argv) ; + else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ; diff --git a/gpio/readall_odroid.c b/gpio/readall_odroid.c index 40583f0..f91be95 100755 --- a/gpio/readall_odroid.c +++ b/gpio/readall_odroid.c @@ -67,11 +67,16 @@ static void doReadallExternal (void) /*----------------------------------------------------------------------------*/ static const char *alts [] = { - "IN", "OUT", "ALT" + "IN", "OUT", "ALT1", "ALT2", "ALT3", "ALT4", "ALT5", "ALT6", "ALT7" +} ; + +static const char *pupd [] = +{ + "DSBLD", "P/U", "P/D" } ; /*----------------------------------------------------------------------------*/ -static const int physToWpi [64] = +static const int physToWpi [64] = { -1, // 0 -1, -1, // 1, 2 @@ -295,6 +300,7 @@ static void readallPhysOdroid (int model, int rev, int physPin, const char *phys { int pin ; + // GPIO, wPi pin number if ((physPinToGpio (physPin) == -1) && (physToWpi [physPin] == -1)) printf (" | | ") ; else if (physPinToGpio (physPin) != -1) @@ -302,10 +308,12 @@ static void readallPhysOdroid (int model, int rev, int physPin, const char *phys else printf (" | | %3d", physToWpi [physPin]); + // GPIO pin name printf (" | %s", physNames [physPin]) ; + // GPIO pin mode, value, drive strength, pupd if ((physToWpi [physPin] == -1) || (physPinToGpio (physPin) == -1)) - printf (" | | ") ; + printf (" | | | | ") ; else { if (wpMode == MODE_GPIO) pin = physPinToGpio (physPin); @@ -316,16 +324,18 @@ static void readallPhysOdroid (int model, int rev, int physPin, const char *phys printf (" | %4s", alts [getAlt (pin)]) ; printf (" | %d", digitalRead (pin)) ; + printf (" | %2d", getPadDrive (pin)) ; + printf (" | %5s", pupd [getPUPD (pin)]); } - // Pin numbers: + // Physical pin number printf (" | %2d", physPin) ; ++physPin ; printf (" || %-2d", physPin) ; - // Same, reversed + // GPIO pin mode, value, drive strength, pupd if ((physToWpi [physPin] == -1) || (physPinToGpio (physPin) == -1)) - printf (" | | ") ; + printf (" | | | | ") ; else { if (wpMode == MODE_GPIO) pin = physPinToGpio (physPin); @@ -334,12 +344,16 @@ static void readallPhysOdroid (int model, int rev, int physPin, const char *phys else pin = physToWpi [physPin]; + printf (" | %-5s", pupd [getPUPD (pin)]); + printf (" | %-2d", getPadDrive (pin)) ; printf (" | %d", digitalRead (pin)); printf (" | %-4s", alts [getAlt (pin)]); } + // GPIO pin name printf (" | %-6s", physNames [physPin]); + // GPIO, wPi pin number if ((physPinToGpio (physPin) == -1) && (physToWpi [physPin] == -1)) printf (" | | ") ; else if (physPinToGpio (physPin) != -1) @@ -355,11 +369,11 @@ void ReadallOdroid (int model, int rev, const char *physNames[]) { int pin ; - printf (" | GPIO | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | GPIO |\n") ; - printf (" +------+-----+----------+------+---+----++----+---+------+----------+-----+------+\n") ; + printf (" | GPIO | wPi | Name | Mode | V | DS | PU/PD | Physical | PU/PD | DS | V | Mode | Name | wPi | GPIO |\n") ; + printf (" +------+-----+----------+------+---+----+-------+----++----+-------+----+---+------+----------+-----+------+\n") ; for (pin = 1 ; pin <= 40 ; pin += 2) readallPhysOdroid (model, rev, pin, physNames) ; - printf (" +------+-----+----------+------+---+----++----+---+------+----------+-----+------+\n") ; + printf (" +------+-----+----------+------+---+----+-------+----++----+-------+----+---+------+----------+-----+------+\n") ; } /*----------------------------------------------------------------------------*/ @@ -387,26 +401,26 @@ void doReadall (void) switch (model) { case MODEL_ODROID_C1: - printf (" +------+-----+----------+------+- Model ODROID-C -+------+----------+-----+------+\n") ; + printf (" +------+-----+----------+------+---+----+---- Model ODROID-C1 ----+----+---+------+----------+-----+------+\n") ; physNames = physNamesOdroidC1; break; case MODEL_ODROID_C2: - printf (" +------+-----+----------+------+ Model ODROID-C2 +------+----------+-----+------+\n") ; + printf (" +------+-----+----------+------+---+----+---- Model ODROID-C2 ----+----+---+------+----------+-----+------+\n") ; if (rev == 1) physNames = physNamesOdroidC2_Rev1; else physNames = physNamesOdroidC2_Rev2; break; case MODEL_ODROID_XU3: - printf (" +------+-----+----------+------ Model ODROID-XU3/4 ------+----------+-----+------+\n") ; + printf (" +------+-----+----------+------+---+----+--- Model ODROID-XU3/4 ---+----+---+------+----------+-----+------+\n") ; physNames = physNamesOdroidXU3; break; case MODEL_ODROID_N1: - printf (" +------+-----+----------+------+ Model ODROID-N1 +------+----------+-----+------+\n") ; + printf (" +------+-----+----------+------+---+----+---- Model ODROID-N1 ----+----+---+------+----------+-----+------+\n") ; physNames = physNamesOdroidN1; break; case MODEL_ODROID_N2: - printf (" +------+-----+----------+------+ Model ODROID-N2 +------+----------+-----+------+\n") ; + printf (" +------+-----+----------+------+---+----+---- Model ODROID-N2 ----+----+---+------+----------+-----+------+\n") ; physNames = physNamesOdroidN2; break; default: diff --git a/wiringPi/odroidn2.c b/wiringPi/odroidn2.c index 8f326ef..b22db26 100755 --- a/wiringPi/odroidn2.c +++ b/wiringPi/odroidn2.c @@ -106,13 +106,18 @@ 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 void setPadDrive (int pin, int value); +static int getPadDrive (int pin); static void pinMode (int pin, int mode); static int getAlt (int pin); +static int getPUPD (int pin); static void pullUpDnControl (int pin, int pud); static int digitalRead (int pin); static void digitalWrite (int pin, int value); @@ -212,6 +217,46 @@ static int gpioToGPFSELReg (int pin) return N2_GPIOA_FSEL_REG_OFFSET; return -1; } + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Drive Strength register +// +/*----------------------------------------------------------------------------*/ +static int gpioToDSReg (int pin) +{ + if (pin >= N2_GPIOX_PIN_START && pin <= N2_GPIOX_PIN_MID) + return N2_GPIOX_DS_REG_2A_OFFSET; + if (pin > N2_GPIOX_PIN_MID && pin <= N2_GPIOX_PIN_END) + return N2_GPIOX_DS_REG_2B_OFFSET; + if (pin >= N2_GPIOA_PIN_START && pin <= N2_GPIOA_PIN_END) + return N2_GPIOA_DS_REG_5A_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pin Mux register +// +/*----------------------------------------------------------------------------*/ +static int gpioToMuxReg (int pin) +{ + switch (pin) { + case N2_GPIOA_PIN_START ...N2_GPIOA_PIN_START + 7: + return N2_GPIOA_MUX_D_REG_OFFSET; + case N2_GPIOA_PIN_START + 8 ...N2_GPIOA_PIN_END: + return N2_GPIOA_MUX_E_REG_OFFSET; + case N2_GPIOX_PIN_START ...N2_GPIOX_PIN_START + 7: + return N2_GPIOX_MUX_3_REG_OFFSET; + case N2_GPIOX_PIN_START + 8 ...N2_GPIOX_PIN_START + 15: + return N2_GPIOX_MUX_4_REG_OFFSET; + case N2_GPIOX_PIN_START + 16 ...N2_GPIOX_PIN_END: + return N2_GPIOX_MUX_5_REG_OFFSET; + default: + return -1; + } +} + /*----------------------------------------------------------------------------*/ static int getModeToGpio (int mode, int pin) { @@ -246,6 +291,48 @@ static int getModeToGpio (int mode, int pin) return retPin; } +/*----------------------------------------------------------------------------*/ +static void setPadDrive (int pin, int value) +{ + int ds, shift; + + if (lib->mode == MODE_GPIO_SYS) + return; + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return; + + if (value < 0 || value > 3) { + msg(MSG_WARN, "%s : Invalid value %d (Must be 0 ~ 3)\n", __func__, value); + return; + } + + ds = gpioToDSReg(pin); + shift = gpioToShiftReg(pin); + shift = pin > N2_GPIOX_PIN_MID ? (shift - 16) * 2 : shift * 2 ; + + *(gpio + ds) &= ~(0b11 << shift); + *(gpio + ds) |= (value << shift); +} + +/*----------------------------------------------------------------------------*/ +static int getPadDrive (int pin) +{ + int ds, shift; + + if (lib->mode == MODE_GPIO_SYS) + return; + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return; + + ds = gpioToDSReg(pin); + shift = gpioToShiftReg(pin); + shift = pin > N2_GPIOX_PIN_MID ? (shift - 16) * 2 : shift * 2 ; + + return (*(gpio + ds) >> shift) & 0b11; +} + /*----------------------------------------------------------------------------*/ static void pinMode (int pin, int mode) { @@ -285,7 +372,7 @@ static void pinMode (int pin, int mode) /*----------------------------------------------------------------------------*/ static int getAlt (int pin) { - int fsel, shift; + int fsel, mux, shift, target, mode; if (lib->mode == MODE_GPIO_SYS) return 0; @@ -293,10 +380,37 @@ static int getAlt (int pin) if ((pin = getModeToGpio(lib->mode, pin)) < 0) return 2; - fsel = gpioToGPFSELReg(pin); + 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; + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return; + + puen = gpioToPUENReg(pin); + pupd = gpioToPUPDReg(pin); shift = gpioToShiftReg(pin); - return (*(gpio + fsel) & (1 << shift)) ? 0 : 1; + if (*(gpio + puen) & (1 << shift)) + return *(gpio + pupd) & (1 << shift) ? 1 : 2; + else + return 0; } /*----------------------------------------------------------------------------*/ @@ -494,8 +608,11 @@ void init_odroidn2 (struct libodroid *libwiring) /* wiringPi Core function initialize */ libwiring->getModeToGpio = getModeToGpio; + libwiring->setPadDrive = setPadDrive; + libwiring->getPadDrive = getPadDrive; libwiring->pinMode = pinMode; libwiring->getAlt = getAlt; + libwiring->getPUPD = getPUPD; libwiring->pullUpDnControl = pullUpDnControl; libwiring->digitalRead = digitalRead; libwiring->digitalWrite = digitalWrite; diff --git a/wiringPi/odroidn2.h b/wiringPi/odroidn2.h index c2c6bf9..a6cff9c 100755 --- a/wiringPi/odroidn2.h +++ b/wiringPi/odroidn2.h @@ -14,22 +14,31 @@ #define GPIO_PIN_BASE 410 -#define N2_GPIOA_PIN_START (GPIO_PIN_BASE + 50) -#define N2_GPIOA_PIN_END (GPIO_PIN_BASE + 65) -#define N2_GPIOX_PIN_START (GPIO_PIN_BASE + 66) -#define N2_GPIOX_PIN_END (GPIO_PIN_BASE + 85) +#define N2_GPIOA_PIN_START (GPIO_PIN_BASE + 50) // GPIOA_0 +#define N2_GPIOA_PIN_END (GPIO_PIN_BASE + 65) // GPIOA_15 +#define N2_GPIOX_PIN_START (GPIO_PIN_BASE + 66) // GPIOX_0 +#define N2_GPIOX_PIN_MID (GPIO_PIN_BASE + 81) // GPIOX_15 +#define N2_GPIOX_PIN_END (GPIO_PIN_BASE + 85) // GPIOX_19 #define N2_GPIOX_FSEL_REG_OFFSET 0x116 #define N2_GPIOX_OUTP_REG_OFFSET 0x117 #define N2_GPIOX_INP_REG_OFFSET 0x118 #define N2_GPIOX_PUPD_REG_OFFSET 0x13C #define N2_GPIOX_PUEN_REG_OFFSET 0x14A +#define N2_GPIOX_DS_REG_2A_OFFSET 0x1D2 +#define N2_GPIOX_DS_REG_2B_OFFSET 0x1D3 +#define N2_GPIOX_MUX_3_REG_OFFSET 0x1B3 +#define N2_GPIOX_MUX_4_REG_OFFSET 0x1B4 +#define N2_GPIOX_MUX_5_REG_OFFSET 0x1B5 #define N2_GPIOA_FSEL_REG_OFFSET 0x120 #define N2_GPIOA_OUTP_REG_OFFSET 0x121 #define N2_GPIOA_INP_REG_OFFSET 0x122 #define N2_GPIOA_PUPD_REG_OFFSET 0x13F #define N2_GPIOA_PUEN_REG_OFFSET 0x14D +#define N2_GPIOA_DS_REG_5A_OFFSET 0x1D6 +#define N2_GPIOA_MUX_D_REG_OFFSET 0x1BD +#define N2_GPIOA_MUX_E_REG_OFFSET 0x1BE #ifdef __cplusplus extern "C" { diff --git a/wiringPi/wiringOdroid.c b/wiringPi/wiringOdroid.c index b6c62b7..44d73de 100755 --- a/wiringPi/wiringOdroid.c +++ b/wiringPi/wiringOdroid.c @@ -177,7 +177,6 @@ static void warn_msg(const char *func) // /*----------------------------------------------------------------------------*/ static void piGpioLayoutOops (const char *why) { warn_msg(__func__); return; } - void setPadDrive (int group, int value) { warn_msg(__func__); return; } void pwmSetMode (int mode) { warn_msg(__func__); return; } void pwmSetRange (unsigned int range) { warn_msg(__func__); return; } void pwmSetClock (int divisor) { warn_msg(__func__); return; } @@ -459,6 +458,34 @@ int physPinToGpio (int physPin) return -1; } +/*----------------------------------------------------------------------------*/ +/* + * setPadDrive: + * Set the PAD driver value + */ +/*----------------------------------------------------------------------------*/ +void setPadDrive (int pin, int value) +{ + if (libwiring.setPadDrive) + return libwiring.setPadDrive(pin, value); + + return -1; +} + +/*----------------------------------------------------------------------------*/ +/* + * getPadDrive: + * Get the PAD driver value + */ +/*----------------------------------------------------------------------------*/ +int getPadDrive (int pin) +{ + if (libwiring.getPadDrive) + return libwiring.getPadDrive(pin); + + return -1; +} + /*----------------------------------------------------------------------------*/ /* * getAlt: @@ -474,6 +501,21 @@ int getAlt (int pin) return -1; } +/*----------------------------------------------------------------------------*/ +/* + * getPUPD: + * Returns the PU/PD bits for a given port. Only really of-use + * for the gpio readall command (I think) + */ +/*----------------------------------------------------------------------------*/ +int getPUPD (int pin) +{ + if (libwiring.getPUPD) + return libwiring.getPUPD(pin); + + return -1; +} + /*----------------------------------------------------------------------------*/ /* * Core Functions diff --git a/wiringPi/wiringOdroid.h b/wiringPi/wiringOdroid.h index 6b4a5a1..4ae927f 100755 --- a/wiringPi/wiringOdroid.h +++ b/wiringPi/wiringOdroid.h @@ -175,8 +175,11 @@ struct libodroid /* wiringPi core func */ int (*getModeToGpio) (int mode, int pin); + void (*setPadDrive) (int pin, int value); + int (*getPadDrive) (int pin); void (*pinMode) (int pin, int mode); int (*getAlt) (int pin); + int (*getPUPD) (int pin); void (*pullUpDnControl) (int pin, int pud); int (*digitalRead) (int pin); void (*digitalWrite) (int pin, int value);