ODROID-C4: New support for ODROID-C4

Signed-off-by: Yang Deokgyu <secugyu@gmail.com>
Signed-off-by: Luke Go <sangch.go@gmail.com>
Change-Id: I0fd2de97d95bb8bf71cc1975081177571b1e8301
diff --git a/Android.bp b/Android.bp
index 098a4ed..28fec7f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,7 @@
         "wiringPi/wiringPi.c",
         "wiringPi/mcp23017.c",
         "wiringPi/odroidc2.c",
+        "wiringPi/odroidc4.c",
         "wiringPi/drcSerial.c",
         "wiringPi/mcp23s08.c",
         "wiringPi/odroidn1.c",
diff --git a/build b/build
index bfe05dc..37978ab 100755
--- a/build
+++ b/build
@@ -64,7 +64,7 @@
       *c|*c1|*c2)
         $sudo cp -f udev/rules.d/99-odroid-wiringpi-meson.rules /etc/udev/rules.d/
         ;;
-      *n2)
+      *n2|*c4)
         $sudo cp -f udev/rules.d/99-odroid-wiringpi-aml.rules /etc/udev/rules.d/
         ;;
       *)
diff --git a/debian/odroid-wiringpi.postinst b/debian/odroid-wiringpi.postinst
index 83c66ec..c02cfba 100644
--- a/debian/odroid-wiringpi.postinst
+++ b/debian/odroid-wiringpi.postinst
@@ -20,7 +20,7 @@
 				*c|*c1|*c2)
 					cp -f /tmp/odroid-wiringpi/rules.d/99-odroid-wiringpi-meson.rules /etc/udev/rules.d/
 					;;
-				*n2)
+				*n2|*c4)
 					cp -f /tmp/odroid-wiringpi/rules.d/99-odroid-wiringpi-aml.rules /etc/udev/rules.d/
 					;;
 				*)
diff --git a/gpio/readall.c b/gpio/readall.c
index be2619c..83ad11c 100755
--- a/gpio/readall.c
+++ b/gpio/readall.c
@@ -482,6 +482,68 @@
 };
 
 /*----------------------------------------------------------------------------*/
