iBoot/target/e86/init.c

299 lines
7.4 KiB
C

/*
* Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <drivers/power.h>
#if (APPLICATION_IBOOT && PRODUCT_IBOOT)
#include <drivers/displayport/displayport.h>
#include <drivers/displayport.h>
#endif
#include <lib/env.h>
#include <lib/mib.h>
#include <lib/paint.h>
#include <lib/syscfg.h>
#include <platform.h>
#include <platform/gpiodef.h>
#include <platform/soc/chipid.h>
#include <target.h>
#include <platform/soc/hwclocks.h>
#define E86_AP_BOARD_ID (0xE) // AP board ID
#define E86_DEV_BOARD_ID (0xF) // DEV board ID
#define E86_BOARD_REV (0xF) //(0xF)
// Combined Board Id/Board Revision
typedef enum {
BOARD_TYPE_UNKNOWN = 0,
BOARD_TYPE_E86_PROTO1 = 1
} board_type;
static uint32_t gpio_board_rev;
static bool gpio_board_rev_valid;
static uint32_t e86_get_board_rev(void);
static board_type e86_get_board_type(void);
#if WITH_HW_DISPLAY_DISPLAYPORT
static dp_t dp_link_config = {
.mode = 1,
.type = 0,
.min_link_rate = 0xa,
.max_link_rate = 0xa,
.lanes = 4,
.ssc = 0,
.alpm = 0,
.vrr_enable = 0,
.vrr_on = 0,
.fast_link_training = false,
};
#endif
MIB_CONSTANT(kMIBTargetOsPictureScale, kOIDTypeUInt32, 1);
MIB_CONSTANT(kMIBTargetPictureRotate, kOIDTypeInt32, 0);
static uint32_t e86_get_board_rev (void)
{
if (!gpio_board_rev_valid) {
gpio_configure(GPIO_BOARD_REV0, GPIO_CFG_IN);
gpio_configure(GPIO_BOARD_REV1, GPIO_CFG_IN);
gpio_configure(GPIO_BOARD_REV2, GPIO_CFG_IN);
gpio_configure(GPIO_BOARD_REV3, GPIO_CFG_IN);
gpio_configure_pupdn(GPIO_BOARD_REV0, GPIO_PDN);
gpio_configure_pupdn(GPIO_BOARD_REV1, GPIO_PDN);
gpio_configure_pupdn(GPIO_BOARD_REV2, GPIO_PDN);
gpio_configure_pupdn(GPIO_BOARD_REV3, GPIO_PDN);
spin(100); // Wait 100us
gpio_board_rev =
(gpio_read(GPIO_BOARD_REV3) << 3) |
(gpio_read(GPIO_BOARD_REV2) << 2) |
(gpio_read(GPIO_BOARD_REV1) << 1) |
(gpio_read(GPIO_BOARD_REV0) << 0);
gpio_configure(GPIO_BOARD_REV0, GPIO_CFG_DFLT);
gpio_configure(GPIO_BOARD_REV1, GPIO_CFG_DFLT);
gpio_configure(GPIO_BOARD_REV2, GPIO_CFG_DFLT);
gpio_configure(GPIO_BOARD_REV3, GPIO_CFG_DFLT);
gpio_board_rev_valid = true;
}
return gpio_board_rev;
}
static board_type e86_get_board_type (void)
{
static board_type board_type = BOARD_TYPE_UNKNOWN;
if (board_type != BOARD_TYPE_UNKNOWN) {
dprintf(DEBUG_INFO, "%s: board type: %d\n", __func__, board_type);
return board_type;
}
uint32_t board_id = platform_get_board_id();
uint32_t board_rev = e86_get_board_rev();
dprintf(DEBUG_INFO, "%s: board id: %d, rev: %d\n",
__func__, board_id, board_rev);
if (target_config_ap()) {
if (E86_AP_BOARD_ID == board_id) {
if (E86_BOARD_REV == board_rev) {
return (BOARD_TYPE_E86_PROTO1);
}
}
}
panic("Unknown/unsupported board id/rev combination: 0x%x/0x%x",
board_id, board_rev);
return (BOARD_TYPE_UNKNOWN);
}
static void e86_reset_hoover (bool reset)
{
power_set_gpio(POWER_GPIO_HVR_RESET_L, 1, !reset);
}
static void target_fixup_pmu(void)
{
#if WITH_HW_POWER
int pmu_set_data(int dev, uint16_t reg, uint8_t byte, bool do_confirm);
int pmu_get_data(int dev, uint16_t reg, uint8_t *byte);
int rc;
uint8_t val;
bool fix_ana_trim = false;
rc = pmu_get_data(0, 0x1, &val); // read PMU.OTP version
if (rc < 0) {
dprintf(DEBUG_CRITICAL, "PMU: cannot read OTP Version (%d)\n", rc);
} else {
dprintf(DEBUG_INFO, "%s: PMU OTP ver: %x\n", __func__, val);
if (val < 0x0d) {
rc = pmu_get_data(0, 0x01d7, &val); // read kD2186_BUCK6_ANA_TRIM4
if (rc < 0) {
dprintf(DEBUG_INFO, "PMU: cannot read "
"kD2186_BUCK6_ANA_TRIM4 (%d)\n", rc);
} else {
fix_ana_trim = true;
}
}
}
dprintf(DEBUG_INFO, "%s: fix_ana_trim: %d\n", __func__, fix_ana_trim);
rc = pmu_set_data(0, 0x7000, 0x1d, 0); // test mode
if (rc < 0) {
dprintf(DEBUG_INFO, "PMU: cannot enter test mode (%d)\n", rc);
} else {
// <rdar://problem/16775541> Remove N56 EVT iBoot Overwrites for PMU
// to set high gain mode for kD2186_BUCK6_ANA_TRIM4 0x02 has to be
// OR'd in to preserve exiting bits
if (fix_ana_trim) {
// merge in high gain mode
rc = pmu_set_data(0, 0x01d7, ( val | 0x02 ), 1);
if (rc < 0) {
dprintf(DEBUG_INFO, "cannot change "
"kD2186_BUCK6_ANA_TRIM4 (%d)\n", rc);
}
}
// <rdar://problem/16871166> N61/12A265: All wakes appended with
// "button4"
rc = pmu_set_data(0, 0x0443, 0x35, 1);
if (rc < 0) {
dprintf(DEBUG_INFO, "cannot change button4 (%d)\n", rc);
}
rc = pmu_set_data(0, 0x7000, 0x00, 0);
if (rc < 0) {
panic("PMU: cannot exit test mode (%d)", rc);
}
}
#endif
}
void target_early_init (void)
{
#if PRODUCT_LLB || PRODUCT_IBSS
dprintf(DEBUG_INFO, "%s: chip rev: %d, fuse: %d\n", __func__,
chipid_get_chip_revision(), chipid_get_fuse_revision());
target_fixup_pmu();
#endif
}
void target_late_init (void)
{
clock_gate(CLK_UART7, 0);
#if WITH_HW_DISPLAY_DISPLAYPORT
displayport_init(&dp_link_config);
e86_reset_hoover(false);
#endif
}
void target_init (void)
{
#if WITH_HW_FLASH_NOR
flash_nor_init(SPI_NOR0);
#endif
}
void target_quiesce_hardware (void)
{
dprintf(DEBUG_INFO, "%s ...\n", __func__);
}
void target_poweroff (void)
{
dprintf(DEBUG_INFO, "%s ...\n", __func__);
}
int target_bootprep (enum boot_target target)
{
dprintf(DEBUG_INFO, "%s ...\n", __func__);
return 0;
}
bool target_should_recover (void)
{
return platform_get_request_dfu2() && power_has_usb();
}
bool target_should_poweron (bool *cold_button_boot)
{
#if WITH_HW_POWER
if (power_get_boot_flag() == kPowerBootFlagColdButton) {
*cold_button_boot = true;
}
#else
*cold_button_boot = false;
#endif // WITH_HW_POWER
return (!*cold_button_boot || platform_get_request_dfu1());
}
bool target_should_poweroff (bool at_boot)
{
return (platform_get_request_dfu1() && (!at_boot || !power_has_usb()));
}
#if APPLICATION_IBOOT
void target_watchdog_tickle (void)
{
uint32_t value = gpio_read(GPIO_WDOG_TICKLE);
gpio_write(GPIO_WDOG_TICKLE, value ^ 1);
dprintf(DEBUG_INFO, "%s ...\n", __func__);
}
#endif // APPLICATION_IBOOT
void * target_get_display_configuration(void)
{
#if WITH_HW_DISPLAY_DISPLAYPORT
return ((void *)(&dp_link_config));
#else
return (NULL);
#endif
}
#if WITH_ENV
void target_setup_default_environment (void)
{
dprintf(DEBUG_INFO, "%s ...\n", __func__);
// boot-device is set in platform's init.c
env_set("wifiaddr", "7E:77:77:77:77:77", 0);
env_set("display-timing", "720p-e86", 0);
env_set("adbe-tunables", "default", 0);
}
#endif
#if WITH_DEVICETREE
int target_update_device_tree (void)
{
dprintf(DEBUG_INFO, "%s ...\n", __func__);
return 0;
}
#endif // WITH_DEVICETREE