wiringPi: Add support for ODROID N1

Change-Id: Id7952e7d220b50cdbfcc5f9084547bf46599c817
This commit is contained in:
Joshua Yang
2018-01-11 14:32:58 +09:00
parent 9c84ec6db5
commit 9048264cc2
10 changed files with 683 additions and 123 deletions

View File

@@ -234,26 +234,26 @@ static const char *physNamesOdroidN1 [64] =
{ {
NULL, NULL,
" 3.3V", "5V ", " 3.0V", "5V ",
"I2C1.SDA", "5V ", "I2C4_SDA", "5V ",
"I2C1.SCL", "GND(0V) ", "I2C4_SCL", "GND(0V) ",
"GPIO. 18", "UART0.TX", "GPIO1A.0", "UART0_TX",
" GND(0V)", "UART0.RX", " GND(0V)", "UART0_RX",
"GPIO.174", "GPIO.173", "GPIO1A.1", "GPIO1A.2",
"GPIO. 21", "GND(0V) ", "GPIO1A.3", "GND(0V) ",
"GPIO. 22", "GPIO. 19", "GPIO1A.4", "GPIO1B.5",
" 3.3V", "GPIO. 23", " 3.0V", "GPIO1C.2",
" MOSI", "GND(0V) ", "SPI1_TXD", "GND(0V) ",
" MISO", "GPIO. 24", "SPI1_RXD", "GPIO1D.0",
" SCLK", "CE0 ", "SPI1_CLK", "SPI1_CSN",
" GND(0V)", "GPIO. 25", " GND(0V)", "GPIO1C.6",
"I2C5.SDA", "I2C5.SCL", "I2C8_SDA", "I2C8_SCL",
"GPIO. 28", "GND(0V) ", "SPDIF_TX", "GND(0V) ",
"GPIO. 30", "GPIO. 29", " PWM1", "GPIO4D.4",
"GPIO. 31", "GND(0V) ", "GPIO4D.0", "GND(0V) ",
"POWER ON", "GPIO. 33", "GPIO4D.5", "GPIO4D.6",
" AIN.0", "1V8 ", "ADC.AIN1", "1V8 ",
" GND(0V)", "AIN.3 ", " GND(0V)", "ADC.AIN0",
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,
@@ -372,6 +372,7 @@ void doReadall (void)
physNames = physNamesOdroidXU3; physNames = physNamesOdroidXU3;
break; break;
case MODEL_ODROID_N1: case MODEL_ODROID_N1:
printf (" +------+-----+----------+------+ Model ODROID-N1 +------+----------+-----+------+\n") ;
physNames = physNamesOdroidN1; physNames = physNamesOdroidN1;
break; break;
default: default:

View File

@@ -513,6 +513,9 @@ void init_odroidc1 (struct libodroid *libwiring)
libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalWriteByte = digitalWriteByte;
libwiring->digitalReadByte = digitalReadByte; libwiring->digitalReadByte = digitalReadByte;
/* specify pin base number */
libwiring->pinBase = GPIO_PIN_BASE;
/* global variable setup */ /* global variable setup */
lib = libwiring; lib = libwiring;
} }

View File

@@ -543,6 +543,9 @@ void init_odroidc2 (struct libodroid *libwiring)
libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalWriteByte = digitalWriteByte;
libwiring->digitalReadByte = digitalReadByte; libwiring->digitalReadByte = digitalReadByte;
/* specify pin base number */
libwiring->pinBase = GPIO_PIN_BASE;
/* global variable setup */ /* global variable setup */
lib = libwiring; lib = libwiring;
} }

View File

@@ -12,11 +12,12 @@
#define ODROIDC2_GPIO_MASK (0xFFFFFF00) #define ODROIDC2_GPIO_MASK (0xFFFFFF00)
#define ODROIDC2_GPIO_BASE 0xC8834000 #define ODROIDC2_GPIO_BASE 0xC8834000
#define C2_GPIO_PIN_BASE 136 #define 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_GPIOY_PIN_START (GPIO_PIN_BASE + 75)
#define C2_GPIOX_PIN_START (C2_GPIO_PIN_BASE + 92) #define C2_GPIOY_PIN_END (GPIO_PIN_BASE + 91)
#define C2_GPIOX_PIN_END (C2_GPIO_PIN_BASE + 114) #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_FSEL_REG_OFFSET 0x118
#define C2_GPIOX_OUTP_REG_OFFSET 0x119 #define C2_GPIOX_OUTP_REG_OFFSET 0x119

View File

