static uint32_t dev_tree_compatible(void *dtb) { int root_offset; const void *prop; char model[128]; struct msm_id msm_id; int len; root_offset = fdt_path_offset(dtb, "/"); if (root_offset < 0) return false; prop = fdt_getprop(dtb, root_offset, "model", &len); if (prop && len > 0) { memcpy(model, prop, MIN((int)sizeof(model), len)); model[sizeof(model) - 1] = '\0'; } else { model[0] = '\0'; } prop = fdt_getprop(dtb, root_offset, "qcom,msm-id", &len); if (!prop || len <= 0) { dprintf(INFO, "qcom,msm-id entry not found\n"); return false; } else if (len < (int)sizeof(struct msm_id)) { dprintf(INFO, "qcom,msm-id entry size mismatch (%d != %d)\n", len, sizeof(struct msm_id)); return false; } msm_id.platform_id = fdt32_to_cpu(((const struct msm_id *)prop)->platform_id); msm_id.hardware_id = fdt32_to_cpu(((const struct msm_id *)prop)->hardware_id); msm_id.soc_rev = fdt32_to_cpu(((const struct msm_id *)prop)->soc_rev); dprintf(INFO, "Found an appended flattened device tree (%s - %d %d 0x%x)\n", *model ? model : "unknown", msm_id.platform_id, msm_id.hardware_id, msm_id.soc_rev); if (msm_id.platform_id != board_platform_id() || msm_id.hardware_id != board_hardware_id()) { dprintf(INFO, "Device tree's msm_id doesn't match the board: <%d %d 0x%x> != <%d %d 0x%x>\n", msm_id.platform_id, msm_id.hardware_id, msm_id.soc_rev, board_platform_id(), board_hardware_id(), board_soc_version()); return INVALID_SOC_REV_ID; } dprintf(INFO, "Device tree's msm_id matches the board: <%d %d 0x%x> == <%d %d 0x%x>\n", msm_id.platform_id, msm_id.hardware_id, msm_id.soc_rev, board_platform_id(), board_hardware_id(), board_soc_version()); return msm_id.soc_rev; }
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 (platform_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 (platform_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"); }
/* * 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 (soc_ver >= BOARD_SOC_VERSION2) host->caps.bus_width = MMC_BOOT_BUS_WIDTH_8_BIT; else host->caps.bus_width = MMC_BOOT_BUS_WIDTH_4_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; }
void reboot_device(unsigned reboot_reason) { uint32_t soc_ver = 0; soc_ver = board_soc_version(); /* Write the reboot reason */ if (soc_ver >= BOARD_SOC_VERSION2) writel(reboot_reason, RESTART_REASON_ADDR_V2); else writel(reboot_reason, RESTART_REASON_ADDR); /* Configure PMIC for warm reset */ pm8x41_reset_configure(PON_PSHOLD_WARM_RESET); /* Disable Watchdog Debug. * Required becuase of a H/W bug which causes the system to * reset partially even for non watchdog resets. */ writel(readl(GCC_WDOG_DEBUG) & ~(1 << WDOG_DEBUG_DISABLE_BIT), GCC_WDOG_DEBUG); dsb(); /* Wait until the write takes effect. */ while(readl(GCC_WDOG_DEBUG) & (1 << WDOG_DEBUG_DISABLE_BIT)); /* Drop PS_HOLD for MSM */ writel(0x00, MPM2_MPM_PS_HOLD); mdelay(5000); dprintf(CRITICAL, "Rebooting failed\n"); }
/* workaround_12 as described in HPG */ void dwc_ss_phy_workaround_12(dwc_dev_t *dev) { /* 12. */ if ( platform_is_8974() && (board_soc_version() < BOARD_SOC_VERSION2)) { REG_WRITEI(dev, GUSB3PIPECTL, 0, 0x30C0003); } }
void usb_wrapper_workaround_10(usb_wrapper_dev_t *dev) { /* 10. */ if ( (board_platform_id() == MSM8974) && (board_soc_version() < BOARD_SOC_VERSION2)) { REG_WRITE(dev, GENERAL_CFG, 0x78); } }
uint32_t platform_is_msm8976_v_1_1() { uint32_t soc_ver = board_soc_version(); uint32_t ret = 0; if(soc_ver == MSM8976_SOC_V11) ret = 1; return ret; }
addr_t get_bs_info_addr() { uint32_t soc_ver = board_soc_version(); if (soc_ver < BOARD_SOC_VERSION2) return ((addr_t)BS_INFO_ADDR_V1); else return ((addr_t)BS_INFO_ADDR_V2); }
static int platform_dt_match(struct dt_entry *cur_dt_entry, uint32_t target_variant_id, uint32_t subtype_mask) { /* 1. must match the platform_id, hardware_id, platform_version * 2. soc rev number equal then return 0 * 3. dt soc rev number less than cdt return -1 * 4. otherwise return 1 */ uint32_t cur_dt_target_id ; cur_dt_target_id = cur_dt_entry->variant_id | ((cur_dt_entry->board_hw_subtype & subtype_mask & 0xff) << 24); if((cur_dt_entry->platform_id == board_platform_id()) && (cur_dt_target_id == target_variant_id)) { if(cur_dt_entry->soc_rev == board_soc_version()) { return 0; } else if(cur_dt_entry->soc_rev < board_soc_version()) { return -1; } } return 1; }
/* Function to return the pointer to the start of the correct device tree * based on the platform data. */ struct dt_entry * dev_tree_get_entry_ptr(struct dt_table *table) { uint32_t i; struct dt_entry *dt_entry_ptr; struct dt_entry *latest_dt_entry = NULL; dt_entry_ptr = (struct dt_entry *)((char *)table + DEV_TREE_HEADER_SIZE); for(i = 0; i < table->num_entries; i++) { /* DTBs are stored in the ascending order of soc revision. * For eg: Rev0..Rev1..Rev2 & so on. * we pickup the DTB with highest soc rev number which is less * than or equal to actual hardware */ if((dt_entry_ptr->platform_id == board_platform_id()) && (dt_entry_ptr->variant_id == board_hardware_id()) && (dt_entry_ptr->soc_rev == board_soc_version())) { return dt_entry_ptr; } /* if the exact match not found, return the closest match * assuming it to be the nearest soc version */ if((dt_entry_ptr->platform_id == board_platform_id()) && (dt_entry_ptr->variant_id == board_hardware_id()) && (dt_entry_ptr->soc_rev <= board_soc_version())) { latest_dt_entry = dt_entry_ptr; } dt_entry_ptr++; } if (latest_dt_entry) { dprintf(SPEW, "Loading DTB with SOC version:%x\n", latest_dt_entry->soc_rev); return latest_dt_entry; } return NULL; }
uint32_t platform_boot_config() { uint32_t boot_config; if (platform_is_mdmcalifornium()) boot_config = BOOT_CONFIG_REG_V2; /* Else the platform is 9x45 */ else if (board_soc_version() >= 0x20000) boot_config = BOOT_CONFIG_REG_V2; else boot_config = BOOT_CONFIG_REG_V1; return boot_config; }
/* AXI master config */ void dwc_axi_master_config(dwc_dev_t *dev) { uint32_t reg = 0; /* 17. */ if ( platform_is_8974() && (board_soc_version() < BOARD_SOC_VERSION2)) { reg = (DWC_GSBUSCFG0_INCR4BRSTENA_BMSK | DWC_GSBUSCFG0_INCR8BRSTENA_BMSK | DWC_GSBUSCFG0_INCR16BRSTENA_BMSK); REG_WRITE(dev, GSBUSCFG0, reg); } }
/* configure SS phy as specified in HPG */ void usb_wrapper_ss_phy_configure(usb_wrapper_dev_t *dev) { /* 4.a */ REG_WRITE_FIELD(dev, SS_PHY_CTRL, REF_USE_PAD, 1); /* .b */ REG_WRITE_FIELD(dev, SS_PHY_CTRL, LANE0_PWR_PRESENT, 1); /* .c */ REG_WRITE_FIELD(dev, SS_PHY_CTRL, REF_SS_PHY_EN, 1); /* For Aragorn V1, reset value fix is required.*/ if ( (board_platform_id() == MSM8974) && (board_soc_version() < BOARD_SOC_VERSION2)) { REG_WRITE_FIELD(dev, SS_PHY_CTRL, SSC_REF_CLK_SEL, 0x108); } }
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 (soc_ver >= BOARD_SOC_VERSION2) restart_reason_addr = RESTART_REASON_ADDR_V2; else restart_reason_addr = RESTART_REASON_ADDR; /* Read reboot reason and scrub it */ restart_reason = readl(restart_reason_addr); writel(0x00, restart_reason_addr); return restart_reason; }
static target_mmc_sdhci_init() { struct mmc_config_data config; uint32_t soc_ver = 0; /* Enable sdhci mode */ sdhci_mode_enable(1); 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 (soc_ver >= BOARD_SOC_VERSION2) config.bus_width = DATA_BUS_WIDTH_8BIT; else config.bus_width = DATA_BUS_WIDTH_4BIT; break; default: config.bus_width = DATA_BUS_WIDTH_8BIT; }; config.max_clk_rate = MMC_CLK_200MHZ; /* Trying Slot 1*/ config.slot = 1; config.base = mmc_sdhci_base[config.slot - 1]; if (!(dev = mmc_init(&config))) { /* Trying Slot 2 next */ config.slot = 2; config.base = mmc_sdhci_base[config.slot - 1]; if (!(dev = mmc_init(&config))) { dprintf(CRITICAL, "mmc init failed!"); ASSERT(0); } } }
/* * Will relocate the DTB to the tags addr if the device tree is found and return * its address * * Arguments: kernel - Start address of the kernel loaded in RAM * tags - Start address of the tags loaded in RAM * kernel_size - Size of the kernel in bytes * * Return Value: DTB address : If appended device tree is found * 'NULL' : Otherwise */ void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags) { void *kernel_end = kernel + kernel_size; uint32_t app_dtb_offset = 0; void *dtb; void *bestmatch_tag = NULL; uint32_t bestmatch_tag_size; uint32_t bestmatch_soc_rev_id = INVALID_SOC_REV_ID; memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t)); dtb = kernel + app_dtb_offset; while (dtb + sizeof(struct fdt_header) < kernel_end) { uint32_t dtb_soc_rev_id; struct fdt_header dtb_hdr; uint32_t dtb_size; /* the DTB could be unaligned, so extract the header, * and operate on it separately */ memcpy(&dtb_hdr, dtb, sizeof(struct fdt_header)); if (fdt_check_header((const void *)&dtb_hdr) != 0 || (dtb + fdt_totalsize((const void *)&dtb_hdr) > kernel_end)) break; dtb_size = fdt_totalsize(&dtb_hdr); if (check_aboot_addr_range_overlap(tags, dtb_size)) { dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n"); return NULL; } /* now that we know we have a valid DTB, we need to copy * it somewhere aligned, like tags */ memcpy(tags, dtb, dtb_size); dtb_soc_rev_id = dev_tree_compatible(tags); if (dtb_soc_rev_id == board_soc_version()) { /* clear out the old DTB magic so kernel doesn't find it */ *((uint32_t *)(kernel + app_dtb_offset)) = 0; return tags; } else if ((dtb_soc_rev_id != INVALID_SOC_REV_ID) && (dtb_soc_rev_id < board_soc_version())) { /* if current bestmatch is less than new dtb_soc_rev_id then update bestmatch_tag */ if((bestmatch_soc_rev_id == INVALID_SOC_REV_ID) || (bestmatch_soc_rev_id < dtb_soc_rev_id)) { bestmatch_tag = dtb; bestmatch_tag_size = dtb_size; bestmatch_soc_rev_id = dtb_soc_rev_id; } } /* goto the next device tree if any */ dtb += dtb_size; } if(bestmatch_tag) { dprintf(INFO,"DTB found with bestmatch soc rev id 0x%x.Board soc rev id 0x%x\n", bestmatch_soc_rev_id, board_soc_version()); memcpy(tags, bestmatch_tag, bestmatch_tag_size); /* clear out the old DTB magic so kernel doesn't find it */ *((uint32_t *)(kernel + app_dtb_offset)) = 0; return tags; } dprintf(CRITICAL, "DTB offset is incorrect, kernel image does not have appended DTB\n"); return NULL; }
static int __dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info, uint32_t target_variant_id, uint32_t subtype_mask) { uint32_t i; unsigned char *table_ptr; struct dt_entry dt_entry_buf_1; struct dt_entry dt_entry_buf_2; struct dt_entry *cur_dt_entry; struct dt_entry *best_match_dt_entry; struct dt_entry_v1 *dt_entry_v1; uint32_t found = 0; if (!dt_entry_info) { dprintf(CRITICAL, "ERROR: Bad parameter passed to %s \n", __func__); return -1; } table_ptr = (unsigned char *)table + DEV_TREE_HEADER_SIZE; cur_dt_entry = &dt_entry_buf_1; best_match_dt_entry = NULL; for(i = 0; found == 0 && i < table->num_entries; i++) { memset(cur_dt_entry, 0, sizeof(struct dt_entry)); switch(table->version) { case DEV_TREE_VERSION_V1: dt_entry_v1 = (struct dt_entry_v1 *)table_ptr; cur_dt_entry->platform_id = dt_entry_v1->platform_id; cur_dt_entry->variant_id = dt_entry_v1->variant_id; cur_dt_entry->soc_rev = dt_entry_v1->soc_rev; cur_dt_entry->board_hw_subtype = board_hardware_subtype(); cur_dt_entry->offset = dt_entry_v1->offset; cur_dt_entry->size = dt_entry_v1->size; table_ptr += sizeof(struct dt_entry_v1); break; case DEV_TREE_VERSION_V2: memcpy(cur_dt_entry, (struct dt_entry *)table_ptr, sizeof(struct dt_entry)); table_ptr += sizeof(struct dt_entry); break; default: dprintf(CRITICAL, "ERROR: Unsupported version (%d) in DT table \n", table->version); return -1; } /* DTBs are stored in the ascending order of soc revision. * For eg: Rev0..Rev1..Rev2 & so on. * we pickup the DTB with highest soc rev number which is less * than or equal to actual hardware */ switch(platform_dt_match(cur_dt_entry, target_variant_id, subtype_mask)) { case 0: best_match_dt_entry = cur_dt_entry; found = 1; break; case -1: if (!best_match_dt_entry) { /* copy structure */ best_match_dt_entry = cur_dt_entry; cur_dt_entry = &dt_entry_buf_2; } else { /* Swap dt_entry buffers */ struct dt_entry *temp = cur_dt_entry; cur_dt_entry = best_match_dt_entry; best_match_dt_entry = temp; } default: break; } } if (best_match_dt_entry) { *dt_entry_info = *best_match_dt_entry; found = 1; } if (found != 0) { dprintf(INFO, "Using DTB entry %u/%08x/%u/%u for device %u/%08x/%u/%u\n", dt_entry_info->platform_id, dt_entry_info->soc_rev, dt_entry_info->variant_id, dt_entry_info->board_hw_subtype, board_platform_id(), board_soc_version(), board_hardware_id(), board_hardware_subtype()); return 0; } dprintf(CRITICAL, "ERROR: Unable to find suitable device tree for device (%u/0x%08x/%u/%u)\n", board_platform_id(), board_soc_version(), board_hardware_id(), board_hardware_subtype()); return -1; }
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 (platform_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]; config.hs400_support = 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); } }
static int dev_tree_compatible(void *dtb, uint32_t dtb_size, struct dt_entry_node *dtb_list) { int root_offset; const void *prop = NULL; const char *plat_prop = NULL; const char *board_prop = NULL; const char *pmic_prop = NULL; char *model = NULL; struct dt_entry *cur_dt_entry; struct dt_entry *dt_entry_array = NULL; struct board_id *board_data = NULL; struct plat_id *platform_data = NULL; struct pmic_id *pmic_data = NULL; int len; int len_board_id; int len_plat_id; int min_plat_id_len = 0; int len_pmic_id; uint32_t dtb_ver; uint32_t num_entries = 0; uint32_t i, j, k, n; uint32_t msm_data_count; uint32_t board_data_count; uint32_t pmic_data_count; root_offset = fdt_path_offset(dtb, "/"); if (root_offset < 0) return false; prop = fdt_getprop(dtb, root_offset, "model", &len); if (prop && len > 0) { model = (char *) malloc(sizeof(char) * len); ASSERT(model); strlcpy(model, prop, len); } else { dprintf(INFO, "model does not exist in device tree\n"); } /* Find the pmic-id prop from DTB , if pmic-id is present then * the DTB is version 3, otherwise find the board-id prop from DTB , * if board-id is present then the DTB is version 2 */ pmic_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,pmic-id", &len_pmic_id); board_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,board-id", &len_board_id); if (pmic_prop && (len_pmic_id > 0) && board_prop && (len_board_id > 0)) { if ((len_pmic_id % PMIC_ID_SIZE) || (len_board_id % BOARD_ID_SIZE)) { dprintf(CRITICAL, "qcom,pmic-id(%d) or qcom,board-id(%d) in device tree is not a multiple of (%d %d)\n", len_pmic_id, len_board_id, PMIC_ID_SIZE, BOARD_ID_SIZE); return false; } dtb_ver = DEV_TREE_VERSION_V3; min_plat_id_len = PLAT_ID_SIZE; } else if (board_prop && len_board_id > 0) { if (len_board_id % BOARD_ID_SIZE) { dprintf(CRITICAL, "qcom,board-id in device tree is (%d) not a multiple of (%d)\n", len_board_id, BOARD_ID_SIZE); return false; } dtb_ver = DEV_TREE_VERSION_V2; min_plat_id_len = PLAT_ID_SIZE; } else { dtb_ver = DEV_TREE_VERSION_V1; min_plat_id_len = DT_ENTRY_V1_SIZE; } /* Get the msm-id prop from DTB */ plat_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,msm-id", &len_plat_id); if (!plat_prop || len_plat_id <= 0) { dprintf(INFO, "qcom,msm-id entry not found\n"); return false; } else if (len_plat_id % min_plat_id_len) { dprintf(INFO, "qcom,msm-id in device tree is (%d) not a multiple of (%d)\n", len_plat_id, min_plat_id_len); return false; } /* * If DTB version is '1' look for <x y z> pair in the DTB * x: platform_id * y: variant_id * z: SOC rev */ if (dtb_ver == DEV_TREE_VERSION_V1) { cur_dt_entry = (struct dt_entry *) malloc(sizeof(struct dt_entry)); if (!cur_dt_entry) { dprintf(CRITICAL, "Out of memory\n"); return false; } memset(cur_dt_entry, 0, sizeof(struct dt_entry)); while (len_plat_id) { cur_dt_entry->platform_id = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->platform_id); cur_dt_entry->variant_id = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->variant_id); cur_dt_entry->soc_rev = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->soc_rev); cur_dt_entry->board_hw_subtype = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->variant_id) >> 0x18; cur_dt_entry->pmic_rev[0] = board_pmic_target(0); cur_dt_entry->pmic_rev[1] = board_pmic_target(1); cur_dt_entry->pmic_rev[2] = board_pmic_target(2); cur_dt_entry->pmic_rev[3] = board_pmic_target(3); cur_dt_entry->offset = (uint32_t)dtb; cur_dt_entry->size = dtb_size; dprintf(SPEW, "Found an appended flattened device tree (%s - %u %u 0x%x)\n", *model ? model : "unknown", cur_dt_entry->platform_id, cur_dt_entry->variant_id, cur_dt_entry->soc_rev); if (platform_dt_absolute_match(cur_dt_entry, dtb_list)) { dprintf(SPEW, "Device tree exact match the board: <%u %u 0x%x> != <%u %u 0x%x>\n", cur_dt_entry->platform_id, cur_dt_entry->variant_id, cur_dt_entry->soc_rev, board_platform_id(), board_hardware_id(), board_soc_version()); } else { dprintf(SPEW, "Device tree's msm_id doesn't match the board: <%u %u 0x%x> != <%u %u 0x%x>\n", cur_dt_entry->platform_id, cur_dt_entry->variant_id, cur_dt_entry->soc_rev, board_platform_id(), board_hardware_id(), board_soc_version()); plat_prop += DT_ENTRY_V1_SIZE; len_plat_id -= DT_ENTRY_V1_SIZE; continue; } } free(cur_dt_entry); }
static int msm8974_backlight_on() { static struct pm8x41_wled_data wled_ctrl = { .mod_scheme = 0xC3, .led1_brightness = (0x0F << 8) | 0xEF, .led2_brightness = (0x0F << 8) | 0xEF, .led3_brightness = (0x0F << 8) | 0xEF, .max_duty_cycle = 0x01, }; pm8x41_wled_config(&wled_ctrl); pm8x41_wled_sink_control(1); pm8x41_wled_iled_sync_control(1); pm8x41_wled_enable(1); return 0; } static int msm8974_mdss_dsi_panel_clock(uint8_t enable) { if (enable) { mdp_gdsc_ctrl(enable); mdp_clock_init(); mdss_dsi_uniphy_pll_config(); mmss_clock_init(); } else if(!target_cont_splash_screen()) { // * Add here for continuous splash * mmss_clock_disable(); mdp_clock_disable(); mdp_gdsc_ctrl(enable); } return 0; } /* Pull DISP_RST_N high to get panel out of reset */ static void msm8974_mdss_mipi_panel_reset(uint8_t enable) { struct pm8x41_gpio gpio19_param = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_CMOS, .out_strength = PM_GPIO_OUT_DRIVE_MED, }; pm8x41_gpio_config(19, &gpio19_param); if (enable) { gpio_tlmm_config(58, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE); pm8x41_gpio_set(19, PM_GPIO_FUNC_HIGH); mdelay(2); pm8x41_gpio_set(19, PM_GPIO_FUNC_LOW); mdelay(5); pm8x41_gpio_set(19, PM_GPIO_FUNC_HIGH); mdelay(2); gpio_set(58, 2); } else { gpio19_param.out_strength = PM_GPIO_OUT_DRIVE_LOW; pm8x41_gpio_config(19, &gpio19_param); pm8x41_gpio_set(19, PM_GPIO_FUNC_LOW); gpio_set(58, 2); } } static int msm8974_mipi_panel_power(uint8_t enable) { if (enable) { /* Enable backlight */ msm8974_backlight_on(); /* Turn on LDO8 for lcd1 mipi vdd */ dprintf(SPEW, " Setting LDO22\n"); pm8x41_ldo_set_voltage("LDO22", 3000000); pm8x41_ldo_control("LDO22", enable); dprintf(SPEW, " Setting LDO12\n"); /* Turn on LDO23 for lcd1 mipi vddio */ pm8x41_ldo_set_voltage("LDO12", 1800000); pm8x41_ldo_control("LDO12", enable); dprintf(SPEW, " Setting LDO2\n"); /* Turn on LDO2 for vdda_mipi_dsi */ pm8x41_ldo_set_voltage("LDO2", 1200000); pm8x41_ldo_control("LDO2", enable); dprintf(SPEW, " Panel Reset \n"); /* Panel Reset */ msm8974_mdss_mipi_panel_reset(enable); dprintf(SPEW, " Panel Reset Done\n"); } else { msm8974_mdss_mipi_panel_reset(enable); pm8x41_wled_enable(enable); pm8x41_ldo_control("LDO2", enable); pm8x41_ldo_control("LDO22", enable); } return 0; } void display_init(void) { uint32_t hw_id = board_hardware_id(); uint32_t soc_ver = board_soc_version(); dprintf(INFO, "display_init(),target_id=%d.\n", hw_id); switch (hw_id) { case HW_PLATFORM_MTP: case HW_PLATFORM_FLUID: case HW_PLATFORM_SURF: mipi_toshiba_video_720p_init(&(panel.panel_info)); panel.clk_func = msm8974_mdss_dsi_panel_clock; panel.power_func = msm8974_mipi_panel_power; panel.fb.base = MIPI_FB_ADDR; panel.fb.width = panel.panel_info.xres; panel.fb.height = panel.panel_info.yres; panel.fb.stride = panel.panel_info.xres; panel.fb.bpp = panel.panel_info.bpp; panel.fb.format = FB_FORMAT_RGB888; panel.mdp_rev = MDP_REV_50; break; default: return; }; if (msm_display_init(&panel)) { dprintf(CRITICAL, "Display init failed!\n"); return; } display_enable = 1; }