diff --git a/Makefile.am b/Makefile.am
index fee51de86f293116a10d17afe00fd54abd3429ba..7e80a535c07d1dd20c69a4a59c4b6f17f9f7c045 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,3 +18,7 @@ endif
 if BLUETOOTH
 gbridge_SOURCES += bluetooth.c
 endif
+
+if UART
+gbridge_SOURCES += uart.c
+endif
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
index 190443f56faaccd9ac9eb313bdfc0c636b257231..72f61babcbf450c5452c6a0d44bbcea06f15245d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,16 @@ AC_ARG_ENABLE([tcpip],
 esac])
 AM_CONDITIONAL([TPCIP], [test x$tcpip = xtrue])
 
+AC_ARG_ENABLE([uart],
+[  --enable-uart    Enable uart],
+[case "${enableval}" in
+	yes) uart=true ;
+	     AC_DEFINE([HAVE_UART], [1], ["UART support"]) ;;
+	no)  uart=false ;;
+	*) AC_MSG_ERROR([bad value ${enableval} for --enable-uart]) ;;
+esac])
+AM_CONDITIONAL([UART], [test x$uart = xtrue])
+
 AC_ARG_VAR([GBDIR], ["greybus sources directory"])
 AS_IF([test "$GBDIR" = ""], [
   AC_MSG_ERROR([Environment variable GBDIR needs to be set])
diff --git a/main.c b/main.c
index d3c73408cd84672cbe26d0fb4ae7d55fba6de81e..80d5f3db4fdaef530a78b03819a0c1e2d0330446 100644
--- a/main.c
+++ b/main.c
@@ -16,13 +16,28 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <errno.h>
 #include <signal.h>
+#include <unistd.h>
 
 #include <debug.h>
 #include <controller.h>
 
 #include "gbridge.h"
 #include "netlink.h"
+#include "uart.h"
+
+static void help(void)
+{
+	printf("gbridge: Greybus bridge application\n"
+		"\t-h: Print the help\n"
+#ifdef HAVE_UART
+		"uart options:\n"
+		"\t-p uart_device: set the uart device\n"
+		"\t-b baudrate: set the uart baudrate\n"
+#endif
+		);
+}
 
 static void signal_handler(int sig)
 {
@@ -31,12 +46,33 @@ static void signal_handler(int sig)
 
 int main(int argc, char *argv[])
 {
+	int c;
 	int ret;
 
+	int baudrate = 115200;
+	const char *uart = NULL;
+
 	signal(SIGINT, signal_handler);
 	signal(SIGHUP, signal_handler);
 	signal(SIGTERM, signal_handler);
 
+	while ((c = getopt(argc, argv, "p:b:")) != -1) {
+		switch(c) {
+		case 'p':
+			uart = optarg;
+			break;
+		case 'b':
+			if (sscanf(optarg, "%u", &baudrate) != 1) {
+				help();
+				return -EINVAL;
+			}
+			break;
+		default:
+			help();
+			return -EINVAL;
+		}
+	}
+
 	ret = greybus_init();
 	if (ret) {
 		pr_err("Failed to init Greybus\n");
@@ -55,6 +91,14 @@ int main(int argc, char *argv[])
 		goto err_netlink_exit;
 	}
 
+	if (uart) {
+		ret = register_uart_controller(uart, baudrate);
+		if (ret) {
+			pr_err("Failed to init uart controller\n");
+			goto err_netlink_exit;
+		}
+	}
+
 	controllers_init();
 
 	netlink_loop();
diff --git a/uart.c b/uart.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb74f4d20cdd3798d3d0638780d3ddecadc17446
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,183 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ * Author: Alexandre Bailon <abailon@baylibre.com>
+ * Copyright (c) 2016 Alexandre Bailon
+ */
+
+#include <debug.h>
+#include <gbridge.h>
+#include <controller.h>
+#include <uart.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+struct controller uart_controller;
+
+struct uart_controller {
+	int fd;
+};
+
+int register_uart_controller(const char *file_name, int baudrate)
+{
+	int ret;
+	struct termios tio;
+	struct controller *ctrl;
+	struct uart_controller *uart_ctrl;
+
+	uart_ctrl = malloc(sizeof(*uart_ctrl));
+	if (!uart_ctrl)
+		return -ENOMEM;
+
+	tcgetattr(uart_ctrl->fd, &tio);
+	cfsetospeed(&tio, baudrate);
+	cfsetispeed(&tio, baudrate);
+	tio.c_cflag = CS8 | CREAD;
+	tio.c_iflag = IGNBRK;
+	tio.c_lflag = 0;
+	tio.c_oflag = 0;
+
+	uart_ctrl->fd = open(file_name, O_RDWR | O_NOCTTY | O_NDELAY);
+	if (uart_ctrl->fd < 0) {
+		free(uart_ctrl);
+		return uart_ctrl->fd;
+	}
+
+	ret = tcsetattr(uart_ctrl->fd, TCSANOW, &tio);
+	if (ret < 0) {
+		close(uart_ctrl->fd);
+		free(uart_ctrl);
+	}
+
+	ctrl = malloc(sizeof(*ctrl));
+	if (!ctrl) {
+		close(uart_ctrl->fd);
+		free(uart_ctrl);
+		return -ENOMEM;
+	}
+
+	memcpy(ctrl, &uart_controller, sizeof(*ctrl));
+	ctrl->priv = uart_ctrl;
+	register_controller(ctrl);
+
+	return 0;
+}
+
+static int uart_init(struct controller * ctrl)
+{
+	return 0;
+}
+
+static void uart_exit(struct controller * ctrl)
+{
+	struct uart_controller *uart_ctrl = ctrl->priv;
+
+	close(uart_ctrl->fd);
+	free(uart_ctrl);
+}
+
+static int uart_hotplug(struct controller *ctrl)
+{
+	int ret;
+	struct interface *intf;
+
+	/* FIXME: use real IDs */
+	intf = interface_create(ctrl, 1, 1, 0x1234, NULL);
+	if (!intf)
+		return -ENOMEM;
+
+	ret = interface_hotplug(intf);
+	if (ret < 0) {
+		interface_destroy(intf);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int uart_write(struct connection * conn, void *data, size_t len)
+{
+	struct uart_controller *ctrl = conn->intf->ctrl->priv;
+
+	cport_pack(data, conn->cport2_id);
+	return write(ctrl->fd, data, len);
+}
+
+static int _uart_read(struct uart_controller *ctrl,
+		      void *data, size_t len)
+{
+	int ret;
+	uint8_t *p_data = data;
+
+	while (len) {
+		ret = read(ctrl->fd, p_data, len);
+		if (ret == 0 || ret == -EAGAIN ||
+		    (ret == -1 && errno == -EAGAIN ))
+			usleep(10);
+		else if (ret < -1)
+			return ret;
+		else {
+			len -= ret;
+			p_data += ret;
+		}
+	}
+
+	return 0;
+}
+
+static int uart_read(struct interface * intf,
+		     uint16_t * cport_id, void *data, size_t len)
+{
+	int ret;
+	uint8_t *p_data = data;
+	struct uart_controller *ctrl = intf->ctrl->priv;
+
+	ret = _uart_read(ctrl, p_data, sizeof(struct gb_operation_msg_hdr));
+	if (ret) {
+		pr_err("Failed to get header\n");
+		return ret;
+	}
+
+	ret = gb_operation_msg_size(data);
+	if (ret > len) {
+		pr_err("Message to big\n");
+		return -EMSGSIZE;	/* FIXME: drop remaining data */
+	}
+
+	p_data += sizeof(struct gb_operation_msg_hdr);
+	len = ret - sizeof(struct gb_operation_msg_hdr);
+	ret = _uart_read(ctrl, p_data, len);
+	if (ret) {
+		pr_err("Failed to get the payload\n");
+		return ret;
+	}
+
+	*cport_id = cport_unpack(data);
+
+	return len + sizeof(struct gb_operation_msg_hdr);
+}
+
+struct controller uart_controller = {
+	.name = "uart",
+	.init = uart_init,
+	.exit = uart_exit,
+	.write = uart_write,
+	.intf_read = uart_read,
+	.event_loop = uart_hotplug,
+};
\ No newline at end of file
diff --git a/uart.h b/uart.h
new file mode 100644
index 0000000000000000000000000000000000000000..289a9438b3238eafc1e71ce5b296617474d8d45e
--- /dev/null
+++ b/uart.h
@@ -0,0 +1,36 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ * Author: Alexandre Bailon <abailon@baylibre.com>
+ * Copyright (c) 2016 Alexandre Bailon
+ */
+
+#ifndef _UART_H_
+#define _UART_H_
+
+#include <config.h>
+#include <debug.h>
+
+#ifdef HAVE_UART
+int register_uart_controller(const char *file_name, int baudrate);
+#else
+int register_uart_controller(const char *file_name, int baudrate)
+{
+	pr_err("UART support has not been compiled.\n");
+
+	return -1;
+}
+#endif
+
+#endif /* _UART_H_ */
\ No newline at end of file