FP2-15: create Product ID for FP2 project
Change-Id: Ia7290f1516b3397590be838f6311a902fbe323b8
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;
+}