+static const char *physNamesOdroidC4All [64] =
+{
+	NULL,
+
+	"    3.3V", "5V      ",
+	"   SDA.2", "5V      ",
+	"   SCL.2", "GND(0V) ",
+	"GPIO.481", "TxD1    ",
+	" GND(0V)", "RxD1    ",
+	"GPIO.479", "GPIO.492",
+	"GPIO.480", "GND(0V) ",
+	"GPIO.483", "GPIO.476",
+	"    3.3V", "GPIO.477",
+	"    MOSI", "GND(0V) ",
+	"    MISO", "GPIO.478",
+	"    SLCK", "SS      ",
+	" GND(0V)", "GPIO. 23",
+	"   SDA.3", "SCL.3   ",
+	"GPIO.490", "GND(0V) ",
+	"GPIO.491", "GPIO. 24",
+	"GPIO.482", "GND(0V) ",
+	"GPIO.495", "GPIO. 22",
+	"   AIN.2", "1V8     ",
+	" GND(0V)", "AIN.0   ",
+
+	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 *physNamesOdroidC4 [64] =
+{
+	NULL,
+
+	"   3.3V", "5V     ",
+	"  SDA.2", "5V     ",
+	"  SCL.2", "0V     ",
+	" IO.481", "TxD1   ",
+	"     0V", "RxD1   ",
+	" IO.479", "IO.492 ",
+	" IO.480", "0V     ",
+	" IO.483", "IO.476 ",
+	"   3.3V", "IO.477 ",
+	"   MOSI", "0V     ",
+	"   MISO", "IO.478 ",
+	"   SLCK", "SS     ",
+	"     0V", "IO. 23 ",
+	"  SDA.3", "SCL.3  ",
+	" IO.490", "0V     ",
+	" IO.491", "IO. 24 ",
+	" IO.482", "0V     ",
+	" IO.495", "IO. 22 ",
+	"  AIN.2", "1V8    ",
+	"     0V", "AIN.0  ",
+
+	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 ;
 
@@ -533,6 +595,7 @@
 				break;
 			case MODEL_ODROID_XU3:
 			case MODEL_ODROID_N2:
+			case MODEL_ODROID_C4:
 				printf (" | %2d | %5s", getPadDrive(pin), pupd[getPUPD(pin)]);
 				break;
 			default:
@@ -573,6 +636,7 @@
 				break;
 			case MODEL_ODROID_XU3:
 			case MODEL_ODROID_N2:
+			case MODEL_ODROID_C4:
 				printf (" | %-5s | %-2d", pupd[getPUPD(pin)], getPadDrive(pin));
 				break;
 			default:
@@ -696,6 +760,10 @@
 			headerName = (isAll == FALSE) ? "--- N2 ---" : "---- Model  ODROID-N2 ----";
 			physNames = (char *) ((isAll == FALSE) ? physNamesOdroidN2 : physNamesOdroidN2All);
 			break;
+		case MODEL_ODROID_C4:
+			headerName = (isAll == FALSE) ? "--- C4 ---" : "---- Model  ODROID-C4 ----";
+			physNames = (char *) ((isAll == FALSE) ? physNamesOdroidC4 : physNamesOdroidC4All);
+			break;
 		default:
 			printf("Oops - unknown model: %d\n", model);
 			return;
diff --git a/pins/Makefile b/pins/Makefile
index 0426542..665f769 100755
--- a/pins/Makefile
+++ b/pins/Makefile
@@ -8,7 +8,8 @@
 		odroid_c1.tex	\
 		odroid_c2.tex	\
 		odroid_n1.tex	\
-		odroid_n2.tex
+		odroid_n2.tex	\
+		odroid_c4.tex
 
 DVI	=	$(SRC:.tex=.dvi)
 
diff --git a/pins/odroid_c4.pdf b/pins/odroid_c4.pdf
new file mode 100644
index 0000000..d5d4760
--- /dev/null
+++ b/pins/odroid_c4.pdf
Binary files differ
diff --git a/pins/odroid_c4.tex b/pins/odroid_c4.tex
new file mode 100644
index 0000000..62eb42a
--- /dev/null
+++ b/pins/odroid_c4.tex
@@ -0,0 +1,99 @@
+\documentclass[11pt,a4paper]{article}
+\parskip 1ex
+\parindent 0em
+\thispagestyle{empty}
+\pagestyle{plain}
+\pagenumbering{arabic}
+\setlength{\topmargin}{0pt}
+\setlength{\headheight}{0pt}
+\setlength{\headsep}{0pt}
+\setlength{\topskip}{0pt}
+\setlength{\textheight}{240mm}
+\setlength{\footskip}{5ex}
+\setlength{\oddsidemargin}{0pt}
+\setlength{\evensidemargin}{0pt}
+\setlength{\textwidth}{160mm}
+\usepackage[dvips]{graphics,color}
+\usepackage{helvet}
+\renewcommand{\familydefault}{\sfdefault}
+\begin{document}
+\begin{sffamily}
+\definecolor{rtb-black}{rgb}  {0.0, 0.0, 0.0}
+\definecolor{rtb-navy}{rgb}   {0.0, 0.0, 0.5}
+\definecolor{rtb-green}{rgb}  {0.0, 0.5, 0.0}
+\definecolor{rtb-teal}{rgb}   {0.0, 0.5, 0.5}
+\definecolor{rtb-maroon}{rgb} {0.5, 0.0, 0.0}
+\definecolor{rtb-purple}{rgb} {0.5, 0.0, 0.5}
+\definecolor{rtb-olive}{rgb}  {0.5, 0.5, 0.0}
+\definecolor{rtb-silver}{rgb} {0.7, 0.7, 0.7}
+\definecolor{rtb-grey}{rgb}   {0.5, 0.5, 0.5}
+\definecolor{rtb-blue}{rgb}   {0.0, 0.0, 1.0}
+\definecolor{rtb-lime}{rgb}   {0.0, 1.0, 0.0}
+\definecolor{rtb-aqua}{rgb}   {0.0, 1.0, 1.0}
+\definecolor{rtb-red}{rgb}    {1.0, 0.0, 0.0}
+\definecolor{rtb-fuchsia}{rgb}{1.0, 0.0, 1.0}
+\definecolor{rtb-yellow}{rgb} {1.0, 1.0, 0.0}
+\definecolor{rtb-white}{rgb}  {1.0, 1.0, 1.0}
+
+\begin{center}
+\bfseries{WiringPi: GPIO Pin Numbering Tables}\\
+\tt{https://wiki.odroid.com/odroid-c4/hardware/}
+\end{center}
+
+\begin{center}
+\begin{tabular}{|c|c|c||p{8mm}|p{8mm}||c|c|c|c|}
+\hline
+\multicolumn{8}{|c|}{\bfseries{ODROID-C4: 40 Pin GPIO connector(J2)}}\\
+\hline
+\hline
+WiringPi Pin	& Native GPIO	& Name	& \multicolumn{2}{|c||}{Header}	& Name	& Native GPIO	& WiringPi Pin\\
+\hline
+\hline
+	& 					& \textcolor{rtb-red}{3.3v}		& \raggedleft{1} &  2 & \textcolor{rtb-maroon}{5v}		&			 		& \\
+\hline
+8	& 493 (GPIOX.17)	& \textcolor{rtb-aqua}{SDA1}	& \raggedleft{3} &  4 & \textcolor{rtb-maroon}{5v}		& 					& \\
+\hline
+9	& 494 (GPIOX.18)	& \textcolor{rtb-aqua}{SCL1}	& \raggedleft{5} &  6 & \textcolor{rtb-black}{0v}		& 					& \\
+\hline
+7	& 481 (GPIOX.5)		& \textcolor{rtb-green}{GPIO7}	& \raggedleft{7} &  8 & \textcolor{rtb-yellow}{TxD}		& 488 (GPIOX.12)	& 15\\
+\hline
+	&			 		& \textcolor{rtb-black}{0v}		& \raggedleft{9} & 10 & \textcolor{rtb-yellow}{RxD}		& 489 (GPIOX.13)	& 16\\
+\hline
+0	& 479 (GPIOX.3)		& \textcolor{rtb-green}{GPIO0}	& \raggedleft{11} & 12 & \textcolor{rtb-green}{GPIO1}	& 492 (GPIOX.16)	& 1\\
+\hline
+2	& 480 (GPIOX.4)		& \textcolor{rtb-green}{GPIO2}	& \raggedleft{13} & 14 & \textcolor{rtb-black}{0v}		& 					& \\
+\hline
+3	& 483 (GPIOX.7)		& \textcolor{rtb-green}{GPIO3}	& \raggedleft{15} & 16 & \textcolor{rtb-green}{GPIO4}	& 476 (GPIOX.0)		& 4\\
+\hline
+	& 					& \textcolor{rtb-red}{3.3v}		& \raggedleft{17} & 18 & \textcolor{rtb-green}{GPIO5}	& 477 (GPIOX.1)		& 5\\
+\hline
+12	& 484 (GPIOX.8)		& \textcolor{rtb-green}{GPIO12}	& \raggedleft{19} & 20 & \textcolor{rtb-black}{0v}		& 					& \\
+\hline
+13	& 485 (GPIOX.9)	& \textcolor{rtb-green}{GPIO13}	& \raggedleft{21} & 22 & \textcolor{rtb-green}{GPIO6}	& 478 (GPIOX.2)		& 6\\
+\hline
+14	& 487 (GPIOX.11)	& \textcolor{rtb-green}{GPIO14}	& \raggedleft{23} & 24 & \textcolor{rtb-green}{GPIO10}	& 486 (GPIOX.10)	& 10\\
+\hline
+	& 					& \textcolor{rtb-black}{0v}		& \raggedleft{25} & 26 & \textcolor{rtb-green}{GPIO11}	& 23 (GPIOH.6)	& 11\\
+\hline
+30	& 474 (GPIOA.14)	& \textcolor{rtb-aqua}{SDA2}	& \raggedleft{27} & 28 & \textcolor{rtb-aqua}{SCL2}		& 475 (GPIOA.15)	& 31\\
+\hline
+21	& 490 (GPIOX.14)	& \textcolor{rtb-green}{GPIO21}	& \raggedleft{29} & 30 & \textcolor{rtb-black}{0v}		&					& \\
+\hline
+22	& 491 (GPIOX.15)	& \textcolor{rtb-green}{GPIO22}	& \raggedleft{31} & 32 & \textcolor{rtb-green}{GPIO26}	& 24 (GPIOH.7)	& 26\\
+\hline
+23	& 482 (GPIOX.6)		& \textcolor{rtb-green}{GPIO23}	& \raggedleft{33} & 34 & \textcolor{rtb-black}{0v}		&					& \\
+\hline
+24	& 495 (GPIOX.19)		& \textcolor{rtb-green}{GPIO24}	& \raggedleft{35} & 36 & \textcolor{rtb-green}{GPIO27}	& 22 (GPIOH.5)		& 27\\
+\hline
+25	& ADC.AIN1			& \textcolor{rtb-green}{GPIO25}	& \raggedleft{37} & 38 & \textcolor{rtb-green}{GPIO28}	& 1.8V Ref Out		& 28\\
+\hline
+	& 					& \textcolor{rtb-black}{0v}		& \raggedleft{39} & 40 & \textcolor{rtb-green}{GPIO29}	& ADC.AIN0			& 29\\
+\hline
+\hline
+WiringPi Pin	& Native GPIO	& Name	& \multicolumn{2}{|c||}{Header}	& Name	& Native GPIO	& WiringPi Pin\\
+\hline
+\end{tabular}
+\end{center}
+
+\end{sffamily}
+\end{document}
diff --git a/wiringPi/Makefile b/wiringPi/Makefile
index 702ef31..47ddf3a 100755
--- a/wiringPi/Makefile
+++ b/wiringPi/Makefile
@@ -68,7 +68,8 @@
 		odroidc2.c						\
 		odroidxu3.c						\
 		odroidn1.c						\
-		odroidn2.c
+		odroidn2.c						\
+		odroidc4.c
 
 HEADERS =	$(shell ls *.h)
 
@@ -155,6 +156,7 @@
 odroidxu3.o : wiringPi.h odroidxu3.h
 odroidn1.o  : wiringPi.h odroidn1.h
 odroidn2.o  : wiringPi.h odroidn2.h
+odroidc4.o  : wiringPi.h odroidc4.h
 
 wiringPi.o: softPwm.h softTone.h wiringPi.h ../version.h
 wiringSerial.o: wiringSerial.h
diff --git a/wiringPi/odroidc4.c b/wiringPi/odroidc4.c
new file mode 100644
index 0000000..8b9b3ff
--- /dev/null
+++ b/wiringPi/odroidc4.c
@@ -0,0 +1,704 @@
+/*----------------------------------------------------------------------------*/
+//
+//
+//	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 <sys/utsname.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
+	479, 492,	//  0 |  1 : GPIOX.3, GPIOX.16
+	480, 483,	//  2 |  3 : GPIOX.4, GPIOX.7
+	476, 477,	//  4 |  5 : GPIOX.0, GPIOX.1
+	478, 481,	//  6 |  7 : GPIOX.2, GPIOX.5
+	493, 494,	//  8 |  9 : GPIOX.17(I2C-2_SDA), GPIOX.18(I2C-2_SCL)
+	486,  23,	// 10 | 11 : GPIOX.10(SPI_SS), GPIOH.6
+	484, 485,	// 12 | 13 : GPIOX.8(SPI_MOSI), GPIOX.9(SPI_MISO)
+	487, 488,	// 14 | 15 : GPIOX.11(SPI_CLK), GPIOX.12(UART_TX_B)
+	489,  -1,	// 16 | 17 : GPIOX.13(UART_RX_B),
+	 -1, - 1,	// 18 | 19 :
+	 -1, 490,	// 20 | 21 : , GPIOX.14
+	491, 482,	// 22 | 23 : GPIOX.15, GPIOX.6
+	495,  -1,	// 24 | 25 : GPIOX.19, ADC.AIN3
+	 24,  22,	// 26 | 27 : GPIOH.7, GPIOH.5
+	 -1, - 1,	// 28 | 29 : REF1.8V OUT, ADC.AIC4
+	474, 475,	// 30 | 31 : GPIOA.14(I2C-3_SDA), GPIOA.15(I2C-3_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] = {
+	// physical header pin number to native gpio number
+	 -1,		//  0
+	 -1,  -1,	//  1 |  2 : 3.3V, 5.0V
+	493,  -1,	//  3 |  4 : GPIOX.17(I2C-2_SDA), 5.0V
+	494,  -1,	//  5 |  6 : GPIOX.18(I2C-2_SCL), GND
+	481, 488,	//  7 |  8 : GPIOX.5, GPIOX.12(UART_TX_B)
+	 -1, 489,	//  9 | 10 : GND, GPIOX.13(UART_RX_B)
+	479, 492,	// 11 | 12 : GPIOX.3, GPIOX.16
+	480,  -1,	// 13 | 14 : GPIOX.4, GND
+	483, 476,	// 15 | 16 : GPIOX.7, GPIOX.0
+	 -1, 477,	// 17 | 18 : 3.3V, GPIOX.1
+	484,  -1,	// 19 | 20 : GPIOX.8(SPI_MOSI), GND
+	485, 478,	// 21 | 22 : GPIOX.9(SPI_MISO), GPIOX.2
+	487, 486,	// 23 | 24 : GPIOX.11(SPI_CLK), GPIOX.10(SPI_SS)
+	 -1,  23,	// 25 | 26 : GND, GPIOH.6
+	474, 475,	// 27 | 28 : GPIOA.14(I2C-3_SDA), GPIOA.15(I2C-3_SCL)
+	490,  -1,	// 29 | 30 : GPIOX.14, GND
+	491,  24,	// 31 | 32 : GPIOX.15, GPIOH.7
+	482,  -1,	// 33 | 34 : GPIOX.6, GND
+	495,  22,	// 35 | 36 : GPIOX.19, GPIOH.5
+	 -1,  -1,	// 37 | 38 : ADC.AIN3, 1.8V REF OUT
+	 -1,  -1,	// 39 | 40 : GND, ADC.AIC4
+	// 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
+/*----------------------------------------------------------------------------*/
+/* ADC file descriptor */
+static int adcFds[2];
+
+/* 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		_setPadDrive		(int pin, int value);
+static int		_getPadDrive		(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);
+static int		_analogRead		(int pin);
+static int		_digitalWriteByte	(const unsigned int value);
+static unsigned int	_digitalReadByte	(void);
+
+/*----------------------------------------------------------------------------*/
+// board init function
+/*----------------------------------------------------------------------------*/
+static 	void init_gpio_mmap	(void);
+static 	void init_adc_fds	(void);
+
+	void init_odroidc4 	(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 _setPadDrive (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 _getPadDrive (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 int _analogRead (int pin)
+{
+	char value[5] = {0,};
+
+	if (lib->mode == MODE_GPIO_SYS)
+		return	-1;
+
+	/* wiringPi ADC number = pin 25, pin 29 */
+	switch (pin) {
+	case	3:	case	25:
+		pin = 0;
+	break;
+	case	2:	case	29:
+		pin = 1;
+	break;
+	default:
+		return	0;
+	}
+	if (adcFds [pin] == -1)
+		return 0;
+
+	lseek (adcFds [pin], 0L, SEEK_SET);
+	if (read(adcFds [pin], &value[0], 4) < 0) {
+		msg(MSG_WARN, "%s: Error occurs when it reads from ADC file descriptor. \n", __func__);
+		return -1;
+	}
+
+	return	atoi(value);
+}
+
+/*----------------------------------------------------------------------------*/
+static int _digitalWriteByte (const unsigned int value)
+{
+	union	reg_bitfield	gpiox;
+
+	if (lib->mode == MODE_GPIO_SYS)
+		return -1;
+
+	gpiox.wvalue = *(gpio + C4_GPIOX_INP_REG_OFFSET);
+
+	/* Wiring PI GPIO0 = C4 GPIOX.3 */
+	gpiox.bits.bit3 = (value & 0x01);
+	/* Wiring PI GPIO1 = C4 GPIOX.16 */
+	gpiox.bits.bit16 = (value & 0x02);
+	/* Wiring PI GPIO2 = C4 GPIOX.4 */
+	gpiox.bits.bit4 = (value & 0x04);
+	/* Wiring PI GPIO3 = C4 GPIOX.7 */
+	gpiox.bits.bit7 = (value & 0x08);
+	/* Wiring PI GPIO4 = C4 GPIOX.0 */
+	gpiox.bits.bit0 = (value & 0x10);
+	/* Wiring PI GPIO5 = C4 GPIOX.1 */
+	gpiox.bits.bit1 = (value & 0x20);
+	/* Wiring PI GPIO6 = C4 GPIOX.2 */
+	gpiox.bits.bit2 = (value & 0x40);
+	/* Wiring PI GPIO7 = C4 GPIOX.5 */
+	gpiox.bits.bit5 = (value & 0x80);
+
+	*(gpio + C4_GPIOX_OUTP_REG_OFFSET) = gpiox.wvalue;
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+static unsigned int _digitalReadByte (void)
+{
+	union	reg_bitfield	gpiox;
+	unsigned int		value = 0;
+
+	if (lib->mode == MODE_GPIO_SYS)
+		return -1;
+
+	gpiox.wvalue = *(gpio + C4_GPIOX_INP_REG_OFFSET);
+
+	/* Wiring PI GPIO0 = C4 GPIOX.3 */
+	if (gpiox.bits.bit3)
+		value |= 0x01;
+	/* Wiring PI GPIO1 = C4 GPIOX.16 */
+	if (gpiox.bits.bit16)
+		value |= 0x02;
+	/* Wiring PI GPIO2 = C4 GPIOX.4 */
+	if (gpiox.bits.bit4)
+		value |= 0x04;
+	/* Wiring PI GPIO3 = C4 GPIOX.7 */
+	if (gpiox.bits.bit7)
+		value |= 0x08;
+	/* Wiring PI GPIO4 = C4 GPIOX.0 */
+	if (gpiox.bits.bit0)
+		value |= 0x10;
+	/* Wiring PI GPIO5 = C4 GPIOX.1 */
+	if (gpiox.bits.bit1)
+		value |= 0x20;
+	/* Wiring PI GPIO6 = C4 GPIOX.2 */
+	if (gpiox.bits.bit2)
+		value |= 0x40;
+	/* Wiring PI GPIO7 = C4 GPIOX.5 */
+	if (gpiox.bits.bit5)
+		value |= 0x80;
+
+	return	value;
+}
+
+/*----------------------------------------------------------------------------*/
+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));
+		} 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;
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+static void init_adc_fds (void)
+{
+	const char *AIN25_NODE, *AIN29_NODE;
+
+	/* ADC node setup */
+	AIN25_NODE = "/sys/devices/platform/ff809000.saradc/iio:device0/in_voltage2_raw";
+	AIN29_NODE = "/sys/devices/platform/ff809000.saradc/iio:device0/in_voltage0_raw";
+
+	adcFds[0] = open(AIN25_NODE, O_RDONLY);
+	adcFds[1] = open(AIN29_NODE, O_RDONLY);
+}
+
+/*----------------------------------------------------------------------------*/
+void init_odroidc4 (struct libodroid *libwiring)
+{
+	init_gpio_mmap();
+
+	init_adc_fds();
+
+	/* 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;
+	libwiring->analogRead		= _analogRead;
+	libwiring->digitalWriteByte	= _digitalWriteByte;
+	libwiring->digitalReadByte	= _digitalReadByte;
+
+	/* specify pin base number */
+	libwiring->pinBase		= C4_GPIO_PIN_BASE;
+
+	/* global variable setup */
+	lib = libwiring;
+}
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
diff --git a/wiringPi/odroidc4.h b/wiringPi/odroidc4.h
new file mode 100644
index 0000000..94fb88e
--- /dev/null
+++ b/wiringPi/odroidc4.h
@@ -0,0 +1,65 @@
+/*----------------------------------------------------------------------------*/
+/*
+
+	WiringPi ODROID-C4 Board Header file
+
+ */
+/*----------------------------------------------------------------------------*/
+#ifndef	__ODROID_C4_H__
+#define	__ODROID_C4_H__
+
+/*----------------------------------------------------------------------------*/
+#define C4_GPIO_BASE			0xFF634000
+
+#define C4_GPIO_PIN_BASE		460
+
+#define C4_GPIOH_PIN_START		17				// GPIOH_0
+#define C4_GPIOH_PIN_END		25				// GPIOH_8
+#define C4_GPIOA_PIN_START		C4_GPIO_PIN_BASE		// GPIOA_0
+#define C4_GPIOA_PIN_END		(C4_GPIO_PIN_BASE + 15)		// GPIOA_15
+#define C4_GPIOX_PIN_START		(C4_GPIO_PIN_BASE + 16)		// GPIOX_0
+#define C4_GPIOX_PIN_MID		(C4_GPIO_PIN_BASE + 31)		// GPIOX_15
+#define C4_GPIOX_PIN_END		(C4_GPIO_PIN_BASE + 35)		// GPIOX_19
+
+#define C4_GPIOH_FSEL_REG_OFFSET	0x119
+#define C4_GPIOH_OUTP_REG_OFFSET	0x11A
+#define C4_GPIOH_INP_REG_OFFSET		0x11B
+#define C4_GPIOH_PUPD_REG_OFFSET	0x13D
+#define C4_GPIOH_PUEN_REG_OFFSET	0x14B
+#define C4_GPIOH_DS_REG_3A_OFFSET	0x1D4
+#define C4_GPIOH_MUX_B_REG_OFFSET	0x1BB
+
+#define C4_GPIOA_FSEL_REG_OFFSET	0x120
+#define C4_GPIOA_OUTP_REG_OFFSET	0x121
+#define C4_GPIOA_INP_REG_OFFSET		0x122
+#define C4_GPIOA_PUPD_REG_OFFSET	0x13F
+#define C4_GPIOA_PUEN_REG_OFFSET	0x14D
+#define C4_GPIOA_DS_REG_5A_OFFSET	0x1D6
+#define C4_GPIOA_MUX_D_REG_OFFSET	0x1BD
+#define C4_GPIOA_MUX_E_REG_OFFSET	0x1BE
+
+#define C4_GPIOX_FSEL_REG_OFFSET	0x116
+#define C4_GPIOX_OUTP_REG_OFFSET	0x117
+#define C4_GPIOX_INP_REG_OFFSET		0x118
+#define C4_GPIOX_PUPD_REG_OFFSET	0x13C
+#define C4_GPIOX_PUEN_REG_OFFSET	0x14A
+#define C4_GPIOX_DS_REG_2A_OFFSET	0x1D2
+#define C4_GPIOX_DS_REG_2B_OFFSET	0x1D3
+#define C4_GPIOX_MUX_3_REG_OFFSET	0x1B3
+#define C4_GPIOX_MUX_4_REG_OFFSET	0x1B4
+#define C4_GPIOX_MUX_5_REG_OFFSET	0x1B5
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void init_odroidc4 (struct libodroid *libwiring);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+#endif	/* __ODROID_C4_H__ */
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c
index 54d0484..9f658e8 100755
--- a/wiringPi/wiringPi.c
+++ b/wiringPi/wiringPi.c
@@ -37,6 +37,7 @@
 #include "odroidxu3.h"
 #include "odroidn1.h"
 #include "odroidn2.h"
+#include "odroidc4.h"
 
 /*----------------------------------------------------------------------------*/
 // Const string define
@@ -49,6 +50,7 @@
 	"ODROID-XU3/4",
 	"ODROID-N1",
 	"ODROID-N2",
+	"ODROID-C4",
 };
 
 const char *piRevisionNames [16] =
@@ -441,6 +443,11 @@
 		libwiring.maker	= MAKER_AMLOGIC;
 		libwiring.mem	= 4;
 		libwiring.rev	= 1;
+	} else if (strncmp (c, "05", 2) == 0) {
+		libwiring.model	= MODEL_ODROID_C4;
+		libwiring.maker	= MAKER_AMLOGIC;
+		libwiring.mem	= 4;
+		libwiring.rev	= 1;
 	} else {
 		libwiring.model	= MODEL_UNKNOWN;
 		libwiring.maker	= MAKER_UNKNOWN;
@@ -474,6 +481,7 @@
  *         Rev 1.1 : /sys/class/odroid/boardrev value is 1 (Mass board)
  *  03xx - Model ODROID N1, 4096M, Hardkernel
  *  04xx - Model ODROID N2, 4096M, Hardkernel
+ *  05xx - Model ODROID C4, 4096M, Hardkernel
  */
 /*----------------------------------------------------------------------------*/
 void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
@@ -1073,6 +1081,9 @@
 	case MODEL_ODROID_N2:
 		init_odroidn2(&libwiring);
 	break;
+	case MODEL_ODROID_C4:
+		init_odroidc4(&libwiring);
+	break;
 	default:
 		return wiringPiFailure (WPI_ALMOST,
 			"wiringPiSetup: Unknown model\n");
diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h
index 25d8dd8..a00dc9d 100755
--- a/wiringPi/wiringPi.h
+++ b/wiringPi/wiringPi.h
@@ -52,6 +52,7 @@
 #define	MODEL_ODROID_XU3	3
 #define	MODEL_ODROID_N1		4
 #define	MODEL_ODROID_N2		5
+#define	MODEL_ODROID_C4		6
 
 #define	MAKER_UNKNOWN		0
 #define	MAKER_AMLOGIC		1
diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c
index b9fc54a..48d0a1e 100644
--- a/wiringPi/wiringPiI2C.c
+++ b/wiringPi/wiringPiI2C.c
@@ -251,6 +251,7 @@
 		device = "/dev/i2c-4";
 	break;
 	case MODEL_ODROID_N2:
+	case MODEL_ODROID_C4:
 		device = "/dev/i2c-2";
 	break;
 	}
diff --git a/wiringPi/wiringPiSPI.c b/wiringPi/wiringPiSPI.c
index 5166383..406f099 100644
--- a/wiringPi/wiringPiSPI.c
+++ b/wiringPi/wiringPiSPI.c
@@ -146,6 +146,7 @@
 	switch(model)	{
 	case MODEL_ODROID_C1:
 	case MODEL_ODROID_N2:
+	case MODEL_ODROID_C4:
 		sprintf(device, "%s%d", spiDevType0, channel);
 	break;
 	case MODEL_ODROID_XU3: