2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 * Copyright 2014 Google Inc.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but without any warranty; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 #include <libpayload.h>
30 #include "base/init_funcs.h"
32 #include "boot/ramoops.h"
33 #include "drivers/bus/spi/ipq40xx.h"
34 #include "drivers/bus/i2c/ipq40xx.h"
35 #include "drivers/bus/i2c/ipq40xx_blsp.h"
36 #include "drivers/bus/usb/usb.h"
37 #include "drivers/gpio/gpio.h"
38 #include "drivers/gpio/ipq40xx.h"
39 #include "drivers/gpio/sysinfo.h"
40 #include "drivers/power/power.h"
41 #include "drivers/sound/route.h"
42 #include "drivers/storage/ipq40xx_mmc.h"
43 #include "drivers/storage/mtd/mtd.h"
44 #include "drivers/storage/mtd/nand/ipq_nand.h"
45 #include "drivers/storage/mtd/stream.h"
46 #include "drivers/storage/spi_gpt.h"
47 #include "drivers/tpm/slb9635_i2c.h"
48 #include "drivers/tpm/tpm.h"
49 #include "drivers/video/ww_ring.h"
50 #include "vboot/callbacks/nvstorage_flash.h"
51 #include "vboot/stages.h"
52 #include "vboot/util/flag.h"
56 #define MSM_SDC1_BASE 0x7824000
59 /* Structure describing properties of various Storm based boards. */
60 struct board_descriptor {
61 const char *compat_string; // Match the device tree in FIT image.
62 int calibration_needed; // Some boards need to populate WiFi
64 int use_nand; // true if NAND, false if eMMC
67 static struct board_descriptor bdescriptor;
69 static void fill_board_descriptor(void)
71 switch(lib_sysinfo.board_id) {
73 /* FIXME: Add valid board IDs */
74 bdescriptor.compat_string = "google,gale";
75 bdescriptor.calibration_needed = 1;
80 static const DtPathMap mac_maps[] = {
81 { 0, "soc/edma@c080000/gmac0/local-mac-address" },
82 { 0, "soc/edma@c080000/gmac1/local-mac-address" },
83 //{ 1, "chosen/bluetooth/local-mac-address" },
87 static const DtPathMap calibration_maps[] = {
88 {1, "soc/wifi@a000000/qcom,ath10k-pre-calibration-data",
89 "wifi_base64_calibration0"},
90 {1, "soc/wifi@a800000/qcom,ath10k-pre-calibration-data",
91 "wifi_base64_calibration1"},
92 {1, "soc/qcom,pcie@80000/pcie@0/ath10k@0,0/qcom,ath10k-calibration-data",
93 "wifi_base64_calibration2"},
97 static int fix_device_tree(DeviceTreeFixup *fixup, DeviceTree *tree)
101 //rv = dt_set_mac_addresses(tree, mac_maps);
103 //if (bdescriptor.calibration_needed)
104 rv = dt_set_wifi_calibration(tree, calibration_maps);
109 static DeviceTreeFixup ipq_enet_fixup = {
110 .fixup = fix_device_tree
113 gpio_func_data_t mmc_ap_dk04[] = {
117 .pull = GPIO_PULL_UP,
119 .oe = GPIO_OE_DISABLE,
120 .gpio_vm = GPIO_VM_ENABLE,
121 .gpio_od_en = GPIO_OD_DISABLE,
122 .gpio_pu_res = GPIO_PULL_RES2
127 .pull = GPIO_PULL_UP,
129 .oe = GPIO_OE_DISABLE,
130 .gpio_vm = GPIO_VM_ENABLE,
131 .gpio_od_en = GPIO_OD_DISABLE,
132 .gpio_pu_res = GPIO_PULL_RES2
137 .pull = GPIO_PULL_UP,
139 .oe = GPIO_OE_DISABLE,
140 .gpio_vm = GPIO_VM_ENABLE,
141 .gpio_od_en = GPIO_OD_DISABLE,
142 .gpio_pu_res = GPIO_PULL_RES2
147 .pull = GPIO_PULL_UP,
149 .oe = GPIO_OE_DISABLE,
150 .gpio_vm = GPIO_VM_ENABLE,
151 .gpio_od_en = GPIO_OD_DISABLE,
152 .gpio_pu_res = GPIO_PULL_RES2
157 .pull = GPIO_PULL_UP,
159 .oe = GPIO_OE_DISABLE,
160 .gpio_vm = GPIO_VM_ENABLE,
161 .gpio_od_en = GPIO_OD_DISABLE,
162 .gpio_pu_res = GPIO_PULL_RES2
167 .pull = GPIO_PULL_UP,
169 .oe = GPIO_OE_DISABLE,
170 .gpio_vm = GPIO_VM_ENABLE,
171 .gpio_od_en = GPIO_OD_DISABLE,
172 .gpio_pu_res = GPIO_PULL_RES2
177 .pull = GPIO_PULL_UP,
179 .oe = GPIO_OE_DISABLE,
180 .gpio_vm = GPIO_VM_ENABLE,
181 .gpio_od_en = GPIO_OD_DISABLE,
182 .gpio_pu_res = GPIO_PULL_RES2
187 .pull = GPIO_PULL_UP,
189 .oe = GPIO_OE_DISABLE,
190 .gpio_vm = GPIO_VM_ENABLE,
191 .gpio_od_en = GPIO_OD_DISABLE,
192 .gpio_pu_res = GPIO_PULL_RES2
197 .pull = GPIO_PULL_UP,
199 .oe = GPIO_OE_DISABLE,
200 .gpio_vm = GPIO_VM_ENABLE,
201 .gpio_od_en = GPIO_OD_DISABLE,
202 .gpio_pu_res = GPIO_PULL_RES2
207 .pull = GPIO_NO_PULL,
209 .oe = GPIO_OE_DISABLE,
210 .gpio_vm = GPIO_VM_ENABLE,
211 .gpio_od_en = GPIO_OD_DISABLE,
212 .gpio_pu_res = GPIO_PULL_RES2
216 /* Ipq GPIO access wrapper. */
219 GpioOps gpio_ops; /* Depthcharge GPIO API wrapper. */
220 gpio_t desc; /* GPIO description. */
223 static int get_gpio(struct GpioOps *me)
225 IpqGpio *gpio = container_of(me, IpqGpio, gpio_ops);
226 return gpio_get_in_value(gpio->desc);
229 static GpioOps *new_gpio_input_from_coreboot(uint32_t port)
231 IpqGpio *gpio = xzalloc(sizeof(*gpio));
232 gpio->gpio_ops.get = get_gpio;
233 gpio->desc = (gpio_t)port;
234 return &gpio->gpio_ops;
237 static void install_phys_presence_flag(void)
239 GpioOps *phys_presence = sysinfo_lookup_gpio
240 ("developer", 1, new_gpio_input_from_coreboot);
242 if (!phys_presence) {
243 printf("%s failed retrieving phys presence GPIO\n", __func__);
246 flag_install(FLAG_PHYS_PRESENCE, phys_presence);
249 void ipq_configure_gpio(gpio_func_data_t *gpio, uint32_t count)
253 for (i = 0; i < count; i++) {
254 gpio_tlmm_config(gpio->gpio, gpio->func, gpio->out,
255 gpio->pull, gpio->drvstr, gpio->oe,
256 gpio->gpio_vm, gpio->gpio_od_en,
262 void board_mmc_gpio_config(void)
264 ipq_configure_gpio(mmc_ap_dk04, ARRAY_SIZE(mmc_ap_dk04));
268 void board_i2s_gpio_config(void)
271 unsigned char gpio_config_arr[] = {I2S_SYNC, I2S_CLK, I2S_DOUT};
273 for (i = 0; i < ARRAY_SIZE(gpio_config_arr); i++) {
274 gpio_tlmm_config_set(gpio_config_arr[i], GPIO_I2S_FUNC_VAL,
275 GPIO_NO_PULL, GPIO_16MA, 1);
279 void board_dac_gpio_config(void)
281 gpio_tlmm_config_set(DAC_SDMODE, FUNC_SEL_GPIO, GPIO_NO_PULL,
286 static void set_ramoops_buffer(void)
288 uint64_t base, total_size, record_size;
291 * Hardcoded record and total sizes could be defined through Kconfig.
293 * The 'total_size' bytes of memory, aligned at 'record_size' boundary
294 * is found at the top of available memory as defined in the coreboot
295 * table and assigned to the ramoops cache.
297 * This is fairly brittle, as other parts of depthcharge or libpayload
298 * could be using this memory for something. But this is no worse than
299 * hardcoding this area to any particular address.
301 * A proper solution would be to have coreboot assign this memory and
302 * explicitly describe this in the coreboot memory table.
304 record_size = 0x20000;
305 total_size = 0x100000;
308 /* Let's allocate it as high as possible in the available memory */
309 for (int i = 0; i < lib_sysinfo.n_memranges; i++) {
310 uint64_t new_base, size;
311 struct memrange *range = lib_sysinfo.memrange + i;
314 if ((range->type != CB_MEM_RAM) ||
315 (size < (total_size + record_size)))
318 /* Record size aligned area is guaranteed to fit. */
319 new_base = ALIGN_DOWN(range->base + size - total_size,
326 ramoops_buffer(base, total_size, record_size);
329 static uint8_t kb_buffer[4];
330 static int kb_in, kb_out;
332 static int dakota_havekey(void)
335 * We want to react to the button press only, i.e. we need to
336 * catch the "unpressed -> pressed" transition.
338 static uint32_t prev = 1;
339 uint32_t rv = flag_fetch(FLAG_PHYS_PRESENCE);
342 return kb_in != kb_out;
346 return kb_in != kb_out;
348 if (((kb_in + 1) % sizeof(kb_buffer)) == kb_out) {
349 printf("%s: keyboard buffer overflow!\n", __func__);
353 /* Dev switch was pressed, what's the meaning of it? */
354 if (vboot_in_recovery()) {
355 /* This must mean ^D, the user wants to switch to dev mode. */
356 kb_buffer[kb_in++] = 0x4;
357 kb_in %= sizeof(kb_buffer);
359 if (((kb_in + 1) % sizeof(kb_buffer)) != kb_out)
360 kb_buffer[kb_in++] = 0xd;
363 * Should never happen, but worse come to worse the
364 * user will lose the CR and will have to reboot in
365 * recovery mode again to enter dev mode.
367 printf("%s: keyboard buffer overflow!\n", __func__);
369 /* This must mean ^U, the user wants to boot from USB. */
370 kb_buffer[kb_in++] = 0x15;
373 kb_in %= sizeof(kb_buffer);
378 static int dakota_getchar(void)
382 while (!dakota_havekey())
385 storm_char = kb_buffer[kb_out++];
387 kb_out %= sizeof(kb_buffer);
392 static struct console_input_driver dakota_input_driver =
399 static int board_setup(void)
401 sysinfo_install_flags(NULL);
403 fill_board_descriptor();
405 fit_set_compat(bdescriptor.compat_string);
407 install_phys_presence_flag();
409 console_add_input_driver(&dakota_input_driver);
411 power_set_ops(new_ipq40xx_power_ops());
413 SpiController *spi = new_spi(0, 0);
414 flash_set_ops(&new_spi_flash(&spi->ops)->ops);
416 QcomMmcHost *mmc = new_qcom_mmc_host(1, MSM_SDC1_BASE, 8);
421 list_insert_after(&mmc->mmc.ctrlr.list_node,
422 &fixed_block_dev_controllers);
424 UsbHostController *usb_host1 = new_usb_hc(XHCI, 0x8A00000);
426 list_insert_after(&usb_host1->list_node, &usb_host_controllers);
428 #if (!CONFIG_MOCK_TPM)
429 Ipq40xxI2c *i2c = new_ipq40xx_i2c(BLSP_QUP_ID_2);
430 tpm_set_ops(&new_slb9635_i2c(&i2c->ops, 0x20)->base.ops);
433 DisplayOps *ww_ring_ops = new_ww_ring_display
434 (&new_ipq40xx_i2c (BLSP_QUP_ID_3)->ops, 0x32);
436 display_set_ops(ww_ring_ops);
441 Ipq806xSound *sound = new_ipq806x_sound(new_storm_dac_gpio_output(),
443 SoundRoute *sound_route = new_sound_route(&sound->ops);
444 sound_set_ops(&sound_route->ops);
447 write32(ADSS_AUDIO_TXB_CBCR_REG, 0); /* Disable ADSS clock branch */
449 list_insert_after(&ipq_enet_fixup.list_node, &device_tree_fixups);
451 set_ramoops_buffer();
456 int board_wan_port_number(void)
458 if ((lib_sysinfo.board_id == BOARD_ID_PROTO_0) ||
459 (lib_sysinfo.board_id == BOARD_ID_PROTO_0_2))
460 return 4; /* Storm variants */
462 return 1; /* Whirlwind variants, let it be the default. */
465 INIT_FUNC(board_setup);