diff --git a/gpio/readall_odroid.c b/gpio/readall_odroid.c index 1af675a..55a010e 100755 --- a/gpio/readall_odroid.c +++ b/gpio/readall_odroid.c @@ -234,26 +234,26 @@ static const char *physNamesOdroidN1 [64] = { NULL, - " 3.3V", "5V ", - "I2C1.SDA", "5V ", - "I2C1.SCL", "GND(0V) ", - "GPIO. 18", "UART0.TX", - " GND(0V)", "UART0.RX", - "GPIO.174", "GPIO.173", - "GPIO. 21", "GND(0V) ", - "GPIO. 22", "GPIO. 19", - " 3.3V", "GPIO. 23", - " MOSI", "GND(0V) ", - " MISO", "GPIO. 24", - " SCLK", "CE0 ", - " GND(0V)", "GPIO. 25", - "I2C5.SDA", "I2C5.SCL", - "GPIO. 28", "GND(0V) ", - "GPIO. 30", "GPIO. 29", - "GPIO. 31", "GND(0V) ", - "POWER ON", "GPIO. 33", - " AIN.0", "1V8 ", - " GND(0V)", "AIN.3 ", + " 3.0V", "5V ", + "I2C4_SDA", "5V ", + "I2C4_SCL", "GND(0V) ", + "GPIO1A.0", "UART0_TX", + " GND(0V)", "UART0_RX", + "GPIO1A.1", "GPIO1A.2", + "GPIO1A.3", "GND(0V) ", + "GPIO1A.4", "GPIO1B.5", + " 3.0V", "GPIO1C.2", + "SPI1_TXD", "GND(0V) ", + "SPI1_RXD", "GPIO1D.0", + "SPI1_CLK", "SPI1_CSN", + " GND(0V)", "GPIO1C.6", + "I2C8_SDA", "I2C8_SCL", + "SPDIF_TX", "GND(0V) ", + " PWM1", "GPIO4D.4", + "GPIO4D.0", "GND(0V) ", + "GPIO4D.5", "GPIO4D.6", + "ADC.AIN1", "1V8 ", + " GND(0V)", "ADC.AIN0", NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, @@ -372,6 +372,7 @@ void doReadall (void) physNames = physNamesOdroidXU3; break; case MODEL_ODROID_N1: + printf (" +------+-----+----------+------+ Model ODROID-N1 +------+----------+-----+------+\n") ; physNames = physNamesOdroidN1; break; default: diff --git a/wiringPi/odroidc1.c b/wiringPi/odroidc1.c index fdb868a..c6575f4 100755 --- a/wiringPi/odroidc1.c +++ b/wiringPi/odroidc1.c @@ -513,6 +513,9 @@ void init_odroidc1 (struct libodroid *libwiring) libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalReadByte = digitalReadByte; + /* specify pin base number */ + libwiring->pinBase = GPIO_PIN_BASE; + /* global variable setup */ lib = libwiring; } diff --git a/wiringPi/odroidc2.c b/wiringPi/odroidc2.c index 96548a7..360bca3 100755 --- a/wiringPi/odroidc2.c +++ b/wiringPi/odroidc2.c @@ -543,6 +543,9 @@ void init_odroidc2 (struct libodroid *libwiring) libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalReadByte = digitalReadByte; + /* specify pin base number */ + libwiring->pinBase = GPIO_PIN_BASE; + /* global variable setup */ lib = libwiring; } diff --git a/wiringPi/odroidc2.h b/wiringPi/odroidc2.h index 4c17e72..4cac662 100755 --- a/wiringPi/odroidc2.h +++ b/wiringPi/odroidc2.h @@ -12,11 +12,12 @@ #define ODROIDC2_GPIO_MASK (0xFFFFFF00) #define ODROIDC2_GPIO_BASE 0xC8834000 -#define C2_GPIO_PIN_BASE 136 -#define C2_GPIOY_PIN_START (C2_GPIO_PIN_BASE + 75) -#define C2_GPIOY_PIN_END (C2_GPIO_PIN_BASE + 91) -#define C2_GPIOX_PIN_START (C2_GPIO_PIN_BASE + 92) -#define C2_GPIOX_PIN_END (C2_GPIO_PIN_BASE + 114) +#define GPIO_PIN_BASE 136 + +#define C2_GPIOY_PIN_START (GPIO_PIN_BASE + 75) +#define C2_GPIOY_PIN_END (GPIO_PIN_BASE + 91) +#define C2_GPIOX_PIN_START (GPIO_PIN_BASE + 92) +#define C2_GPIOX_PIN_END (GPIO_PIN_BASE + 114) #define C2_GPIOX_FSEL_REG_OFFSET 0x118 #define C2_GPIOX_OUTP_REG_OFFSET 0x119 diff --git a/wiringPi/odroidn1.c b/wiringPi/odroidn1.c index c04d84b..fa2ae3b 100755 --- a/wiringPi/odroidn1.c +++ b/wiringPi/odroidn1.c @@ -25,55 +25,53 @@ // wiringPi gpio map define /*----------------------------------------------------------------------------*/ static const int pinToGpio[64] = { -#if 0 // wiringPi number to native gpio number - ???, ???, // 0 | 1 : - ???, -1, // 2 | 3 : - ???, ???, // 4 | 5 : - ???, ???, // 6 | 7 : - -1, -1, // 8 | 9 : - ???, ???, // 10 | 11 : - ???, ???, // 12 | 13 : - ???, -1, // 14 | 15 : - -1, -1, // 16 | 17 : + 33, 34, // 0 | 1 : GPIO1_A.1, GPIO1_A.2 + 35, 36, // 2 | 3 : GPIO1_A.3, GPIO1_A.4 + 45, 50, // 4 | 5 : GPIO1_B.5, GPIO1_C.2 + 56, 32, // 6 | 7 : GPIO1_D.0, GPIO1_A.0 + 43, 44, // 8 | 9 : GPIO1_B.3(I2C4_SDA), GPIO1_B.4(I2C4_SCL) + 42, 54, // 10 | 11 : GPIO1_B.2(SPI1_CSN), GPIO1_C.6 + 40, 39, // 12 | 13 : GPIO1_B.0(SPI1_TXD), GPIO1_A.7(SPI1_RXD) + 41, 81, // 14 | 15 : GPIO1_B.1(SPI1_CLK), GPIO2_C.1_B(UART0_TX) + 80, -1, // 16 | 17 : GPIO2_C.0_B(UART0_RX) -1, -1, // 18 | 19 : - -1, ???, // 20 | 21 : - ???, ???, // 22 | 23 : - ???, -1, // 24 | 25 : - ???, ???, // 26 | 27 : - -1, -1, // 28 | 29 : - -1, -1, // 30 | 31 : -#endif + -1, 149, // 20 | 21 : , GPIO4_C.5(SPDIF_TX) + 150,152, // 22 | 23 : GPIO4_C.6(PWM1), CPIO4_D.0 + 157, -1, // 24 | 25 : GPIO4_D.5, ADC.AIN1 + 156,158, // 26 | 27 : GPIO4_D.4, GPIO4_D.6 + -1, -1, // 28 | 29 : 18.V REF, ADC.AIN0 + 52, 53, // 30 | 31 : GPIO1_C.4(I2C8_SDA), GPIO1_C.5(I2C8_SCL) + // 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] = { -#if 0 // physical header pin number to native gpio number -1, // 0 - -1, -1, // 1 | 2 : - -1, -1, // 3 | 4 : - -1, -1, // 5 | 6 : - ???, -1, // 7 | 8 : - -1, -1, // 9 | 10 : - ???,???, // 11 | 12 : - ???, -1, // 13 | 14 : - -1, ???, // 15 | 16 : - -1, ???, // 17 | 18 : - ???, -1, // 19 | 20 : - ???,???, // 21 | 22 : - ???,???, // 23 | 24 : - -1, ???, // 25 | 26 : - -1, -1, // 27 | 28 : - ???, -1, // 29 | 30 : - ???,???, // 31 | 32 : - ???, -1, // 33 | 34 : - ???,???, // 35 | 36 : - -1, -1, // 37 | 38 : - -1, -1, // 39 | 40 : -#endif + -1, -1, // 1 | 2 : 3.0V, 5.0V + 43, -1, // 3 | 4 : GPIO1_B.3(I2C4_SDA), 5.0V + 44, -1, // 5 | 6 : GPIO1_B.4(I2C4_SCL), GND + 32, 81, // 7 | 8 : GPIO1_A.0, GPIO2_C.1_B(UART0_TX) + -1, 80, // 9 | 10 : GND, GPIO2_C.0_B(UART0_RX) + 33, 34, // 11 | 12 : GPIO1_A.1, GPIO1_A.2 + 35, -1, // 13 | 14 : GPIO1_A.3, GND + 36, 45, // 15 | 16 : GPIO1_A.4, GPIO1_B.5 + -1, 50, // 17 | 18 : 3.0V, GPIO1_C.2 + 40, -1, // 19 | 20 : GPIO1_B.0(SPI1_TXD), GND + 39, 56, // 21 | 22 : GPIO1_A.7(SPI1_RXD), GPIO1_D.0 + 41, 42, // 23 | 24 : GPIO1_B.1(SPI1_CLK), GPIO1_B.2(SPI1_CSN0) + -1, 54, // 25 | 26 : GND, GPIO1_C.6 + 52, 53, // 27 | 28 : GPIO1_C.4(I2C8_SDA), GPIO1_C.5(I2C8_SCL) + 149, -1, // 29 | 30 : GPIO4_C.5(SPDIF_TX), GND + 150,156, // 31 | 32 : GPIO4_C.6(PWM1), GPIO4_D.4 + 152, -1, // 33 | 34 : GPIO4_D.0, GND + 157,158, // 35 | 36 : GPIO4_D.5, GPIO4_D.6 + -1, -1, // 37 | 38 : ADC.AIN1, 1.8V REF + -1, -1, // 39 | 40 : GND, ADC.AIN0 + // Not used -1, -1, -1, -1, -1, -1, -1, -1, // 41...48 -1, -1, -1, -1, -1, -1, -1, -1, // 49...56 @@ -88,8 +86,14 @@ static const int phyToGpio[64] = { /* ADC file descriptor */ static char *adcFds[2]; -/* GPIO mmap control */ -static volatile uint32_t *gpio, *gpio1; +/* GPIO mmap control. Actual GPIO bank number. */ +static volatile uint32_t *gpio[5]; + +/* GRF(General Register Files) base addresses to control GPIO modes */ +static volatile uint32_t *grf[2]; + +/* CRU(Clock & Reset Unit) base addresses to control CLK mode */ +static volatile uint32_t *cru[2]; /* wiringPi Global library */ static struct libodroid *lib = NULL; @@ -97,12 +101,10 @@ 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 gpioToShiftGReg (int pin); +static void setClkState (int pin, int state); +static void setIomuxMode (int pin, int mode); /*----------------------------------------------------------------------------*/ // wiringPi core function @@ -123,49 +125,9 @@ static unsigned int digitalReadByte (void); static void init_gpio_mmap (void); static void init_adc_fds (void); - void init_odroidn1 (struct libodroid *libwiring); + void init_odroidn1 (struct libodroid *libwiring); /*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -// -// offset to the GPIO Set regsiter -// -/*----------------------------------------------------------------------------*/ -static int gpioToGPSETReg (int pin) -{ - return -1; -} - -/*----------------------------------------------------------------------------*/ -// -// offset to the GPIO Input regsiter -// -/*----------------------------------------------------------------------------*/ -static int gpioToGPLEVReg (int pin) -{ - return -1; -} - -/*----------------------------------------------------------------------------*/ -// -// offset to the GPIO Pull up/down enable regsiter -// -/*----------------------------------------------------------------------------*/ -static int gpioToPUENReg (int pin) -{ - return -1; -} - -/*----------------------------------------------------------------------------*/ -// -// offset to the GPIO Pull up/down regsiter -// -/*----------------------------------------------------------------------------*/ -static int gpioToPUPDReg (int pin) -{ - return -1; -} - /*----------------------------------------------------------------------------*/ // // offset to the GPIO bit @@ -173,75 +135,591 @@ static int gpioToPUPDReg (int pin) /*----------------------------------------------------------------------------*/ static int gpioToShiftReg (int pin) { - return -1; + return pin % 32; } /*----------------------------------------------------------------------------*/ // -// offset to the GPIO Function register +// offset to the GPIO bit at GRF address // /*----------------------------------------------------------------------------*/ -static int gpioToGPFSELReg (int pin) +static int gpioToShiftGReg (int pin) { - return -1; + return pin % 8; } + /*----------------------------------------------------------------------------*/ static int getModeToGpio (int mode, int pin) { - return -1; + if (pin > 255) + return msg(MSG_ERR, "%s : Invalid pin number %d\n", __func__, pin); + + switch (mode) { + /* Native gpio number */ + case MODE_GPIO: + return pin; + /* Native gpio number for sysfs */ + case MODE_GPIO_SYS: + return lib->sysFds[pin] != -1 ? pin : -1; + /* wiringPi number */ + case MODE_PINS: + return pin < 64 ? pinToGpio[pin] : -1; + /* header pin number */ + case MODE_PHYS: + return pin < 64 ? phyToGpio[pin] : -1; + default : + msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode); + return -1; + } +} + +/*----------------------------------------------------------------------------*/ +// +// set GPIO clock state +// +/*----------------------------------------------------------------------------*/ +static void setClkState (int pin, int state) +{ + uint32_t target = GPIO_CON_REGS_PROG; + int bank = pin / 32; + int shift = bank < 2 ? bank + 2 : bank + 1; + + switch (state) { + case CLK_ENABLE: + if (bank < 2) { + target |= *(cru[0] + (PMUCRU_GPIO_CLK_OFFSET >> 2)); + target &= ~(1 << shift); + + *(cru[0] + (PMUCRU_GPIO_CLK_OFFSET >> 2)) = target; + } else { + target |= *(cru[1] + (CRU_GPIO_CLK_OFFSET >> 2)); + target &= ~(1 << shift); + + *(cru[1] + (CRU_GPIO_CLK_OFFSET >> 2)) = target; + } + break; + case CLK_DISABLE: + if (bank < 2) { + target |= *(cru[0] + (PMUCRU_GPIO_CLK_OFFSET >> 2)); + target |= (1 << shift); + + *(cru[0] + (PMUCRU_GPIO_CLK_OFFSET >> 2)) = target; + } else { + target |= *(cru[1] + (CRU_GPIO_CLK_OFFSET >> 2)); + target |= (1 << shift); + + *(cru[1] + (CRU_GPIO_CLK_OFFSET >> 2)) = target; + } + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +// +// set IOMUX mode +// +/*----------------------------------------------------------------------------*/ +static void setIomuxMode (int pin, int mode) +{ + uint32_t offset, target; + uint8_t bank, group; + + bank = pin / 32; + group = (pin - bank * 32) / 8; + offset = 0x10 * (bank > 1 ? bank - 2 : bank) + 0x4 * group; + target = GPIO_CON_REGS_PROG; + + switch (mode) { + case FUNC_GPIO: + // Common IOMUX Funtion 1 : GPIO + if (bank < 2) { + offset += PMUGRF_IOMUX_OFFSET; + + target |= *(grf[0] + (offset >> 2)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2)); + + *(grf[0] + (offset >> 2)) = target; + } else { + offset += GRF_IOMUX_OFFSET; + + target |= *(grf[1] + (offset >> 2)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2)); + + *(grf[1] + (offset >> 2)) = target; + } + break; + default: + break; + } } /*----------------------------------------------------------------------------*/ static void pinMode (int pin, int mode) { + int origPin, bank; + unsigned long flags; + + if (lib->mode == MODE_GPIO_SYS) + return; + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return; + + origPin = pin; + bank = pin / 32; + + softPwmStop (origPin); + softToneStop(origPin); + + setClkState (pin, CLK_ENABLE); + setIomuxMode(pin, FUNC_GPIO); + + switch (mode) { + case INPUT: + *(gpio[bank] + (GPIO_CON_OFFSET >> 2)) &= ~(1 << gpioToShiftReg(pin)); + break; + case OUTPUT: + *(gpio[bank] + (GPIO_CON_OFFSET >> 2)) |= (1 << gpioToShiftReg(pin)); + 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); + break; + } + + setClkState (pin, CLK_DISABLE); } /*----------------------------------------------------------------------------*/ static int getAlt (int pin) { - return -1; + uint32_t offset, target; + uint8_t bank, group; + uint8_t ret = 0; + + if (lib->mode == MODE_GPIO_SYS) + return 0; + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return 2; + + bank = pin / 32; + group = (pin - bank * 32) / 8; + offset = 0x10 * (bank > 1 ? bank - 2 : bank) + 0x4 * group; + target = GPIO_CON_REGS_PROG; + + setClkState(pin, CLK_ENABLE); + + // Check if the pin is GPIO mode on GRF register + if (bank < 2) { + offset += PMUGRF_IOMUX_OFFSET; + if (*(grf[0] + (offset >> 2)) & (3 << (gpioToShiftGReg(pin) * 2))) + ret = 2; + } else { + offset += GRF_IOMUX_OFFSET; + if (*(grf[1] + (offset >> 2)) & (3 << (gpioToShiftGReg(pin) * 2))) + ret = 2; + } + + // If it is GPIO mode, check it's direction + if (ret != 2) + ret = *(gpio[bank] + (GPIO_CON_OFFSET >> 2)) & (1 << gpioToShiftReg(pin)) ? 1 : 0; + + setClkState(pin, CLK_DISABLE); + + return ret; } /*----------------------------------------------------------------------------*/ static void pullUpDnControl (int pin, int pud) { + uint32_t offset, target; + uint8_t bank, group; + + if (lib->mode == MODE_GPIO_SYS) + return 0; + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return 2; + + bank = pin / 32; + group = (pin - bank * 32) / 8; + offset = 0x10 * (bank > 1 ? bank - 2 : bank) + 0x4 * group; + target = GPIO_CON_REGS_PROG; + + setClkState(pin, CLK_ENABLE); + + switch (pud) { + case PUD_UP: + if (bank < 2) { + offset += PMUGRF_PUPD_OFFSET; + + target |= *(grf[0] + (offset >> 2)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target |= (1 << (gpioToShiftGReg(pin) * 2)); + + *(grf[0] + (offset >> 2)) = target; + } else { + offset += GRF_PUPD_OFFSET; + + target |= *(grf[1] + (offset >> 2)); + + if (bank == 2 && group >= 2) { + target |= (1 << (gpioToShiftGReg(pin) * 2 + 1)); + target |= (1 << (gpioToShiftGReg(pin) * 2)); + } else { + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target |= (1 << (gpioToShiftGReg(pin) * 2)); + } + + *(grf[1] + (offset >> 2)) = target; + } + break; + case PUD_DOWN: + if (bank < 2) { + offset += PMUGRF_PUPD_OFFSET; + + target |= *(grf[0] + (offset >> 2)); + target |= (1 << (gpioToShiftGReg(pin) * 2 + 1)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2)); + + *(grf[0] + (offset >> 2)) = target; + } else { + offset += GRF_PUPD_OFFSET; + + target |= *(grf[1] + (offset >> 2)); + + if (bank == 2 && group >= 2) { + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target |= (1 << (gpioToShiftGReg(pin) * 2)); + } else { + target |= (1 << (gpioToShiftGReg(pin) * 2 + 1)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2)); + } + + *(grf[1] + (offset >> 2)) = target; + } + break; + case PUD_OFF: + if (bank < 2) { + offset += PMUGRF_PUPD_OFFSET; + + target |= *(grf[0] + (offset >> 2)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2)); + + *(grf[0] + (offset >> 2)) = target; + } else { + offset += GRF_PUPD_OFFSET; + + target |= *(grf[1] + (offset >> 2)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2 + 1)); + target &= ~(1 << (gpioToShiftGReg(pin) * 2)); + + *(grf[1] + (offset >> 2)) = target; + } + break; + default: + break; + } + + setClkState(pin, CLK_DISABLE); } /*----------------------------------------------------------------------------*/ static int digitalRead (int pin) { + int bank, ret; + char c; + + if (lib->mode == MODE_GPIO_SYS) { + if (lib->sysFds[pin] == -1) + return LOW; + + lseek (lib->sysFds[pin], 0L, SEEK_SET); + read (lib->sysFds[pin], &c, 1); + + return (c == '0') ? LOW : HIGH; + } + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return 0; + + bank = pin / 32; + setClkState(pin, CLK_ENABLE); + + ret = *(gpio[bank] + (GPIO_GET_OFFSET >> 2)) & (1 << gpioToShiftReg(pin)) ? HIGH : LOW; + + setClkState(pin, CLK_DISABLE); + return ret; } /*----------------------------------------------------------------------------*/ static void digitalWrite (int pin, int value) { + int bank; + + 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_ERR, + "%s : %s\nEdit direction file to output mode for\n\t/sys/class/gpio/gpio%d/direction\n", + __func__, strerror(errno), pin + GPIO_PIN_BASE); + } else { + if (write (lib->sysFds[pin], "1\n", 2) < 0) + msg(MSG_ERR, + "%s : %s\nEdit direction file to output mode for\n\t/sys/class/gpio/gpio%d/direction\n", + __func__, strerror(errno), pin + GPIO_PIN_BASE); + } + } + return; + } + + if ((pin = getModeToGpio(lib->mode, pin)) < 0) + return; + + bank = pin / 32; + setClkState(pin, CLK_ENABLE); + + switch (value) { + case LOW: + *(gpio[bank] + (GPIO_SET_OFFSET >> 2)) &= ~(1 << gpioToShiftReg(pin)); + break; + case HIGH: + *(gpio[bank] + (GPIO_SET_OFFSET >> 2)) |= (1 << gpioToShiftReg(pin)); + break; + default: + break; + } + + setClkState(pin, CLK_DISABLE); } /*----------------------------------------------------------------------------*/ static int analogRead (int pin) { - return -1; + unsigned char value[5] = {0,}; + + if (lib->mode == MODE_GPIO_SYS) + return 0; + + /* wiringPi ADC number = pin 25, pin 29 */ + switch (pin) { + case 0: case 25: + pin = 0; + break; + case 1: case 29: + pin = 1; + break; + default: + return 0; + } + if (adcFds [pin] == -1) + return 0; + + lseek (adcFds [pin], 0L, SEEK_SET); + read (adcFds [pin], &value[0], 4); + + return atoi(value); } /*----------------------------------------------------------------------------*/ static void digitalWriteByte (const int value) { + union reg_bitfield gpioBits1; + + if (lib->mode == MODE_GPIO_SYS) { + return; + } + + // Enable clock for GPIO 1 bank + setClkState(32, CLK_ENABLE); + + /* Read data register */ + gpioBits1.wvalue = *(gpio[1] + (GPIO_GET_OFFSET >> 2)); + + /* Wiring PI GPIO0 = N1 GPIO1_A.1 */ + gpioBits1.bits.bit1 = (value & 0x01); + /* Wiring PI GPIO1 = N1 GPIO1_A.2 */ + gpioBits1.bits.bit2 = (value & 0x02); + /* Wiring PI GPIO2 = N1 GPIO1_A.3 */ + gpioBits1.bits.bit3 = (value & 0x04); + /* Wiring PI GPIO3 = N1 GPIO1_A.4 */ + gpioBits1.bits.bit4 = (value & 0x08); + /* Wiring PI GPIO4 = N1 GPIO1_B.5 */ + gpioBits1.bits.bit14 = (value & 0x10); + /* Wiring PI GPIO5 = N1 GPIO1_C.2 */ + gpioBits1.bits.bit19 = (value & 0x20); + /* Wiring PI GPIO6 = N1 GPIO1_D.0 */ + gpioBits1.bits.bit25 = (value & 0x40); + /* Wiring PI GPIO7 = N1 GPIO1_A.0 */ + gpioBits1.bits.bit0 = (value & 0x80); + + /* Update data register */ + *(gpio[1] + (GPIO_SET_OFFSET >> 2)) = gpioBits1.wvalue; + + setClkState(32, CLK_DISABLE); } /*----------------------------------------------------------------------------*/ static unsigned int digitalReadByte (void) { - return -1; + union reg_bitfield gpioBits1; + unsigned int value = 0; + + if (lib->mode == MODE_GPIO_SYS) { + return -1; + } + + // Enable clock for GPIO 1 bank + setClkState(32, CLK_ENABLE); + + /* Read data register */ + gpioBits1.wvalue = *(gpio[1] + (GPIO_GET_OFFSET >> 2)); + + setClkState(32, CLK_DISABLE); + + /* Wiring PI GPIO0 = N1 GPIO1_A.1 */ + if (gpioBits1.bits.bit1) + value |= 0x01; + /* Wiring PI GPIO1 = N1 GPIO1_A.2 */ + if (gpioBits1.bits.bit2) + value |= 0x02; + /* Wiring PI GPIO2 = N1 GPIO1_A.3 */ + if (gpioBits1.bits.bit3) + value |= 0x04; + /* Wiring PI GPIO3 = N1 GPIO1_A.4 */ + if (gpioBits1.bits.bit4) + value |= 0x08; + /* Wiring PI GPIO4 = N1 GPIO1_B.5 */ + if (gpioBits1.bits.bit14) + value |= 0x10; + /* Wiring PI GPIO5 = N1 GPIO1_C.2 */ + if (gpioBits1.bits.bit19) + value |= 0x20; + /* Wiring PI GPIO6 = N1 GPIO1_D.0 */ + if (gpioBits1.bits.bit25) + value |= 0x40; + /* Wiring PI GPIO7 = N1 GPIO1_A.0 */ + if (gpioBits1.bits.bit0) + value |= 0x80; + + return value; } /*----------------------------------------------------------------------------*/ static void init_gpio_mmap (void) { + int fd; + + /* GPIO mmap setup */ + if (access("/dev/gpiomem",0) == 0) { + if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) + return msg (MSG_ERR, + "wiringPiSetup: Unable to open /dev/gpiomem: %s\n", + strerror (errno)) ; + } else { + if (geteuid () != 0) + return msg (MSG_ERR, + "wiringPiSetup: Must be root. (Did you forget sudo?)\n"); + if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) + return msg (MSG_ERR, + "wiringPiSetup: Unable to open /dev/mem: %s\n", + strerror (errno)) ; + } + + // GPIO{0, 1} + //#define ODROIDN1_PMUCRU_BASE 0xFF750000 + cru[0] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, PMUCRU_BASE) ; + + // GPIO{2, 3, 4} + //#define ODROIDN1_CRU_BASE 0xFF760000 + cru[1] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, CRU_BASE) ; + + // GPIO{0, 1} + //#define ODROIDN1_PMU_BASE 0xFF320000 + grf[0] = (uint32_t *)mmap(0, GRF_BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, PMUGRF_BASE) ; + + // GPIO{2, 3, 4} + //#define ODROIDN1_GRF_BASE 0xFF770000 + grf[1] = (uint32_t *)mmap(0, GRF_BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, GRF_BASE) ; + + // GPIO1_A. 0,1,2,3,4,7 + // GPIO1_B. 0,1,2,3,4,5 + // GPIO1_C. 2,4,5,6 + // GPIO1_D. 0 + //#define ODROIDN1_GPIO1_BASE 0xFF730000 + gpio[1] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, GPIO_1_BASE) ; + + // GPIO2_C. 0_B,1_B + //#define ODROIDN1_GPIO2_BASE 0xFF780000 + gpio[2] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, GPIO_2_BASE) ; + + // GPIO4_C. 5,6 + // GPIO4_D. 0,4,5,6 + //#define ODROIDN1_GPIO4_BASE 0xFF790000 + gpio[4] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, GPIO_4_BASE) ; + + // Reserved + gpio[0] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, GPIO_0_BASE) ; + gpio[3] = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, GPIO_3_BASE) ; + + if (((int32_t)cru[0] == -1) || ((int32_t)cru[1] == -1)) { + return msg (MSG_ERR, + "wiringPiSetup: mmap (CRU) failed: %s\n", + strerror (errno)); + } + + if (((int32_t)grf[0] == -1) || ((int32_t)grf[1] == -1)) { + return msg (MSG_ERR, + "wiringPiSetup: mmap (GRF) failed: %s\n", + strerror (errno)); + } + + if ( ((int32_t)gpio[0] == -1) || + ((int32_t)gpio[1] == -1) || + ((int32_t)gpio[2] == -1) || + ((int32_t)gpio[3] == -1) || + ((int32_t)gpio[4] == -1)) { + return msg (MSG_ERR, + "wiringPiSetup: mmap (GPIO) failed: %s\n", + strerror (errno)); + } } /*----------------------------------------------------------------------------*/ static void init_adc_fds (void) { + const char *AIN0_NODE, *AIN1_NODE; + struct utsname uname_buf; + + /* ADC node setup */ + uname(&uname_buf); + + AIN0_NODE = "/sys/devices/platform/ff100000.saradc/iio:device0/in_voltage0_raw"; + AIN1_NODE = "/sys/devices/platform/ff100000.saradc/iio:device0/in_voltage1_raw"; + + adcFds[0] = open(AIN0_NODE, O_RDONLY); + adcFds[1] = open(AIN1_NODE, O_RDONLY); } /*----------------------------------------------------------------------------*/ @@ -262,6 +740,9 @@ void init_odroidn1 (struct libodroid *libwiring) libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalReadByte = digitalReadByte; + /* specify pin base number */ + libwiring->pinBase = GPIO_PIN_BASE; + /* global variable setup */ lib = libwiring; } diff --git a/wiringPi/odroidn1.h b/wiringPi/odroidn1.h index c477f78..0105bd8 100755 --- a/wiringPi/odroidn1.h +++ b/wiringPi/odroidn1.h @@ -9,6 +9,61 @@ #define __ODROID_N1_H__ /*----------------------------------------------------------------------------*/ +// Common mmap block size for ODROID-N1 GRF register +#define GRF_BLOCK_SIZE 0xF000 + +// Common offset for GPIO registers from each GPIO bank's base address +#define GPIO_CON_OFFSET 0x04 // GPIO_SWPORTA_DDR +#define GPIO_SET_OFFSET 0x00 // GPIO_SWPORTA_DR +#define GPIO_GET_OFFSET 0x50 // GPIO_EXT_PORTA + +#define FUNC_GPIO 0b00 // Bit for IOMUX GPIO mode + +// GPIO{0, 1} +#define PMUGRF_BASE 0xFF320000 +#define PMUGRF_IOMUX_OFFSET 0x0000 // GRF_GPIO0A_IOMUX +#define PMUGRF_PUPD_OFFSET 0x0040 // PMUGRF_GPIO0A_P + +// GPIO{2, 3, 4} +#define GRF_BASE 0xFF770000 +#define GRF_IOMUX_OFFSET 0xE000 // GRF_GPIO2A_IOMUX +#define GRF_PUPD_OFFSET 0xE040 // GRF_GPIO2A_P + +// Offset to control GPIO clock +// Make 31:16 bit HIGH to enable the writing corresponding bit +#define PMUCRU_BASE 0xFF750000 +#define PMUCRU_GPIO_CLK_OFFSET 0x0104 // PMUCRU_CLKGATE_CON1 + +#define CRU_BASE 0xFF760000 +#define CRU_GPIO_CLK_OFFSET 0x037C // CRU_CLKGATE_CON31 + +#define CLK_ENABLE 0b0 +#define CLK_DISABLE 0b1 + +// Control IOMUX, PU/PD, CLK +#define GPIO_CON_REGS_PROG 0xFFFF0000 // To make GRF/CRU register programmable + +// Only for Linux kernel for now. Edit to 0 for Android +#define GPIO_PIN_BASE 1000 + +// GPIO1_A. 0,1,2,3,4,7 +// GPIO1_B. 0,1,2,3,4,5 +// GPIO1_C. 2,4,5,6 +// GPIO1_D. 0 +#define GPIO_1_BASE 0xFF730000 + +// GPIO2_C. 0_B,1_B +#define GPIO_2_BASE 0xFF780000 + +// GPIO4_C. 5,6 +// GPIO4_D. 0,4,5,6 +#define GPIO_4_BASE 0xFF790000 + +// Reserved +// GPIO{0, 3} +#define GPIO_0_BASE 0xFF720000 +#define GPIO_3_BASE 0xFF788000 + #ifdef __cplusplus extern "C" { #endif diff --git a/wiringPi/odroidxu3.c b/wiringPi/odroidxu3.c index 6cdcccd..3b2874e 100755 --- a/wiringPi/odroidxu3.c +++ b/wiringPi/odroidxu3.c @@ -624,6 +624,9 @@ void init_odroidxu3 (struct libodroid *libwiring) libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalReadByte = digitalReadByte; + /* specify pin base number */ + libwiring->pinBase = GPIO_PIN_BASE; + /* global variable setup */ lib = libwiring; } diff --git a/wiringPi/odroidxu3.h b/wiringPi/odroidxu3.h index 9ab31af..2f1d7c9 100755 --- a/wiringPi/odroidxu3.h +++ b/wiringPi/odroidxu3.h @@ -11,6 +11,8 @@ /*----------------------------------------------------------------------------*/ #define ODROIDXU3_GPIO_MASK (0xFFFFFF00) +#define GPIO_PIN_BASE 0 + // GPX0,1,2,3 #define ODROIDXU3_GPX_BASE 0x13400000 diff --git a/wiringPi/wiringOdroid.c b/wiringPi/wiringOdroid.c index 890f512..7b2955f 100755 --- a/wiringPi/wiringOdroid.c +++ b/wiringPi/wiringOdroid.c @@ -341,7 +341,7 @@ int piGpioLayout (void) libwiring.rev = atoi(buf) + 1; } } - } else if (strcmp (c, "0300") == 0) { + } else if (strncmp (c, "03", 2) == 0) { libwiring.model = MODEL_ODROID_N1; libwiring.maker = MAKER_ROCKCHIP; libwiring.mem = 4; @@ -377,7 +377,7 @@ int piBoardRev (void) * 02xx - Model ODROID C2, 2048M, Hardkernel * Rev 1.0 : /sys/class/odroid/boardrev value is 0 (Dev board) * Rev 1.1 : /sys/class/odroid/boardrev value is 1 (Mass board) - * 0300 - Model ODROID N1, 4096M, Hardkernel + * 03xx - Model ODROID N1, 4096M, Hardkernel */ /*----------------------------------------------------------------------------*/ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) @@ -878,7 +878,15 @@ int wiringPiSetupSys (void) for (pin = 0 ; pin < 256 ; ++pin) { - sprintf (fName, "/sys/class/gpio/gpio%d/value", pin); + switch (libwiring.model) { + case MODEL_ODROID_N1: + sprintf (fName, "/sys/class/gpio/gpio%d/value", pin + libwiring.pinBase); + break; + default: + sprintf (fName, "/sys/class/gpio/gpio%d/value", pin); + break; + } + libwiring.sysFds [pin] = open (fName, O_RDWR); } diff --git a/wiringPi/wiringOdroid.h b/wiringPi/wiringOdroid.h index 48c2885..ef1ca09 100755 --- a/wiringPi/wiringOdroid.h +++ b/wiringPi/wiringOdroid.h @@ -120,6 +120,9 @@ struct libodroid /* GPIO sysfs file discripter */ int sysFds[256]; + /* GPIO pin base number */ + int pinBase; + // Time for easy calculations uint64_t epochMilli, epochMicro ; };