FP2-15: create Product ID for FP2 project

Change-Id: Ia7290f1516b3397590be838f6311a902fbe323b8
diff --git a/AndroidBoot.mk b/AndroidBoot.mk
index 6836163..90801f4 100644
--- a/AndroidBoot.mk
+++ b/AndroidBoot.mk
@@ -7,10 +7,14 @@
   SIGNED_KERNEL := SIGNED_KERNEL=0
 endif
 
-ifeq ($(call is-board-platform,msm8660),true)
-  BOOTLOADER_PLATFORM := msm8660_surf
+ifneq ($(strip $(TARGET_BOOTLOADER_PLATFORM_OVERRIDE)),)
+      BOOTLOADER_PLATFORM := $(TARGET_BOOTLOADER_PLATFORM_OVERRIDE)
 else
-  BOOTLOADER_PLATFORM := $(TARGET_BOARD_PLATFORM)
+      ifeq ($(call is-board-platform,msm8660),true)
+           BOOTLOADER_PLATFORM := msm8660_surf
+      else
+           BOOTLOADER_PLATFORM := $(TARGET_BOARD_PLATFORM)
+      endif
 endif
 
 # NAND variant output
diff --git a/project/fairphone.mk b/project/fairphone.mk
new file mode 100644
index 0000000..d8d9ab6
--- /dev/null
+++ b/project/fairphone.mk
@@ -0,0 +1,40 @@
+# top level project rules for the msm8974 project
+#
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+TARGET := fairphone
+
+MODULES += app/aboot
+
+ifeq ($(TARGET_BUILD_VARIANT),user)
+DEBUG := 0
+else
+DEBUG := 1
+endif
+
+EMMC_BOOT := 1
+ENABLE_SDHCI_SUPPORT := 1
+
+#DEFINES += WITH_DEBUG_DCC=1
+DEFINES += WITH_DEBUG_UART=1
+#DEFINES += WITH_DEBUG_FBCON=1
+DEFINES += DEVICE_TREE=1
+#DEFINES += MMC_BOOT_BAM=1
+DEFINES += CRYPTO_BAM=1
+DEFINES += CRYPTO_REG_ACCESS=1
+DEFINES += ABOOT_IGNORE_BOOT_HEADER_ADDRS=1
+
+#Disable thumb mode
+ENABLE_THUMB := false
+
+DEFINES += ABOOT_FORCE_KERNEL_ADDR=0x00008000
+DEFINES += ABOOT_FORCE_RAMDISK_ADDR=0x02000000
+DEFINES += ABOOT_FORCE_TAGS_ADDR=0x01e00000
+
+ifeq ($(EMMC_BOOT),1)
+DEFINES += _EMMC_BOOT=1
+endif
+
+ifeq ($(ENABLE_SDHCI_SUPPORT),1)
+DEFINES += MMC_SDHCI_SUPPORT=1
+endif
diff --git a/target/fairphone/include/target/display.h b/target/fairphone/include/target/display.h
new file mode 100644
index 0000000..b827cf6
--- /dev/null
+++ b/target/fairphone/include/target/display.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _TARGET_COPPER_DISPLAY_H
+#define _TARGET_COPPER_DISPLAY_H
+
+/*---------------------------------------------------------------------------*/
+/* HEADER files                                                              */
+/*---------------------------------------------------------------------------*/
+#include <display_resource.h>
+
+/*---------------------------------------------------------------------------*/
+/* GPIO configuration                                                        */
+/*---------------------------------------------------------------------------*/
+static struct gpio_pin reset_gpio = {
+  "pm8941_gpios", 19, 2, 1, 0, 1
+};
+
+static struct gpio_pin enable_gpio = {
+  "msmgpio", 58, 3, 1, 0, 1
+};
+
+static struct gpio_pin pwm_gpio = {
+  "pm8941_gpios", 36, 3, 1, 0, 1
+};
+
+/*---------------------------------------------------------------------------*/
+/* LDO configuration                                                         */
+/*---------------------------------------------------------------------------*/
+static struct ldo_entry ldo_entry_array[] = {
+  { "vdd", 22, 0, 3000000, 100000, 100, 0, 20, 0, 0},
+{ "vddio", 12, 0, 1800000, 100000, 100, 0, 20, 0, 0},
+{ "vdda", 2, 1, 1200000, 100000, 100, 0, 0, 0, 0},
+};
+
+#define TOTAL_LDO_DEFINED 3
+
+/*---------------------------------------------------------------------------*/
+/* Target Physical configuration                                             */
+/*---------------------------------------------------------------------------*/
+
+static const uint32_t panel_strength_ctrl[] = {
+  0xff, 0x06
+};
+
+static const char panel_bist_ctrl[] = {
+  0x00, 0x00, 0xb1, 0xff, 0x00, 0x00
+};
+
+static const uint32_t panel_regulator_settings[] = {
+  0x07, 0x09, 0x03, 0x00, 0x20, 0x00, 0x01
+};
+
+static const char panel_lane_config[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x97,
+  0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x97,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x97,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x97,
+  0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbb
+};
+
+static const uint32_t panel_physical_ctrl[] = {
+  0x5f, 0x00, 0x00, 0x10
+};
+
+/*---------------------------------------------------------------------------*/
+/* Other Configuration                                                       */
+/*---------------------------------------------------------------------------*/
+
+#define MIPI_FB_ADDR  0x03200000
+#define EDP_FB_ADDR   MIPI_FB_ADDR
+
+#define MIPI_HSYNC_PULSE_WIDTH       12
+#define MIPI_HSYNC_BACK_PORCH_DCLK   32
+#define MIPI_HSYNC_FRONT_PORCH_DCLK  144
+
+#define MIPI_VSYNC_PULSE_WIDTH       4
+#define MIPI_VSYNC_BACK_PORCH_LINES  3
+#define MIPI_VSYNC_FRONT_PORCH_LINES 9
+
+#define PWM_BL_LPG_CHAN_ID           8
+
+extern int mdss_dsi_phy_init(struct mipi_dsi_panel_config *, uint32_t ctl_base);
+
+#endif
diff --git a/target/fairphone/init.c b/target/fairphone/init.c
new file mode 100644
index 0000000..de1fd62
--- /dev/null
+++ b/target/fairphone/init.c
@@ -0,0 +1,771 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <platform/iomap.h>
+#include <platform/irqs.h>
+#include <platform/gpio.h>
+#include <reg.h>
+#include <target.h>
+#include <platform.h>
+#include <dload_util.h>
+#include <uart_dm.h>
+#include <mmc.h>
+#include <spmi.h>
+#include <board.h>
+#include <smem.h>
+#include <baseband.h>
+#include <dev/keys.h>
+#include <pm8x41.h>
+#include <crypto5_wrapper.h>
+#include <hsusb.h>
+#include <clock.h>
+#include <partition_parser.h>
+#include <scm.h>
+#include <platform/clock.h>
+#include <platform/gpio.h>
+#include <stdlib.h>
+
+enum hw_platform_subtype
+{
+	HW_PLATFORM_SUBTYPE_CDP_INTERPOSER = 8,
+};
+
+extern  bool target_use_signed_kernel(void);
+static void set_sdc_power_ctrl();
+
+static unsigned int target_id;
+static uint32_t pmic_ver;
+
+#if MMC_SDHCI_SUPPORT
+struct mmc_device *dev;
+#endif
+
+#define PMIC_ARB_CHANNEL_NUM    0
+#define PMIC_ARB_OWNER_ID       0
+
+#define WDOG_DEBUG_DISABLE_BIT  17
+
+#define CE_INSTANCE             2
+#define CE_EE                   1
+#define CE_FIFO_SIZE            64
+#define CE_READ_PIPE            3
+#define CE_WRITE_PIPE           2
+#define CE_READ_PIPE_LOCK_GRP   0
+#define CE_WRITE_PIPE_LOCK_GRP  0
+#define CE_ARRAY_SIZE           20
+
+#ifdef SSD_ENABLE
+#define SSD_CE_INSTANCE_1       1
+#define SSD_PARTITION_SIZE      8192
+#endif
+
+#define FASTBOOT_MODE           0x77665500
+
+#define BOARD_SOC_VERSION1(soc_rev) (soc_rev >= 0x10000 && soc_rev < 0x20000)
+
+#if MMC_SDHCI_SUPPORT
+static uint32_t mmc_sdhci_base[] =
+	{ MSM_SDC1_SDHCI_BASE, MSM_SDC2_SDHCI_BASE, MSM_SDC3_SDHCI_BASE, MSM_SDC4_SDHCI_BASE };
+#endif
+
+static uint32_t mmc_sdc_base[] =
+	{ MSM_SDC1_BASE, MSM_SDC2_BASE, MSM_SDC3_BASE, MSM_SDC4_BASE };
+
+static uint32_t mmc_sdc_pwrctl_irq[] =
+	{ SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ, SDCC3_PWRCTL_IRQ, SDCC4_PWRCTL_IRQ };
+
+void target_early_init(void)
+{
+#if WITH_DEBUG_UART
+	uart_dm_init(1, 0, BLSP1_UART1_BASE);
+#endif
+}
+
+/* Check for 8974 chip */
+static int target_is_8974()
+{
+	uint32_t platform = board_platform_id();
+	int ret = 0;
+
+	switch(platform)
+	{
+		case APQ8074:
+		case MSM8274:
+		case MSM8674:
+		case MSM8974:
+			ret = 1;
+			break;
+		default:
+			ret = 0;
+	};
+
+	return ret;
+}
+
+/* Return 1 if vol_up pressed */
+static int target_volume_up()
+{
+	uint8_t status = 0;
+	struct pm8x41_gpio gpio;
+
+	/* CDP vol_up seems to be always grounded. So gpio status is read as 0,
+	 * whether key is pressed or not.
+	 * Ignore volume_up key on CDP for now.
+	 */
+	if (board_hardware_id() == HW_PLATFORM_SURF)
+		return 0;
+
+	/* Configure the GPIO */
+	gpio.direction = PM_GPIO_DIR_IN;
+	gpio.function  = 0;
+	gpio.pull      = PM_GPIO_PULL_UP_30;
+	gpio.vin_sel   = 2;
+
+	pm8x41_gpio_config(5, &gpio);
+
+	/* Wait for the pmic gpio config to take effect */
+	thread_sleep(1);
+
+	/* Get status of P_GPIO_5 */
+	pm8x41_gpio_get(5, &status);
+
+	return !status; /* active low */
+}
+
+/* Return 1 if vol_down pressed */
+uint32_t target_volume_down()
+{
+	/* Volume down button is tied in with RESIN on MSM8974. */
+	if (target_is_8974() && (pmic_ver == PM8X41_VERSION_V2))
+		return pm8x41_v2_resin_status();
+	else
+		return pm8x41_resin_status();
+}
+
+static void target_keystatus()
+{
+	keys_init();
+
+	if(target_volume_down())
+		keys_post_event(KEY_VOLUMEDOWN, 1);
+
+	if(target_volume_up())
+		keys_post_event(KEY_VOLUMEUP, 1);
+}
+
+/* Set up params for h/w CE. */
+void target_crypto_init_params()
+{
+	struct crypto_init_params ce_params;
+
+	/* Set up base addresses and instance. */
+	ce_params.crypto_instance  = CE_INSTANCE;
+	ce_params.crypto_base      = MSM_CE2_BASE;
+	ce_params.bam_base         = MSM_CE2_BAM_BASE;
+
+	/* Set up BAM config. */
+	ce_params.bam_ee               = CE_EE;
+	ce_params.pipes.read_pipe      = CE_READ_PIPE;
+	ce_params.pipes.write_pipe     = CE_WRITE_PIPE;
+	ce_params.pipes.read_pipe_grp  = CE_READ_PIPE_LOCK_GRP;
+	ce_params.pipes.write_pipe_grp = CE_WRITE_PIPE_LOCK_GRP;
+
+	/* Assign buffer sizes. */
+	ce_params.num_ce           = CE_ARRAY_SIZE;
+	ce_params.read_fifo_size   = CE_FIFO_SIZE;
+	ce_params.write_fifo_size  = CE_FIFO_SIZE;
+
+	/* BAM is initialized by TZ for this platform.
+	 * Do not do it again as the initialization address space
+	 * is locked.
+	 */
+	ce_params.do_bam_init      = 0;
+
+	crypto_init_params(&ce_params);
+}
+
+crypto_engine_type board_ce_type(void)
+{
+	return CRYPTO_ENGINE_TYPE_HW;
+}
+
+#if MMC_SDHCI_SUPPORT
+static void target_mmc_sdhci_init()
+{
+	struct mmc_config_data config = {0};
+	uint32_t soc_ver = 0;
+
+	soc_ver = board_soc_version();
+
+	/*
+	 * 8974 v1 fluid devices, have a hardware bug
+	 * which limits the bus width to 4 bit.
+	 */
+	switch(board_hardware_id())
+	{
+		case HW_PLATFORM_FLUID:
+			if (target_is_8974() && BOARD_SOC_VERSION1(soc_ver))
+				config.bus_width = DATA_BUS_WIDTH_4BIT;
+			else
+				config.bus_width = DATA_BUS_WIDTH_8BIT;
+			break;
+		default:
+			config.bus_width = DATA_BUS_WIDTH_8BIT;
+	};
+
+	/* Trying Slot 1*/
+	config.slot = 1;
+	/*
+	 * For 8974 AC platform the software clock
+	 * plan recommends to use the following frequencies:
+	 * 200 MHz --> 192 MHZ
+	 * 400 MHZ --> 384 MHZ
+	 * only for emmc slot
+	 */
+	if (platform_is_8974ac())
+		config.max_clk_rate = MMC_CLK_192MHZ;
+	else
+		config.max_clk_rate = MMC_CLK_200MHZ;
+	config.sdhc_base = mmc_sdhci_base[config.slot - 1];
+	config.pwrctl_base = mmc_sdc_base[config.slot - 1];
+	config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];
+
+	if (!(dev = mmc_init(&config))) {
+		/* Trying Slot 2 next */
+		config.slot = 2;
+		config.max_clk_rate = MMC_CLK_200MHZ;
+		config.sdhc_base = mmc_sdhci_base[config.slot - 1];
+		config.pwrctl_base = mmc_sdc_base[config.slot - 1];
+		config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];
+
+		if (!(dev = mmc_init(&config))) {
+			dprintf(CRITICAL, "mmc init failed!");
+			ASSERT(0);
+		}
+	}
+
+	/*
+	 * MMC initialization is complete, read the partition table info
+	 */
+	if (partition_read_table()) {
+		dprintf(CRITICAL, "Error reading the partition table info\n");
+		ASSERT(0);
+	}
+}
+
+struct mmc_device *target_mmc_device()
+{
+	return dev;
+}
+
+#else
+static void target_mmc_mci_init()
+{
+	uint32_t base_addr;
+	uint8_t slot;
+
+	/* Trying Slot 1 */
+	slot = 1;
+	base_addr = mmc_sdc_base[slot - 1];
+
+	if (mmc_boot_main(slot, base_addr))
+	{
+		/* Trying Slot 2 next */
+		slot = 2;
+		base_addr = mmc_sdc_base[slot - 1];
+		if (mmc_boot_main(slot, base_addr)) {
+			dprintf(CRITICAL, "mmc init failed!");
+			ASSERT(0);
+		}
+	}
+}
+
+/*
+ * Function to set the capabilities for the host
+ */
+void target_mmc_caps(struct mmc_host *host)
+{
+	uint32_t soc_ver = 0;
+
+	soc_ver = board_soc_version();
+
+	/*
+	 * 8974 v1 fluid devices, have a hardware bug
+	 * which limits the bus width to 4 bit.
+	 */
+	switch(board_hardware_id())
+	{
+		case HW_PLATFORM_FLUID:
+			if (target_is_8974() && BOARD_SOC_VERSION1(soc_ver))
+				host->caps.bus_width = MMC_BOOT_BUS_WIDTH_4_BIT;
+			else
+				host->caps.bus_width = MMC_BOOT_BUS_WIDTH_8_BIT;
+			break;
+		default:
+			host->caps.bus_width = MMC_BOOT_BUS_WIDTH_8_BIT;
+	};
+
+	host->caps.ddr_mode = 1;
+	host->caps.hs200_mode = 1;
+	host->caps.hs_clk_rate = MMC_CLK_96MHZ;
+}
+#endif
+
+
+void target_init(void)
+{
+	dprintf(INFO, "target_init()\n");
+
+	spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
+
+	/* Save PM8941 version info. */
+	pmic_ver = pm8x41_get_pmic_rev();
+
+	target_keystatus();
+
+	if (target_use_signed_kernel())
+		target_crypto_init_params();
+
+	/*
+	 * Set drive strength & pull ctrl for
+	 * emmc
+	 */
+	set_sdc_power_ctrl();
+
+#if MMC_SDHCI_SUPPORT
+	target_mmc_sdhci_init();
+#else
+	target_mmc_mci_init();
+#endif
+}
+
+unsigned board_machtype(void)
+{
+	return target_id;
+}
+
+/* Do any target specific intialization needed before entering fastboot mode */
+#ifdef SSD_ENABLE
+static void ssd_load_keystore_from_emmc()
+{
+	uint64_t           ptn    = 0;
+	int                index  = -1;
+	uint32_t           size   = SSD_PARTITION_SIZE;
+	int                ret    = -1;
+
+	uint32_t *buffer = (uint32_t *)memalign(CACHE_LINE,
+								   ROUNDUP(SSD_PARTITION_SIZE, CACHE_LINE));
+
+	if (!buffer) {
+		dprintf(CRITICAL, "Error Allocating memory for SSD buffer\n");
+		ASSERT(0);
+	}
+
+	index = partition_get_index("ssd");
+
+	ptn   = partition_get_offset(index);
+	if(ptn == 0){
+		dprintf(CRITICAL,"ERROR: ssd parition not found");
+		return;
+	}
+
+	if(mmc_read(ptn, buffer, size)){
+		dprintf(CRITICAL,"ERROR:Cannot read data\n");
+		return;
+	}
+
+	ret = scm_protect_keystore((uint32_t *)&buffer[0],size);
+	if(ret != 0)
+		dprintf(CRITICAL,"ERROR: scm_protect_keystore Failed");
+
+	free(buffer);
+}
+#endif
+
+void target_fastboot_init(void)
+{
+	/* Set the BOOT_DONE flag in PM8921 */
+	pm8x41_set_boot_done();
+
+#ifdef SSD_ENABLE
+	clock_ce_enable(SSD_CE_INSTANCE_1);
+	ssd_load_keystore_from_emmc();
+#endif
+}
+
+/* Detect the target type */
+void target_detect(struct board_data *board)
+{
+	board->target = LINUX_MACHTYPE_UNKNOWN;
+}
+
+/* Detect the modem type */
+void target_baseband_detect(struct board_data *board)
+{
+	uint32_t platform;
+	uint32_t platform_subtype;
+
+	platform = board->platform;
+
+	switch(platform) {
+	case MSM8974:
+	case MSM8274:
+	case MSM8674:
+	case MSM8274AA:
+	case MSM8274AB:
+	case MSM8274AC:
+	case MSM8674AA:
+	case MSM8674AB:
+	case MSM8674AC:
+	case MSM8974AA:
+	case MSM8974AB:
+	case MSM8974AC:
+	case MSMSAMARIUM2:
+	case MSMSAMARIUM9:
+		board->baseband = BASEBAND_MSM;
+		break;
+	case APQ8074:
+	case APQ8074AA:
+	case APQ8074AB:
+	case APQ8074AC:
+	case MSMSAMARIUM0:
+		board->baseband = BASEBAND_APQ;
+		break;
+	default:
+		dprintf(CRITICAL, "Platform type: %u is not supported\n",platform);
+		ASSERT(0);
+	};
+}
+
+unsigned target_baseband()
+{
+	return board_baseband();
+}
+
+void target_serialno(unsigned char *buf)
+{
+	unsigned int serialno;
+	if (target_is_emmc_boot()) {
+		serialno = mmc_get_psn();
+		snprintf((char *)buf, 13, "%x", serialno);
+	}
+}
+
+unsigned check_reboot_mode(void)
+{
+	uint32_t restart_reason = 0;
+	uint32_t soc_ver = 0;
+	uint32_t restart_reason_addr;
+
+	soc_ver = board_soc_version();
+
+	if (target_is_8974() && BOARD_SOC_VERSION1(soc_ver))
+		restart_reason_addr = RESTART_REASON_ADDR;
+	else
+		restart_reason_addr = RESTART_REASON_ADDR_V2;
+
+	/* Read reboot reason and scrub it */
+	restart_reason = readl(restart_reason_addr);
+	writel(0x00, restart_reason_addr);
+
+	return restart_reason;
+}
+
+void reboot_device(unsigned reboot_reason)
+{
+	uint32_t soc_ver = 0;
+	uint8_t reset_type = 0;
+
+	soc_ver = board_soc_version();
+
+	/* Write the reboot reason */
+	if (target_is_8974() && BOARD_SOC_VERSION1(soc_ver))
+		writel(reboot_reason, RESTART_REASON_ADDR);
+	else
+		writel(reboot_reason, RESTART_REASON_ADDR_V2);
+
+	if(reboot_reason == FASTBOOT_MODE)
+		reset_type = PON_PSHOLD_WARM_RESET;
+	else
+		reset_type = PON_PSHOLD_HARD_RESET;
+
+	/* Configure PMIC for warm reset */
+	if (target_is_8974() && (pmic_ver == PM8X41_VERSION_V2))
+		pm8x41_v2_reset_configure(reset_type);
+	else
+		pm8x41_reset_configure(reset_type);
+
+	/* Drop PS_HOLD for MSM */
+	writel(0x00, MPM2_MPM_PS_HOLD);
+
+	mdelay(5000);
+
+	dprintf(CRITICAL, "Rebooting failed\n");
+}
+
+int set_download_mode(enum dload_mode mode)
+{
+	dload_util_write_cookie(mode == NORMAL_DLOAD ?
+		DLOAD_MODE_ADDR_V2 : EMERGENCY_DLOAD_MODE_ADDR_V2, mode);
+
+	return 0;
+}
+
+/* Check if MSM needs VBUS mimic for USB */
+static int target_needs_vbus_mimic()
+{
+	if (target_is_8974())
+		return 0;
+
+	return 1;
+}
+
+/* Do target specific usb initialization */
+void target_usb_init(void)
+{
+	uint32_t val;
+
+	/* Enable secondary USB PHY on DragonBoard8074 */
+	if (board_hardware_id() == HW_PLATFORM_DRAGON) {
+		/* Route ChipIDea to use secondary USB HS port2 */
+		writel_relaxed(1, USB2_PHY_SEL);
+
+		/* Enable access to secondary PHY by clamping the low
+		* voltage interface between DVDD of the PHY and Vddcx
+		* (set bit16 (USB2_PHY_HS2_DIG_CLAMP_N_2) = 1) */
+		writel_relaxed(readl_relaxed(USB_OTG_HS_PHY_SEC_CTRL)
+				| 0x00010000, USB_OTG_HS_PHY_SEC_CTRL);
+
+		/* Perform power-on-reset of the PHY.
+		*  Delay values are arbitrary */
+		writel_relaxed(readl_relaxed(USB_OTG_HS_PHY_CTRL)|1,
+				USB_OTG_HS_PHY_CTRL);
+		thread_sleep(10);
+		writel_relaxed(readl_relaxed(USB_OTG_HS_PHY_CTRL) & 0xFFFFFFFE,
+				USB_OTG_HS_PHY_CTRL);
+		thread_sleep(10);
+
+		/* Enable HSUSB PHY port for ULPI interface,
+		* then configure related parameters within the PHY */
+		writel_relaxed(((readl_relaxed(USB_PORTSC) & 0xC0000000)
+				| 0x8c000004), USB_PORTSC);
+	}
+
+	if (target_needs_vbus_mimic())
+	{
+		/* Select and enable external configuration with USB PHY */
+		ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);
+
+		/* Enable sess_vld */
+		val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
+		writel(val, USB_GENCONFIG_2);
+
+		/* Enable external vbus configuration in the LINK */
+		val = readl(USB_USBCMD);
+		val |= SESS_VLD_CTRL;
+		writel(val, USB_USBCMD);
+	}
+}
+
+uint8_t target_panel_auto_detect_enabled()
+{
+	switch(board_hardware_id())
+	{
+		case HW_PLATFORM_SURF:
+		case HW_PLATFORM_MTP:
+		case HW_PLATFORM_FLUID:
+			return 1;
+			break;
+		default:
+			return 0;
+			break;
+	}
+	return 0;
+}
+
+uint8_t target_is_edp()
+{
+	switch(board_hardware_id())
+	{
+		case HW_PLATFORM_LIQUID:
+			return 1;
+			break;
+		default:
+			return 0;
+			break;
+	}
+	return 0;
+}
+
+static uint8_t splash_override;
+/* Returns 1 if target supports continuous splash screen. */
+int target_cont_splash_screen()
+{
+	uint8_t splash_screen = 0;
+	if(!splash_override) {
+		switch(board_hardware_id())
+		{
+			case HW_PLATFORM_SURF:
+			case HW_PLATFORM_MTP:
+			case HW_PLATFORM_FLUID:
+			case HW_PLATFORM_DRAGON:
+			case HW_PLATFORM_LIQUID:
+				dprintf(SPEW, "Target_cont_splash=1\n");
+				splash_screen = 1;
+				break;
+			default:
+				dprintf(SPEW, "Target_cont_splash=0\n");
+				splash_screen = 0;
+		}
+	}
+	return splash_screen;
+}
+
+void target_force_cont_splash_disable(uint8_t override)
+{
+	splash_override = override;
+}
+
+unsigned target_pause_for_battery_charge(void)
+{
+	uint8_t pon_reason = pm8x41_get_pon_reason();
+
+        /* This function will always return 0 to facilitate
+         * automated testing/reboot with usb connected.
+         * uncomment if this feature is needed */
+	/* if ((pon_reason == USB_CHG) || (pon_reason == DC_CHG))
+		return 1;*/
+
+	return 0;
+}
+
+void target_uninit(void)
+{
+#if MMC_SDHCI_SUPPORT
+	mmc_put_card_to_sleep(dev);
+#else
+	mmc_put_card_to_sleep();
+#endif
+#ifdef SSD_ENABLE
+	clock_ce_disable(SSD_CE_INSTANCE_1);
+#endif
+	if (crypto_initialized())
+		crypto_eng_cleanup();
+
+	/* Disable HC mode before jumping to kernel */
+	sdhci_mode_disable(&dev->host);
+}
+
+void shutdown_device()
+{
+	dprintf(CRITICAL, "Going down for shutdown.\n");
+
+	/* Configure PMIC for shutdown. */
+	if (target_is_8974() && (pmic_ver == PM8X41_VERSION_V2))
+		pm8x41_v2_reset_configure(PON_PSHOLD_SHUTDOWN);
+	else
+		pm8x41_reset_configure(PON_PSHOLD_SHUTDOWN);
+
+	/* Drop PS_HOLD for MSM */
+	writel(0x00, MPM2_MPM_PS_HOLD);
+
+	mdelay(5000);
+
+	dprintf(CRITICAL, "Shutdown failed\n");
+}
+
+static void set_sdc_power_ctrl()
+{
+	uint8_t tlmm_hdrv_clk = 0;
+	uint32_t platform_id = 0;
+
+	platform_id = board_platform_id();
+
+	switch(platform_id)
+	{
+		case MSM8274AA:
+		case MSM8274AB:
+		case MSM8674AA:
+		case MSM8674AB:
+		case MSM8974AA:
+		case MSM8974AB:
+			if (board_hardware_id() == HW_PLATFORM_MTP)
+				tlmm_hdrv_clk = TLMM_CUR_VAL_10MA;
+			else
+				tlmm_hdrv_clk = TLMM_CUR_VAL_16MA;
+			break;
+		default:
+			tlmm_hdrv_clk = TLMM_CUR_VAL_16MA;
+	};
+
+	/* Drive strength configs for sdc pins */
+	struct tlmm_cfgs sdc1_hdrv_cfg[] =
+	{
+		{ SDC1_CLK_HDRV_CTL_OFF,  tlmm_hdrv_clk, TLMM_HDRV_MASK },
+		{ SDC1_CMD_HDRV_CTL_OFF,  TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
+		{ SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
+	};
+
+	/* Pull configs for sdc pins */
+	struct tlmm_cfgs sdc1_pull_cfg[] =
+	{
+		{ SDC1_CLK_PULL_CTL_OFF,  TLMM_NO_PULL, TLMM_PULL_MASK },
+		{ SDC1_CMD_PULL_CTL_OFF,  TLMM_PULL_UP, TLMM_PULL_MASK },
+		{ SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK },
+	};
+
+	struct tlmm_cfgs sdc1_rclk_cfg[] =
+	{
+		{ SDC1_RCLK_PULL_CTL_OFF, TLMM_PULL_DOWN, TLMM_PULL_MASK },
+	};
+
+	/* Set the drive strength & pull control values */
+	tlmm_set_hdrive_ctrl(sdc1_hdrv_cfg, ARRAY_SIZE(sdc1_hdrv_cfg));
+	tlmm_set_pull_ctrl(sdc1_pull_cfg, ARRAY_SIZE(sdc1_pull_cfg));
+
+	/* RCLK is supported only with 8974 pro, set rclk to pull down
+	 * only for 8974 pro targets
+	 */
+	if (!platform_is_8974())
+		tlmm_set_pull_ctrl(sdc1_rclk_cfg, ARRAY_SIZE(sdc1_rclk_cfg));
+}
+
+int emmc_recovery_init(void)
+{
+	return _emmc_recovery_init();
+}
+
+void target_usb_stop(void)
+{
+	uint32_t platform = board_platform_id();
+
+	/* Disable VBUS mimicing in the controller. */
+	if (target_needs_vbus_mimic())
+		ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_CLEAR);
+}
diff --git a/target/fairphone/meminfo.c b/target/fairphone/meminfo.c
new file mode 100644
index 0000000..086c080
--- /dev/null
+++ b/target/fairphone/meminfo.c
@@ -0,0 +1,89 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if DEVICE_TREE /* If using device tree */
+
+#include <reg.h>
+#include <debug.h>
+#include <malloc.h>
+#include <smem.h>
+#include <stdint.h>
+#include <libfdt.h>
+#include <platform/iomap.h>
+#include <dev_tree.h>
+
+/* Funtion to add the ram partition entries into device tree.
+ * The function assumes that all the entire fixed memory regions should
+ * be listed in the first bank of the passed in ddr regions.
+ */
+uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset)
+{
+    struct smem_ram_ptable ram_ptable;
+    unsigned int i;
+	int ret = 0;
+
+	/* Make sure RAM partition table is initialized */
+	ASSERT(smem_ram_ptable_init(&ram_ptable));
+
+     /* Calculating the size of the mem_info_ptr */
+    for (i = 0 ; i < ram_ptable.len; i++)
+    {
+        if((ram_ptable.parts[i].category == SDRAM) &&
+           (ram_ptable.parts[i].type == SYS_MEMORY))
+        {
+
+			/* Pass along all other usable memory regions to Linux */
+			ret = dev_tree_add_mem_info(fdt,
+										memory_node_offset,
+										ram_ptable.parts[i].start,
+										ram_ptable.parts[i].size);
+
+			if (ret)
+			{
+				dprintf(CRITICAL, "Failed to add secondary banks memory addresses\n");
+				goto target_dev_tree_mem_err;
+			}
+
+       }
+    }
+
+target_dev_tree_mem_err:
+
+    return ret;
+}
+
+void *target_get_scratch_address(void)
+{
+	return ((void *)SCRATCH_ADDR);
+}
+
+unsigned target_get_max_flash_size(void)
+{
+	return (512 * 1024 * 1024);
+}
+#endif /* DEVICE_TREE */
diff --git a/target/fairphone/oem_panel.c b/target/fairphone/oem_panel.c
new file mode 100755
index 0000000..8ff54d5
--- /dev/null
+++ b/target/fairphone/oem_panel.c
@@ -0,0 +1,308 @@
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <err.h>
+#include <smem.h>
+#include <msm_panel.h>
+#include <board.h>
+#include <mipi_dsi.h>
+
+#include "include/panel.h"
+#include "panel_display.h"
+
+/*---------------------------------------------------------------------------*/
+/* GCDB Panel Database                                                       */
+/*---------------------------------------------------------------------------*/
+#include "include/panel_toshiba_720p_video.h"
+#include "include/panel_sharp_qhd_video.h"
+#include "include/panel_jdi_1080p_video.h"
+#include "include/panel_generic_720p_cmd.h"
+#include "include/panel_jdi_qhd_dualdsi_video.h"
+#include "include/panel_jdi_qhd_dualdsi_cmd.h"
+
+#define DISPLAY_MAX_PANEL_DETECTION 3
+
+/*---------------------------------------------------------------------------*/
+/* static panel selection variable                                           */
+/*---------------------------------------------------------------------------*/
+enum {
+JDI_1080P_VIDEO_PANEL,
+TOSHIBA_720P_VIDEO_PANEL,
+SHARP_QHD_VIDEO_PANEL,
+GENERIC_720P_CMD_PANEL,
+JDI_QHD_DUALDSI_VIDEO_PANEL,
+JDI_QHD_DUALDSI_CMD_PANEL,
+UNKNOWN_PANEL
+};
+
+/*
+ * The list of panels that are supported on this target.
+ * Any panel in this list can be selected using fastboot oem command.
+ */
+static struct panel_list supp_panels[] = {
+	{"jdi_1080p_video", JDI_1080P_VIDEO_PANEL},
+	{"toshiba_720p_video", TOSHIBA_720P_VIDEO_PANEL},
+	{"sharp_qhd_video", SHARP_QHD_VIDEO_PANEL},
+	{"generic_720p_cmd", GENERIC_720P_CMD_PANEL},
+	{"jdi_qhd_dualdsi_video", JDI_QHD_DUALDSI_VIDEO_PANEL},
+	{"jdi_qhd_dualdsi_cmd", JDI_QHD_DUALDSI_CMD_PANEL},
+};
+
+static uint32_t panel_id;
+
+int oem_panel_rotation()
+{
+	/* OEM can keep there panel spefic on instructions in this
+	function */
+	return NO_ERROR;
+}
+
+
+int oem_panel_on()
+{
+	/* OEM can keep there panel spefic on instructions in this
+	function */
+	return NO_ERROR;
+}
+
+int oem_panel_off()
+{
+	/* OEM can keep there panel spefic off instructions in this
+	function */
+	return NO_ERROR;
+}
+
+static void init_panel_data(struct panel_struct *panelstruct,
+			struct msm_panel_info *pinfo,
+			struct mdss_dsi_phy_ctrl *phy_db)
+{
+	switch (panel_id) {
+	case TOSHIBA_720P_VIDEO_PANEL:
+		panelstruct->paneldata    = &toshiba_720p_video_panel_data;
+		panelstruct->panelres     = &toshiba_720p_video_panel_res;
+		panelstruct->color        = &toshiba_720p_video_color;
+		panelstruct->videopanel   = &toshiba_720p_video_video_panel;
+		panelstruct->commandpanel = &toshiba_720p_video_command_panel;
+		panelstruct->state        = &toshiba_720p_video_state;
+		panelstruct->laneconfig   = &toshiba_720p_video_lane_config;
+		panelstruct->paneltiminginfo
+					 = &toshiba_720p_video_timing_info;
+		panelstruct->panelresetseq
+					 = &toshiba_720p_video_panel_reset_seq;
+		panelstruct->backlightinfo = &toshiba_720p_video_backlight;
+		pinfo->mipi.panel_cmds
+					= toshiba_720p_video_on_command;
+		pinfo->mipi.num_of_panel_cmds
+					= TOSHIBA_720P_VIDEO_ON_COMMAND;
+		memcpy(phy_db->timing,
+			toshiba_720p_video_timings, TIMING_SIZE);
+		pinfo->mipi.signature 	= TOSHIBA_720P_VIDEO_SIGNATURE;
+		break;
+	case SHARP_QHD_VIDEO_PANEL:
+		panelstruct->paneldata    = &sharp_qhd_video_panel_data;
+		panelstruct->panelres     = &sharp_qhd_video_panel_res;
+		panelstruct->color        = &sharp_qhd_video_color;
+		panelstruct->videopanel   = &sharp_qhd_video_video_panel;
+		panelstruct->commandpanel = &sharp_qhd_video_command_panel;
+		panelstruct->state        = &sharp_qhd_video_state;
+		panelstruct->laneconfig   = &sharp_qhd_video_lane_config;
+		panelstruct->paneltiminginfo
+					 = &sharp_qhd_video_timing_info;
+		panelstruct->panelresetseq
+					 = &sharp_qhd_video_panel_reset_seq;
+		panelstruct->backlightinfo = &sharp_qhd_video_backlight;
+		pinfo->mipi.panel_cmds
+					= sharp_qhd_video_on_command;
+		pinfo->mipi.num_of_panel_cmds
+					= SHARP_QHD_VIDEO_ON_COMMAND;
+		memcpy(phy_db->timing,
+				sharp_qhd_video_timings, TIMING_SIZE);
+		break;
+	case JDI_1080P_VIDEO_PANEL:
+		panelstruct->paneldata    = &jdi_1080p_video_panel_data;
+		panelstruct->panelres     = &jdi_1080p_video_panel_res;
+		panelstruct->color        = &jdi_1080p_video_color;
+		panelstruct->videopanel   = &jdi_1080p_video_video_panel;
+		panelstruct->commandpanel = &jdi_1080p_video_command_panel;
+		panelstruct->state        = &jdi_1080p_video_state;
+		panelstruct->laneconfig   = &jdi_1080p_video_lane_config;
+		panelstruct->paneltiminginfo
+			= &jdi_1080p_video_timing_info;
+		panelstruct->panelresetseq
+					 = &jdi_1080p_video_panel_reset_seq;
+		panelstruct->backlightinfo = &jdi_1080p_video_backlight;
+		pinfo->mipi.panel_cmds
+			= jdi_1080p_video_on_command;
+		pinfo->mipi.num_of_panel_cmds
+			= JDI_1080P_VIDEO_ON_COMMAND;
+		memcpy(phy_db->timing,
+			jdi_1080p_video_timings, TIMING_SIZE);
+		pinfo->mipi.signature = JDI_1080P_VIDEO_SIGNATURE;
+		break;
+	case GENERIC_720P_CMD_PANEL:
+		panelstruct->paneldata    = &generic_720p_cmd_panel_data;
+		panelstruct->panelres     = &generic_720p_cmd_panel_res;
+		panelstruct->color        = &generic_720p_cmd_color;
+		panelstruct->videopanel   = &generic_720p_cmd_video_panel;
+		panelstruct->commandpanel = &generic_720p_cmd_command_panel;
+		panelstruct->state        = &generic_720p_cmd_state;
+		panelstruct->laneconfig   = &generic_720p_cmd_lane_config;
+		panelstruct->paneltiminginfo
+			= &generic_720p_cmd_timing_info;
+		panelstruct->panelresetseq
+					 = &generic_720p_cmd_reset_seq;
+		panelstruct->backlightinfo = &generic_720p_cmd_backlight;
+		pinfo->mipi.panel_cmds
+			= generic_720p_cmd_on_command;
+		pinfo->mipi.num_of_panel_cmds
+			= GENERIC_720P_CMD_ON_COMMAND;
+		memcpy(phy_db->timing,
+			generic_720p_cmd_timings, TIMING_SIZE);
+		pinfo->mipi.signature = GENERIC_720P_CMD_SIGNATURE;
+		break;
+	case JDI_QHD_DUALDSI_VIDEO_PANEL:
+		panelstruct->paneldata    = &jdi_qhd_dualdsi_video_panel_data;
+		panelstruct->panelres     = &jdi_qhd_dualdsi_video_panel_res;
+		panelstruct->color        = &jdi_qhd_dualdsi_video_color;
+		panelstruct->videopanel   = &jdi_qhd_dualdsi_video_video_panel;
+		panelstruct->commandpanel = &jdi_qhd_dualdsi_video_command_panel;
+		panelstruct->state        = &jdi_qhd_dualdsi_video_state;
+		panelstruct->laneconfig   = &jdi_qhd_dualdsi_video_lane_config;
+		panelstruct->paneltiminginfo
+			= &jdi_qhd_dualdsi_video_timing_info;
+		panelstruct->panelresetseq
+					 = &jdi_qhd_dualdsi_video_reset_seq;
+		panelstruct->backlightinfo = &jdi_qhd_dualdsi_video_backlight;
+		pinfo->mipi.panel_cmds
+			= jdi_qhd_dualdsi_video_on_command;
+		pinfo->mipi.num_of_panel_cmds
+			= JDI_QHD_DUALDSI_VIDEO_ON_COMMAND;
+		memcpy(phy_db->timing,
+			jdi_qhd_dualdsi_video_timings, TIMING_SIZE);
+		break;
+	case JDI_QHD_DUALDSI_CMD_PANEL:
+		panelstruct->paneldata    = &jdi_qhd_dualdsi_cmd_panel_data;
+		panelstruct->panelres     = &jdi_qhd_dualdsi_cmd_panel_res;
+		panelstruct->color        = &jdi_qhd_dualdsi_cmd_color;
+		panelstruct->videopanel   = &jdi_qhd_dualdsi_cmd_video_panel;
+		panelstruct->commandpanel = &jdi_qhd_dualdsi_cmd_command_panel;
+		panelstruct->state        = &jdi_qhd_dualdsi_cmd_state;
+		panelstruct->laneconfig   = &jdi_qhd_dualdsi_cmd_lane_config;
+		panelstruct->paneltiminginfo
+			= &jdi_qhd_dualdsi_cmd_timing_info;
+		panelstruct->panelresetseq
+					 = &jdi_qhd_dualdsi_cmd_reset_seq;
+		panelstruct->backlightinfo = &jdi_qhd_dualdsi_cmd_backlight;
+		pinfo->mipi.panel_cmds
+			= jdi_qhd_dualdsi_cmd_on_command;
+		pinfo->mipi.num_of_panel_cmds
+			= JDI_QHD_DUALDSI_CMD_ON_COMMAND;
+		memcpy(phy_db->timing,
+			jdi_qhd_dualdsi_cmd_timings, TIMING_SIZE);
+		break;
+	case UNKNOWN_PANEL:
+		memset(panelstruct, 0, sizeof(struct panel_struct));
+		memset(pinfo->mipi.panel_cmds, 0, sizeof(struct mipi_dsi_cmd));
+		pinfo->mipi.num_of_panel_cmds = 0;
+		memset(phy_db->timing, 0, TIMING_SIZE);
+		pinfo->mipi.signature = 0;
+		break;
+	}
+}
+
+uint32_t oem_panel_max_auto_detect_panels()
+{
+	return target_panel_auto_detect_enabled() ?
+			DISPLAY_MAX_PANEL_DETECTION : 0;
+}
+
+static uint32_t auto_pan_loop = 0;
+
+bool oem_panel_select(const char *panel_name, struct panel_struct *panelstruct,
+			struct msm_panel_info *pinfo,
+			struct mdss_dsi_phy_ctrl *phy_db)
+{
+	uint32_t hw_id = board_hardware_id();
+	uint32_t target_id = board_target_id();
+	bool ret = true;
+	int32_t panel_override_id;
+
+	if (panel_name) {
+		panel_override_id = panel_name_to_id(supp_panels,
+				ARRAY_SIZE(supp_panels), panel_name);
+
+		if (panel_override_id < 0) {
+			dprintf(CRITICAL, "Not able to search the panel:%s\n",
+					 panel_name + strspn(panel_name, " "));
+		} else if (panel_override_id < UNKNOWN_PANEL) {
+			/* panel override using fastboot oem command */
+			panel_id = panel_override_id;
+
+			dprintf(INFO, "OEM panel override:%s\n",
+					panel_name + strspn(panel_name, " "));
+			goto panel_init;
+		}
+	}
+
+	switch (hw_id) {
+	case HW_PLATFORM_MTP:
+	case HW_PLATFORM_FLUID:
+	case HW_PLATFORM_SURF:
+		switch (auto_pan_loop) {
+		case 0:
+			panel_id = JDI_1080P_VIDEO_PANEL;
+			break;
+		case 1:
+			panel_id = TOSHIBA_720P_VIDEO_PANEL;
+			break;
+		case 2:
+			panel_id = GENERIC_720P_CMD_PANEL;
+			break;
+		default:
+			panel_id = UNKNOWN_PANEL;
+			ret = false;
+			break;
+		}
+		auto_pan_loop++;
+		break;
+	case HW_PLATFORM_DRAGON:
+		panel_id = SHARP_QHD_VIDEO_PANEL;
+		break;
+	default:
+		dprintf(CRITICAL, "Display not enabled for %d HW type\n"
+					, hw_id);
+		return false;
+	}
+
+panel_init:
+	init_panel_data(panelstruct, pinfo, phy_db);
+
+	return ret;
+}
diff --git a/target/fairphone/rules.mk b/target/fairphone/rules.mk
new file mode 100644
index 0000000..ab9a431
--- /dev/null
+++ b/target/fairphone/rules.mk
@@ -0,0 +1,44 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared
+INCLUDES += -I$(LK_TOP_DIR)/dev/gcdb/display -I$(LK_TOP_DIR)/dev/gcdb/display/include
+
+PLATFORM := msm8974
+
+MEMBASE := 0x0F900000 # SDRAM
+MEMSIZE := 0x00100000 # 1MB
+
+BASE_ADDR        := 0x00000
+
+TAGS_ADDR        := BASE_ADDR+0x00000100
+KERNEL_ADDR      := BASE_ADDR+0x00008000
+RAMDISK_ADDR     := BASE_ADDR+0x01000000
+SCRATCH_ADDR     := 0x11000000
+
+DEFINES += DISPLAY_SPLASH_SCREEN=1
+DEFINES += DISPLAY_TYPE_MIPI=1
+DEFINES += DISPLAY_TYPE_DSI6G=1
+
+MODULES += \
+	dev/keys \
+	dev/pmic/pm8x41 \
+	dev/panel/msm \
+	dev/gcdb/display \
+    lib/ptable \
+    lib/libfdt
+
+DEFINES += \
+	MEMSIZE=$(MEMSIZE) \
+	MEMBASE=$(MEMBASE) \
+	BASE_ADDR=$(BASE_ADDR) \
+	TAGS_ADDR=$(TAGS_ADDR) \
+	KERNEL_ADDR=$(KERNEL_ADDR) \
+	RAMDISK_ADDR=$(RAMDISK_ADDR) \
+	SCRATCH_ADDR=$(SCRATCH_ADDR)
+
+
+OBJS += \
+    $(LOCAL_DIR)/init.o \
+    $(LOCAL_DIR)/meminfo.o \
+    $(LOCAL_DIR)/target_display.o \
+    $(LOCAL_DIR)/oem_panel.o
diff --git a/target/fairphone/target_display.c b/target/fairphone/target_display.c
new file mode 100755
index 0000000..56a03c1
--- /dev/null
+++ b/target/fairphone/target_display.c
@@ -0,0 +1,413 @@
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <smem.h>
+#include <err.h>
+#include <msm_panel.h>
+#include <mipi_dsi.h>
+#include <pm8x41.h>
+#include <pm8x41_wled.h>
+#include <board.h>
+#include <mdp5.h>
+#include <platform/gpio.h>
+#include <platform/clock.h>
+#include <platform/iomap.h>
+#include <target/display.h>
+#include "include/panel.h"
+#include "include/display_resource.h"
+
+static struct msm_fb_panel_data panel;
+static uint8_t edp_enable;
+
+#define HFPLL_LDO_ID 12
+
+static struct pm8x41_wled_data wled_ctrl = {
+	.mod_scheme      = 0x00,
+	.led1_brightness = (0x0F << 8) | 0xEF,
+	.led2_brightness = (0x0F << 8) | 0xEF,
+	.led3_brightness = (0x0F << 8) | 0xEF,
+	.max_duty_cycle  = 0x01,
+	.ovp = 0x2,
+	.full_current_scale = 0x19
+};
+
+static uint32_t dsi_pll_lock_status(uint32_t ctl_base)
+{
+	uint32_t counter, status;
+
+	udelay(100);
+	mdss_dsi_uniphy_pll_lock_detect_setting(ctl_base);
+
+	status = readl(ctl_base + 0x02c0) & 0x01;
+	for (counter = 0; counter < 5 && !status; counter++) {
+		udelay(100);
+		status = readl(ctl_base + 0x02c0) & 0x01;
+	}
+
+	return status;
+}
+
+static uint32_t dsi_pll_enable_seq_b(uint32_t ctl_base)
+{
+	mdss_dsi_uniphy_pll_sw_reset(ctl_base);
+
+	writel(0x01, ctl_base + 0x0220); /* GLB CFG */
+	udelay(1);
+	writel(0x05, ctl_base + 0x0220); /* GLB CFG */
+	udelay(200);
+	writel(0x07, ctl_base + 0x0220); /* GLB CFG */
+	udelay(500);
+	writel(0x0f, ctl_base + 0x0220); /* GLB CFG */
+	udelay(500);
+
+	return dsi_pll_lock_status(ctl_base);
+}
+
+static uint32_t dsi_pll_enable_seq_d(uint32_t ctl_base)
+{
+	mdss_dsi_uniphy_pll_sw_reset(ctl_base);
+
+	writel(0x01, ctl_base + 0x0220); /* GLB CFG */
+	udelay(1);
+	writel(0x05, ctl_base + 0x0220); /* GLB CFG */
+	udelay(200);
+	writel(0x07, ctl_base + 0x0220); /* GLB CFG */
+	udelay(250);
+	writel(0x05, ctl_base + 0x0220); /* GLB CFG */
+	udelay(200);
+	writel(0x07, ctl_base + 0x0220); /* GLB CFG */
+	udelay(500);
+	writel(0x0f, ctl_base + 0x0220); /* GLB CFG */
+	udelay(500);
+
+	return dsi_pll_lock_status(ctl_base);
+}
+
+static void dsi_pll_enable_seq(uint32_t ctl_base)
+{
+	uint32_t counter, status;
+
+	for (counter = 0; counter < 3; counter++) {
+		status = dsi_pll_enable_seq_b(ctl_base);
+		if (status)
+			break;
+		status = dsi_pll_enable_seq_d(ctl_base);
+		if (status)
+			break;
+		status = dsi_pll_enable_seq_d(ctl_base);
+		if(status)
+			break;
+	}
+
+	if (!status)
+		dprintf(CRITICAL, "Pll lock sequence failed\n");
+}
+
+static int msm8974_wled_backlight_ctrl(uint8_t enable)
+{
+	uint32_t platform_id = board_platform_id();
+	uint32_t hardware_id = board_hardware_id();
+	uint8_t slave_id = 1;
+
+	if (enable) {
+		if (platform_id == MSM8974AC)
+			if ((hardware_id == HW_PLATFORM_MTP)
+			    || (hardware_id == HW_PLATFORM_LIQUID))
+				slave_id = 3;
+
+		pm8x41_wled_config_slave_id(slave_id);
+		pm8x41_wled_config(&wled_ctrl);
+		pm8x41_wled_sink_control(enable);
+		pm8x41_wled_iled_sync_control(enable);
+		pm8x41_wled_led_mod_enable(enable);
+	}
+	pm8x41_wled_enable(enable);
+
+	return NO_ERROR;
+}
+
+static int msm8974_pwm_backlight_ctrl(int gpio_num, int lpg_chan, int enable)
+{
+	struct pm8x41_gpio gpio_param = {
+		.direction = PM_GPIO_DIR_OUT,
+		.function = PM_GPIO_FUNC_2,
+		.vin_sel = 2,   /* VIN_2 */
+		.pull = PM_GPIO_PULL_UP_1_5 | PM_GPIO_PULLDOWN_10,
+		.output_buffer = PM_GPIO_OUT_CMOS,
+		.out_strength = PM_GPIO_OUT_DRIVE_HIGH,
+	};
+
+	dprintf(SPEW, "%s: gpio=%d lpg=%d enable=%d\n", __func__,
+				gpio_num, lpg_chan, enable);
+
+	if (enable) {
+		pm8x41_gpio_config(gpio_num, &gpio_param);
+		pm8x41_lpg_write(lpg_chan, 0x41, 0x33); /* LPG_PWM_SIZE_CLK, */
+		pm8x41_lpg_write(lpg_chan, 0x42, 0x01); /* LPG_PWM_FREQ_PREDIV */
+		pm8x41_lpg_write(lpg_chan, 0x43, 0x20); /* LPG_PWM_TYPE_CONFIG */
+		pm8x41_lpg_write(lpg_chan, 0x44, 0xb2); /* LPG_VALUE_LSB */
+		pm8x41_lpg_write(lpg_chan, 0x45, 0x01);  /* LPG_VALUE_MSB */
+		pm8x41_lpg_write(lpg_chan, 0x46, 0xe4); /* LPG_ENABLE_CONTROL */
+	} else {
+		pm8x41_lpg_write(lpg_chan, 0x46, 0x00);
+	}
+
+	return NO_ERROR;
+}
+
+int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
+{
+	uint32_t ret = NO_ERROR;
+
+	if (!bl) {
+		dprintf(CRITICAL, "backlight structure is not available\n");
+		return ERR_INVALID_ARGS;
+	}
+
+	switch (bl->bl_interface_type) {
+		case BL_WLED:
+			ret = msm8974_wled_backlight_ctrl(enable);
+			break;
+		case BL_PWM:
+			ret = msm8974_pwm_backlight_ctrl(pwm_gpio.pin_id,
+							PWM_BL_LPG_CHAN_ID,
+							enable);
+			break;
+		default:
+			dprintf(CRITICAL, "backlight type:%d not supported\n",
+							bl->bl_interface_type);
+			return ERR_NOT_SUPPORTED;
+	}
+
+	return ret;
+}
+
+int target_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
+{
+	struct mdss_dsi_pll_config *pll_data;
+	uint32_t dual_dsi = pinfo->mipi.dual_dsi;
+	dprintf(SPEW, "target_panel_clock\n");
+
+	pll_data = pinfo->mipi.dsi_pll_config;
+	if (enable) {
+		mdp_gdsc_ctrl(enable);
+		mdp_clock_init();
+		mdss_dsi_auto_pll_config(MIPI_DSI0_BASE, pll_data);
+		dsi_pll_enable_seq(MIPI_DSI0_BASE);
+		mmss_clock_auto_pll_init(DSI0_PHY_PLL_OUT, dual_dsi,
+					pll_data->pclk_m,
+					pll_data->pclk_n,
+					pll_data->pclk_d);
+	} else if(!target_cont_splash_screen()) {
+		// * Add here for continuous splash  *
+		mmss_clock_disable(dual_dsi);
+		mdp_clock_disable(dual_dsi);
+	}
+
+	return NO_ERROR;
+}
+
+/* Pull DISP_RST_N high to get panel out of reset */
+int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
+					struct msm_panel_info *pinfo)
+{
+	uint32_t rst_gpio = reset_gpio.pin_id;
+	uint32_t platform_id = board_platform_id();
+	uint32_t hardware_id = board_hardware_id();
+
+	struct pm8x41_gpio resetgpio_param = {
+		.direction = PM_GPIO_DIR_OUT,
+		.output_buffer = PM_GPIO_OUT_CMOS,
+		.out_strength = PM_GPIO_OUT_DRIVE_MED,
+	};
+
+	if (platform_id == MSM8974AC)
+		if ((hardware_id == HW_PLATFORM_MTP)
+		    || (hardware_id == HW_PLATFORM_LIQUID))
+			rst_gpio = 20;
+
+	dprintf(SPEW, "platform_id: %u, rst_gpio: %u\n",
+				platform_id, rst_gpio);
+
+	pm8x41_gpio_config(rst_gpio, &resetgpio_param);
+	if (enable) {
+		gpio_tlmm_config(enable_gpio.pin_id, 0,
+			enable_gpio.pin_direction, enable_gpio.pin_pull,
+			enable_gpio.pin_strength, enable_gpio.pin_state);
+
+		gpio_set(enable_gpio.pin_id, resetseq->pin_direction);
+		pm8x41_gpio_set(rst_gpio, resetseq->pin_state[0]);
+		mdelay(resetseq->sleep[0]);
+		pm8x41_gpio_set(rst_gpio, resetseq->pin_state[1]);
+		mdelay(resetseq->sleep[1]);
+		pm8x41_gpio_set(rst_gpio, resetseq->pin_state[2]);
+		mdelay(resetseq->sleep[2]);
+	} else {
+		resetgpio_param.out_strength = PM_GPIO_OUT_DRIVE_LOW;
+		pm8x41_gpio_config(rst_gpio, &resetgpio_param);
+		pm8x41_gpio_set(rst_gpio, PM_GPIO_FUNC_LOW);
+		gpio_set(enable_gpio.pin_id, resetseq->pin_direction);
+	}
+	return NO_ERROR;
+}
+
+int target_ldo_ctrl(uint8_t enable)
+{
+	uint32_t ldocounter = 0;
+	uint32_t pm8x41_ldo_base = 0x13F00;
+
+	while (ldocounter < TOTAL_LDO_DEFINED) {
+		struct pm8x41_ldo ldo_entry = LDO((pm8x41_ldo_base +
+			0x100 * ldo_entry_array[ldocounter].ldo_id),
+			ldo_entry_array[ldocounter].ldo_type);
+
+		dprintf(SPEW, "Setting %s\n",
+				ldo_entry_array[ldocounter].ldo_id);
+
+		/* Set voltage during power on */
+		if (enable) {
+			pm8x41_ldo_set_voltage(&ldo_entry,
+					ldo_entry_array[ldocounter].ldo_voltage);
+			pm8x41_ldo_control(&ldo_entry, enable);
+		} else if(ldo_entry_array[ldocounter].ldo_id != HFPLL_LDO_ID) {
+			pm8x41_ldo_control(&ldo_entry, enable);
+		}
+		ldocounter++;
+	}
+
+	return NO_ERROR;
+}
+
+static int msm8974_mdss_edp_panel_clock(int enable)
+{
+	if (enable) {
+		mdp_gdsc_ctrl(enable);
+		mdp_clock_init();
+		edp_clk_enable();
+	} else if (!target_cont_splash_screen()) {
+		/* Add here for continuous splash */
+		edp_clk_disable();
+		mdp_clock_disable();
+		mdp_gdsc_ctrl(enable);
+	}
+
+	return 0;
+}
+
+static int msm8974_edp_panel_power(int enable)
+{
+	struct pm8x41_gpio gpio36_param = {
+		.direction = PM_GPIO_DIR_OUT,
+		.function = PM_GPIO_FUNC_2,
+		.vin_sel = 2,	/* VIN_2 */
+		.pull = PM_GPIO_PULL_UP_1_5 | PM_GPIO_PULLDOWN_10,
+		.output_buffer = PM_GPIO_OUT_CMOS,
+		.out_strength = PM_GPIO_OUT_DRIVE_HIGH,
+	};
+
+	struct pm8x41_ldo ldo12 = LDO(PM8x41_LDO12, PLDO_TYPE);
+
+	if (enable) {
+		/* Enable backlight */
+		dprintf(SPEW, "Enable Backlight\n");
+		msm8974_pwm_backlight_ctrl(36, 8, 1);
+		dprintf(SPEW, "Enable Backlight Done\n");
+
+		/* Turn on LDO12 for edp vdda */
+		dprintf(SPEW, "Setting LDO12 n");
+		pm8x41_ldo_set_voltage(&ldo12, 1800000);
+		pm8x41_ldo_control(&ldo12, enable);
+		dprintf(SPEW, "Setting LDO12 Done\n");
+
+		/* Panel Enable */
+		dprintf(SPEW, "Panel Enable\n");
+		gpio_tlmm_config(58, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA,
+				GPIO_DISABLE);
+		gpio_set(58, 2);
+		dprintf(SPEW, "Panel Enable Done\n");
+	} else {
+		/* Keep LDO12 on, otherwise kernel will not boot */
+		gpio_set(58, 0);
+		msm8974_pwm_backlight_ctrl(36, 8, 0);
+	}
+
+	return 0;
+}
+
+void target_display_init(const char *panel_name)
+{
+	uint32_t hw_id = board_hardware_id();
+	uint32_t panel_loop = 0;
+	uint32_t ret = 0;
+	switch (hw_id) {
+	case HW_PLATFORM_LIQUID:
+		edp_panel_init(&(panel.panel_info));
+		panel.clk_func = msm8974_mdss_edp_panel_clock;
+		panel.power_func = msm8974_edp_panel_power;
+		panel.fb.base = (void *)EDP_FB_ADDR;
+		panel.fb.format = FB_FORMAT_RGB888;
+		panel.mdp_rev = MDP_REV_50;
+
+		if (msm_display_init(&panel)) {
+			dprintf(CRITICAL, "edp init failed!\n");
+			return;
+		}
+
+		edp_enable = 1;
+		break;
+	default:
+		do {
+			target_force_cont_splash_disable(false);
+			ret = gcdb_display_init(panel_name, MDP_REV_50,
+				MIPI_FB_ADDR);
+			if (!ret || ret == ERR_NOT_SUPPORTED) {
+				break;
+			} else {
+				target_force_cont_splash_disable(true);
+				msm_display_off();
+			}
+		} while (++panel_loop <= oem_panel_max_auto_detect_panels());
+		break;
+	}
+}
+
+void target_display_shutdown(void)
+{
+	uint32_t hw_id = board_hardware_id();
+	switch (hw_id) {
+	case HW_PLATFORM_LIQUID:
+		if (edp_enable)
+			msm_display_off();
+		break;
+	default:
+		gcdb_display_shutdown();
+		break;
+	}
+}
diff --git a/target/fairphone/tools/makefile b/target/fairphone/tools/makefile
new file mode 100644
index 0000000..2757e07
--- /dev/null
+++ b/target/fairphone/tools/makefile
@@ -0,0 +1,44 @@
+#Makefile to generate appsboot.mbn
+
+ifeq ($(BOOTLOADER_OUT),.)
+APPSBOOTHEADER_DIR  := $(BUILDDIR)
+else
+APPSBOOTHEADER_DIR  := $(BOOTLOADER_OUT)/../..
+endif
+
+SRC_DIR  := target/$(TARGET)/tools
+COMPILER := gcc
+
+ifeq ($(EMMC_BOOT), 1)
+  APPSBOOTHDR_FILES := EMMCBOOT.MBN
+else
+  ifeq ($(BUILD_NANDWRITE), 1)
+    APPSBOOTHDR_FILES :=
+  else
+    APPSBOOTHDR_FILES := appsboot.mbn
+  endif
+endif
+
+APPSBOOTHEADER: $(APPSBOOTHDR_FILES)
+
+
+appsboot.mbn: appsboothd.mbn $(OUTBIN)
+	cp $(OUTBIN) $(APPSBOOTHEADER_DIR)/appsboot.raw
+	cat $(APPSBOOTHEADER_DIR)/appsboothd.mbn $(OUTBIN) > $(APPSBOOTHEADER_DIR)/appsboot.mbn
+	rm -f $(APPSBOOTHEADER_DIR)/appsboothd.mbn
+
+appsboothd.mbn: mkheader $(OUTBIN)
+	$(BUILDDIR)/mkheader $(OUTBIN) $(APPSBOOTHEADER_DIR)/appsboothd.mbn
+
+EMMCBOOT.MBN: emmc_appsboothd.mbn $(OUTBIN)
+	cp $(OUTBIN) $(APPSBOOTHEADER_DIR)/emmc_appsboot.raw
+	cat $(APPSBOOTHEADER_DIR)/emmc_appsboothd.mbn $(OUTBIN) > $(APPSBOOTHEADER_DIR)/EMMCBOOT.MBN
+	cat $(APPSBOOTHEADER_DIR)/emmc_appsboothd.mbn $(OUTBIN) > $(APPSBOOTHEADER_DIR)/emmc_appsboot.mbn
+	rm -f $(APPSBOOTHEADER_DIR)/emmc_appsboothd.mbn
+
+emmc_appsboothd.mbn: mkheader $(OUTBIN)
+	$(BUILDDIR)/mkheader $(OUTBIN) $(APPSBOOTHEADER_DIR)/emmc_appsboothd.mbn
+
+mkheader: $(SRC_DIR)/mkheader.c
+	@mkdir -p $(BUILDDIR)
+	${COMPILER} -DMEMBASE=$(MEMBASE) $(SRC_DIR)/mkheader.c -o $(BUILDDIR)/mkheader
diff --git a/target/fairphone/tools/mkheader.c b/target/fairphone/tools/mkheader.c
new file mode 100644
index 0000000..4a84bd6
--- /dev/null
+++ b/target/fairphone/tools/mkheader.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 2009-2011, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of Google, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/stat.h>
+
+int print_usage()
+{
+	fprintf(stderr, "usage: mkheader <bin> <hdr> <none|unified-boot>\n");
+	fprintf(stderr, "       mkheader <bin> <hdr> <unsecure-boot>"
+		" <outbin>\n");
+	fprintf(stderr, "       mkheader <bin> <hdr> <secure-boot> <outbin>"
+		" <maxsize>\n");
+	fprintf(stderr, "       mkheader <bin> <hdr> <secure-boot> <outbin>"
+		" <maxsize> <certchain> <files...>\n\n");
+	fprintf(stderr, "bin:               Input raw appsbl binary\n");
+	fprintf(stderr,
+		"hdr:               Output of appsbl header location\n");
+	fprintf(stderr,
+		"outbin:            Output of the signed or unsigned"
+		" apps boot location\n");
+	fprintf(stderr,
+		"maxsize:           Maximum size for certificate" " chain\n");
+	fprintf(stderr,
+		"certchain:         Output of the certchain location\n");
+	fprintf(stderr,
+		"files:             Input format <bin signature>"
+		" <certifcate file(s) for certificate chain>...\n");
+	fprintf(stderr,
+		"certificate chain: Files will be concatenated in order"
+		" to create the certificate chain\n\n");
+	return -1;
+}
+
+int cat(FILE * in, FILE * out, unsigned size, unsigned buff_size)
+{
+	unsigned bytes_left = size;
+	char buf[buff_size];
+	int ret = 0;
+
+	while (bytes_left) {
+		fread(buf, sizeof(char), buff_size, in);
+		if (!feof(in)) {
+			bytes_left -= fwrite(buf, sizeof(char), buff_size, out);
+		} else
+			bytes_left = 0;
+	}
+	ret = ferror(in) | ferror(out);
+	if (ret)
+		fprintf(stderr, "ERROR: Occured during file concatenation\n");
+	return ret;
+}
+
+int main(int argc, char *argv[])
+{
+	struct stat s;
+	unsigned size, base;
+	int unified_boot = 0;
+	unsigned unified_boot_magic[20];
+	unsigned non_unified_boot_magic[10];
+	unsigned magic_len = 0;
+	unsigned *magic;
+	unsigned cert_chain_size = 0;
+	unsigned signature_size = 0;
+	int secure_boot = 0;
+	int fd;
+
+	if (argc < 3) {
+		return print_usage();
+	}
+
+	if (argc == 4) {
+		if (!strcmp("unified-boot", argv[3])) {
+			unified_boot = 1;
+		} else if (!strcmp("secure-boot", argv[3])) {
+			fprintf(stderr,
+				"ERROR: Missing arguments: [outbin maxsize] |"
+				" [outbin, maxsize, certchain,"
+				" signature + certifcate(s)]\n");
+			return print_usage();
+		} else if (!strcmp("unsecure-boot", argv[3])) {
+			fprintf(stderr, "ERROR: Missing arguments:"
+				" outbin directory\n");
+			return print_usage();
+		}
+	}
+
+	if (argc > 4) {
+		if (!strcmp("secure-boot", argv[3])) {
+			if (argc < 9 && argc != 6) {
+				fprintf(stderr,
+					"ERROR: Missing argument(s):"
+					" [outbin maxsize] | [outbin, maxsize,"
+					" certchain,"
+					" signature + certifcate(s)]\n");
+				return print_usage();
+			}
+			secure_boot = 1;
+			signature_size = 256;	//Support SHA 256
+			cert_chain_size = atoi(argv[5]);
+		}
+	}
+
+	if (stat(argv[1], &s)) {
+		perror("cannot stat binary");
+		return -1;
+	}
+
+	if (unified_boot) {
+		magic = unified_boot_magic;
+		magic_len = sizeof(unified_boot_magic);
+	} else {
+		magic = non_unified_boot_magic;
+		magic_len = sizeof(non_unified_boot_magic);
+	}
+
+	size = s.st_size;
+#if MEMBASE
+	base = MEMBASE;
+#else
+	base = 0;
+#endif
+
+	printf("Image Destination Pointer: 0x%x\n", base);
+
+	magic[0] = 0x00000005;	/* appsbl */
+	magic[1] = 0x00000003;	//Flash_partition_version /* nand */
+	magic[2] = 0x00000000;	//image source pointer
+	magic[3] = base;	//image destination pointer
+	magic[4] = size + cert_chain_size + signature_size;	//image size
+	magic[5] = size;	//code size
+	magic[6] = base + size;
+	magic[7] = signature_size;
+	magic[8] = size + base + signature_size;
+	magic[9] = cert_chain_size;
+
+	if (unified_boot == 1) {
+		magic[10] = 0x33836685;	/* cookie magic number */
+		magic[11] = 0x00000001;	/* cookie version */
+		magic[12] = 0x00000002;	/* file formats */
+		magic[13] = 0x00000000;
+		magic[14] = 0x00000000;	/* not setting size for boot.img */
+		magic[15] = 0x00000000;
+		magic[16] = 0x00000000;
+		magic[17] = 0x00000000;
+		magic[18] = 0x00000000;
+		magic[19] = 0x00000000;
+	}
+
+	fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
+	if (fd < 0) {
+		perror("cannot open header for writing");
+		return -1;
+	}
+	if (write(fd, magic, magic_len) != magic_len) {
+		perror("cannot write header");
+		close(fd);
+		unlink(argv[2]);
+		return -1;
+	}
+	close(fd);
+
+	if (secure_boot && argc > 6) {
+		FILE *input_file;
+		FILE *output_file;
+		unsigned buff_size = 1;
+		char buf[buff_size];
+		unsigned bytes_left;
+		unsigned current_cert_chain_size = 0;
+		int padding_size = 0;
+		int i;
+
+		if ((output_file = fopen(argv[6], "wb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		printf("Certificate Chain Output File: %s\n", argv[6]);
+
+		for (i = 8; i < argc; i++) {
+			if ((input_file = fopen(argv[i], "rb")) == NULL) {
+				perror("ERROR: Occured during fopen");
+				return -1;
+			}
+			stat(argv[i], &s);
+			bytes_left = s.st_size;
+			current_cert_chain_size += bytes_left;
+			if (cat(input_file, output_file, bytes_left, buff_size))
+				return -1;
+			fclose(input_file);
+		}
+
+		//Pad certifcate chain to the max expected size from input
+		memset(buf, 0xFF, sizeof(buf));
+		padding_size = cert_chain_size - current_cert_chain_size;
+
+		if (padding_size < 0) {
+			fprintf(stderr, "ERROR: Input certificate chain"
+				" (Size=%d) is larger than the maximum"
+				" specified (Size=%d)\n",
+				current_cert_chain_size, cert_chain_size);
+			return -1;
+		}
+
+		bytes_left = (padding_size > 0) ? padding_size : 0;
+		while (bytes_left) {
+			if (!ferror(output_file))
+				bytes_left -= fwrite(buf,
+						     sizeof(buf),
+						     buff_size, output_file);
+			else {
+				fprintf(stderr, "ERROR: Occured during"
+					" certifcate chain padding\n");
+				return -1;
+			}
+		}
+		fclose(output_file);
+
+		/* Concat and combine to signed image.
+		 * Format [HDR][RAW APPSBOOT][PADDED CERT CHAIN]
+		 */
+		if ((output_file = fopen(argv[4], "wb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		printf("Image Output File: %s\n", argv[4]);
+
+		//Header
+		if ((input_file = fopen(argv[2], "rb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		stat(argv[2], &s);
+		if (cat(input_file, output_file, s.st_size, buff_size))
+			return -1;
+		fclose(input_file);
+
+		//Raw Appsbl
+		if ((input_file = fopen(argv[1], "rb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		stat(argv[1], &s);
+		if (cat(input_file, output_file, s.st_size, buff_size))
+			return -1;
+		fclose(input_file);
+
+		//Signature
+		if ((input_file = fopen(argv[7], "rb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		stat(argv[7], &s);
+		if (cat(input_file, output_file, s.st_size, buff_size))
+			return -1;
+		fclose(input_file);
+
+		//Certifcate Chain
+		if ((input_file = fopen(argv[6], "rb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		if (cat(input_file, output_file,
+			(current_cert_chain_size + padding_size), buff_size))
+			return -1;
+		fclose(input_file);
+
+		fclose(output_file);
+
+	} else if (argc == 5 || argc == 6) {
+		FILE *input_file;
+		FILE *output_file;
+		unsigned buff_size = 1;
+		char buf[buff_size];
+
+		/* Concat and combine to unsigned image.
+		 * Format [HDR][RAW APPSBOOT]
+		 */
+		if ((output_file = fopen(argv[4], "wb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		printf("Image Output File: %s\n", argv[4]);
+
+		//Header
+		if ((input_file = fopen(argv[2], "rb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		stat(argv[2], &s);
+		if (cat(input_file, output_file, s.st_size, buff_size))
+			return -1;
+		fclose(input_file);
+
+		//Raw Appsbl
+		if ((input_file = fopen(argv[1], "rb")) == NULL) {
+			perror("ERROR: Occured during fopen");
+			return -1;
+		}
+		stat(argv[1], &s);
+		if (cat(input_file, output_file, s.st_size, buff_size))
+			return -1;
+		fclose(input_file);
+		fclose(output_file);
+	}
+
+	printf("Done execution\n");
+
+	return 0;
+}