@@ -25,55 +25,53 @@
// wiringPi gpio map define // wiringPi gpio map define
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static const int pinToGpio[64] = { static const int pinToGpio[64] = {
#if 0
// wiringPi number to native gpio number // wiringPi number to native gpio number
???, ???, // 0 | 1 : 33, 34, // 0 | 1 : GPIO1_A.1, GPIO1_A.2
???, -1, // 2 | 3 : 35, 36, // 2 | 3 : GPIO1_A.3, GPIO1_A.4
???, ???, // 4 | 5 : 45, 50, // 4 | 5 : GPIO1_B.5, GPIO1_C.2
???, ???, // 6 | 7 : 56, 32, // 6 | 7 : GPIO1_D.0, GPIO1_A.0
-1, -1, // 8 | 9 : 43, 44, // 8 | 9 : GPIO1_B.3(I2C4_SDA), GPIO1_B.4(I2C4_SCL)
???, ???, // 10 | 11 : 42, 54, // 10 | 11 : GPIO1_B.2(SPI1_CSN), GPIO1_C.6
???, ???, // 12 | 13 : 40, 39, // 12 | 13 : GPIO1_B.0(SPI1_TXD), GPIO1_A.7(SPI1_RXD)
???, -1, // 14 | 15 : 41, 81, // 14 | 15 : GPIO1_B.1(SPI1_CLK), GPIO2_C.1_B(UART0_TX)
-1, -1, // 16 | 17 : 80, -1, // 16 | 17 : GPIO2_C.0_B(UART0_RX)
-1, -1, // 18 | 19 : -1, -1, // 18 | 19 :
-1, ???, // 20 | 21 : -1, 149, // 20 | 21 : , GPIO4_C.5(SPDIF_TX)
???, ???, // 22 | 23 : 150,152, // 22 | 23 : GPIO4_C.6(PWM1), CPIO4_D.0
???, -1, // 24 | 25 : 157, -1, // 24 | 25 : GPIO4_D.5, ADC.AIN1
???, ???, // 26 | 27 : 156,158, // 26 | 27 : GPIO4_D.4, GPIO4_D.6
-1, -1, // 28 | 29 : -1, -1, // 28 | 29 : 18.V REF, ADC.AIN0
-1, -1, // 30 | 31 : 52, 53, // 30 | 31 : GPIO1_C.4(I2C8_SDA), GPIO1_C.5(I2C8_SCL)
#endif
// Padding: // 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, // 32...47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48...63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48...63
}; };
static const int phyToGpio[64] = { static const int phyToGpio[64] = {
#if 0
// physical header pin number to native gpio number // physical header pin number to native gpio number
-1, // 0 -1, // 0
-1, -1, // 1 | 2 : -1, -1, // 1 | 2 : 3.0V, 5.0V
-1, -1, // 3 | 4 : 43, -1, // 3 | 4 : GPIO1_B.3(I2C4_SDA), 5.0V
-1, -1, // 5 | 6 : 44, -1, // 5 | 6 : GPIO1_B.4(I2C4_SCL), GND
???, -1, // 7 | 8 : 32, 81, // 7 | 8 : GPIO1_A.0, GPIO2_C.1_B(UART0_TX)
-1, -1, // 9 | 10 : -1, 80, // 9 | 10 : GND, GPIO2_C.0_B(UART0_RX)
???,???, // 11 | 12 : 33, 34, // 11 | 12 : GPIO1_A.1, GPIO1_A.2
???, -1, // 13 | 14 : 35, -1, // 13 | 14 : GPIO1_A.3, GND
-1, ???, // 15 | 16 : 36, 45, // 15 | 16 : GPIO1_A.4, GPIO1_B.5
-1, ???, // 17 | 18 : -1, 50, // 17 | 18 : 3.0V, GPIO1_C.2
???, -1, // 19 | 20 : 40, -1, // 19 | 20 : GPIO1_B.0(SPI1_TXD), GND
???,???, // 21 | 22 : 39, 56, // 21 | 22 : GPIO1_A.7(SPI1_RXD), GPIO1_D.0
???,???, // 23 | 24 : 41, 42, // 23 | 24 : GPIO1_B.1(SPI1_CLK), GPIO1_B.2(SPI1_CSN0)
-1, ???, // 25 | 26 : -1, 54, // 25 | 26 : GND, GPIO1_C.6
-1, -1, // 27 | 28 : 52, 53, // 27 | 28 : GPIO1_C.4(I2C8_SDA), GPIO1_C.5(I2C8_SCL)
???, -1, // 29 | 30 : 149, -1, // 29 | 30 : GPIO4_C.5(SPDIF_TX), GND
???,???, // 31 | 32 : 150,156, // 31 | 32 : GPIO4_C.6(PWM1), GPIO4_D.4
???, -1, // 33 | 34 : 152, -1, // 33 | 34 : GPIO4_D.0, GND
???,???, // 35 | 36 : 157,158, // 35 | 36 : GPIO4_D.5, GPIO4_D.6
-1, -1, // 37 | 38 : -1, -1, // 37 | 38 : ADC.AIN1, 1.8V REF
-1, -1, // 39 | 40 : -1, -1, // 39 | 40 : GND, ADC.AIN0
#endif
// Not used // Not used
-1, -1, -1, -1, -1, -1, -1, -1, // 41...48 -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, -1, // 49...56
@@ -88,8 +86,14 @@ static const int phyToGpio[64] = {
/* ADC file descriptor */ /* ADC file descriptor */
static char *adcFds[2]; static char *adcFds[2];
/* GPIO mmap control */ /* GPIO mmap control. Actual GPIO bank number. */
static volatile uint32_t *gpio, *gpio1; 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 */ /* wiringPi Global library */
static struct libodroid *lib = NULL; static struct libodroid *lib = NULL;
@@ -97,12 +101,10 @@ static struct libodroid *lib = NULL;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
// Function prototype define // 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 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 // wiringPi core function
@@ -123,49 +125,9 @@ static unsigned int digitalReadByte (void);
static void init_gpio_mmap (void); static void init_gpio_mmap (void);
static void init_adc_fds (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 // offset to the GPIO bit
@@ -173,75 +135,591 @@ static int gpioToPUPDReg (int pin)
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static int gpioToShiftReg (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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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->digitalWriteByte = digitalWriteByte;
libwiring->digitalReadByte = digitalReadByte; libwiring->digitalReadByte = digitalReadByte;
/* specify pin base number */
libwiring->pinBase = GPIO_PIN_BASE;
/* global variable setup */ /* global variable setup */
lib = libwiring; lib = libwiring;
} }

View File

@@ -9,6 +9,61 @@
#define __ODROID_N1_H__ #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@@ -624,6 +624,9 @@ void init_odroidxu3 (struct libodroid *libwiring)
libwiring->digitalWriteByte = digitalWriteByte; libwiring->digitalWriteByte = digitalWriteByte;
libwiring->digitalReadByte = digitalReadByte; libwiring->digitalReadByte = digitalReadByte;
/* specify pin base number */
libwiring->pinBase = GPIO_PIN_BASE;
/* global variable setup */ /* global variable setup */
lib = libwiring; lib = libwiring;
} }

View File

@@ -11,6 +11,8 @@
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
#define ODROIDXU3_GPIO_MASK (0xFFFFFF00) #define ODROIDXU3_GPIO_MASK (0xFFFFFF00)
#define GPIO_PIN_BASE 0
// GPX0,1,2,3 // GPX0,1,2,3
#define ODROIDXU3_GPX_BASE 0x13400000 #define ODROIDXU3_GPX_BASE 0x13400000

View File

@@ -341,7 +341,7 @@ int piGpioLayout (void)
libwiring.rev = atoi(buf) + 1; libwiring.rev = atoi(buf) + 1;
} }
} }
} else if (strcmp (c, "0300") == 0) { } else if (strncmp (c, "03", 2) == 0) {
libwiring.model = MODEL_ODROID_N1; libwiring.model = MODEL_ODROID_N1;
libwiring.maker = MAKER_ROCKCHIP; libwiring.maker = MAKER_ROCKCHIP;
libwiring.mem = 4; libwiring.mem = 4;
@@ -377,7 +377,7 @@ int piBoardRev (void)
* 02xx - Model ODROID C2, 2048M, Hardkernel * 02xx - Model ODROID C2, 2048M, Hardkernel
* Rev 1.0 : /sys/class/odroid/boardrev value is 0 (Dev board) * Rev 1.0 : /sys/class/odroid/boardrev value is 0 (Dev board)
* Rev 1.1 : /sys/class/odroid/boardrev value is 1 (Mass 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) 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) 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); libwiring.sysFds [pin] = open (fName, O_RDWR);
} }

View File

@@ -120,6 +120,9 @@ struct libodroid
/* GPIO sysfs file discripter */ /* GPIO sysfs file discripter */
int sysFds[256]; int sysFds[256];
/* GPIO pin base number */
int pinBase;
// Time for easy calculations // Time for easy calculations
uint64_t epochMilli, epochMicro ; uint64_t epochMilli, epochMicro ;
}; };