blob: cd052f762a2b0387ca13451ba4d3451783c15616 [file] [log] [blame]
/*
* Copyright 2014 Google Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <libpayload.h>
#include <sysinfo.h>
#include <stdio.h>
#include "base/init_funcs.h"
#include "boot/fit.h"
#include "drivers/bus/i2c/ipq806x_gsbi.h"
#include "drivers/bus/i2c/ipq806x.h"
#include "drivers/bus/spi/ipq806x.h"
#include "drivers/bus/usb/usb.h"
#include "drivers/gpio/gpio.h"
#include "drivers/gpio/sysinfo.h"
#include "drivers/tpm/slb9635_i2c.h"
#include "drivers/tpm/tpm.h"
#include "vboot/callbacks/nvstorage_flash.h"
#include "vboot/util/flag.h"
#include "drivers/gpio/ipq806x.h"
#include "drivers/storage/ipq806x_mmc.h"
#include "board.h"
#define GPIO_SDCC_FUNC_VAL 2
#define MSM_SDC1_BASE 0x12400000
/*
* MAC address fixup. There might be more addresses in lib_sysinfo than
* required. Just two need to be set, at the particular paths in the device
* tree listed in the array below.
*/
static int set_mac_addresses(DeviceTree *tree)
{
static const char *mac_addr_paths[][3] = {
{ "soc", "ethernet@37000000", NULL },
{ "soc", "ethernet@37400000", NULL },
};
int i;
DeviceTreeNode *gmac_node;
for (i = 0; i < ARRAY_SIZE(mac_addr_paths); i++) {
if (i >= lib_sysinfo.num_macs)
break;
gmac_node = dt_find_node(tree->root,
mac_addr_paths[i], NULL, NULL, 0);
if (!gmac_node) {
printf("Failed to find %s in the device tree\n",
mac_addr_paths[i][1]);
continue;
}
dt_add_bin_prop(gmac_node, "local-mac-address",
lib_sysinfo.macs[i].mac_addr,
sizeof(lib_sysinfo.macs[i].mac_addr));
}
return 0;
}
static int fix_device_tree(DeviceTreeFixup *fixup, DeviceTree *tree)
{
int rv;
rv = set_mac_addresses(tree);
rv |= set_wifi_calibration(tree);
return rv;
}
static DeviceTreeFixup ipq_enet_fixup = {
.fixup = fix_device_tree
};
/* MMC bus GPIO assignments. */
enum storm_emmc_gpio {
SDC1_DATA7 = 38,
SDC1_DATA6 = 39,
SDC1_DATA3 = 40,
SDC1_DATA2 = 41,
SDC1_CLK = 42,
SDC1_DATA1 = 43,
SDC1_DATA0 = 44,
SDC1_CMD = 45,
SDC1_DATA5 = 46,
SDC1_DATA4 = 47,
};
/* Storm GPIO access wrapper. */
typedef struct
{
GpioOps gpio_ops; /* Depthcharge GPIO API wrapper. */
struct cb_gpio *cbgpio; /* GPIO description. */
} StormGpio;
static int get_gpio(struct GpioOps *me)
{
unsigned value;
StormGpio *gpio = container_of(me, StormGpio, gpio_ops);
value = gpio_get_in_value(gpio->cbgpio->port);
if (gpio->cbgpio->polarity == CB_GPIO_ACTIVE_LOW)
value = !value;
return value;
}
static StormGpio phys_presence_flag = {
.gpio_ops = { .get = get_gpio }
};
static void install_phys_presence_flag(void)
{
phys_presence_flag.cbgpio = sysinfo_lookup_gpio("recovery");
if (!phys_presence_flag.cbgpio) {
printf("%s failed retrieving recovery GPIO\n", __func__);
return;
}
flag_install(FLAG_PHYS_PRESENCE, &phys_presence_flag.gpio_ops);
}
void board_mmc_gpio_config(void)
{
unsigned i;
unsigned char gpio_config_arr[] = {
SDC1_DATA7, SDC1_DATA6, SDC1_DATA3,
SDC1_DATA2, SDC1_DATA1, SDC1_DATA0,
SDC1_CMD, SDC1_DATA5, SDC1_DATA4};
gpio_tlmm_config_set(SDC1_CLK, GPIO_SDCC_FUNC_VAL,
GPIO_PULL_DOWN, GPIO_16MA, 1);
for (i = 0; i < ARRAY_SIZE(gpio_config_arr); i++) {
gpio_tlmm_config_set(gpio_config_arr[i],
GPIO_SDCC_FUNC_VAL, GPIO_PULL_UP, GPIO_10MA, 1);
}
}
static int board_setup(void)
{
sysinfo_install_flags();
fit_set_compat("google,storm-proto0");
install_phys_presence_flag();
SpiController *spi = new_spi(0, 0);
flash_set_ops(&new_spi_flash(&spi->ops, 0x800000)->ops);
UsbHostController *usb_host1 = new_usb_hc(XHCI, 0x11000000);
list_insert_after(&usb_host1->list_node, &usb_host_controllers);
QcomMmcHost *mmc = new_qcom_mmc_host(1, MSM_SDC1_BASE, 8);
if (!mmc)
return -1;
list_insert_after(&mmc->mmc.ctrlr.list_node,
&fixed_block_dev_controllers);
Ipq806xI2c *i2c = new_ipq806x_i2c(GSBI_ID_1);
tpm_set_ops(&new_slb9635_i2c(&i2c->ops, 0x20)->base.ops);
flash_nvram_init();
list_insert_after(&ipq_enet_fixup.list_node, &device_tree_fixups);
return 0;
}
int get_mach_id(void)
{
int i;
struct cb_mainboard *mainboard = lib_sysinfo.mainboard;
const char *part_number = (const char *)mainboard->strings +
mainboard->part_number_idx;
struct PartDescriptor {
const char *part_name;
int mach_id;
} parts[] = {
{"Storm", 4936},
{"AP148", CONFIG_MACHID},
};
for (i = 0; i < ARRAY_SIZE(parts); i++) {
if (!strncmp(parts[i].part_name,
part_number, strlen(parts[i].part_name))) {
return parts[i].mach_id;
}
}
return -1;
}
INIT_FUNC(board_setup);