Gale Board: Change Board ID definition.
[depthcharge.git] / src / board / gale / board.c
1 /*
2  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3  * Copyright 2014 Google Inc.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
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.
12  *
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.
17  *
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,
21  * MA 02111-1307 USA
22  */
23
24 #include <config.h>
25 #include <libpayload.h>
26 #include <sysinfo.h>
27 #include <stdio.h>
28 #include <stdint.h>
29
30 #include "base/init_funcs.h"
31 #include "boot/fit.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"
53
54 #include "board.h"
55
56 #define MSM_SDC1_BASE           0x7824000
57
58
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
63                                    // calibration data.
64         int use_nand;              // true if NAND, false if eMMC
65 };
66
67 static struct board_descriptor bdescriptor;
68
69 static void fill_board_descriptor(void)
70 {
71         switch(lib_sysinfo.board_id) {
72         case BOARD_ID_GALE_PROTO:
73         case BOARD_ID_GALE_EVT:
74         case BOARD_ID_GALE_EVT2:
75                 bdescriptor.compat_string = "google,gale";
76                 bdescriptor.calibration_needed = 1;
77                 break;
78         case BOARD_ID_GALE_EVT3:
79         default:
80                 bdescriptor.compat_string = "google,gale-v2";
81                 bdescriptor.calibration_needed = 1;
82                 break;
83         }
84 }
85
86 static const DtPathMap mac_maps[] = {
87         { 0, "soc/edma@c080000/gmac0/local-mac-address" },
88         { 0, "soc/edma@c080000/gmac1/local-mac-address" },
89         //{ 1, "chosen/bluetooth/local-mac-address" },
90         {}
91 };
92
93 static const DtPathMap calibration_maps[] = {
94         {1, "soc/wifi@a000000/qcom,ath10k-pre-calibration-data",
95          "wifi_base64_calibration0"},
96         {1, "soc/wifi@a800000/qcom,ath10k-pre-calibration-data",
97          "wifi_base64_calibration1"},
98         {}
99 };
100
101 static int fix_device_tree(DeviceTreeFixup *fixup, DeviceTree *tree)
102 {
103         int rv;
104
105         //rv = dt_set_mac_addresses(tree, mac_maps);
106
107         //if (bdescriptor.calibration_needed)
108                 rv = dt_set_wifi_calibration(tree, calibration_maps);
109
110         return rv;
111 }
112
113 static DeviceTreeFixup ipq_enet_fixup = {
114         .fixup = fix_device_tree
115 };
116
117 gpio_func_data_t mmc_ap_dk04[] = {
118         {
119                 .gpio = 23,
120                 .func = 1,
121                 .pull = GPIO_PULL_UP,
122                 .drvstr = GPIO_10MA,
123                 .oe = GPIO_OE_DISABLE,
124                 .gpio_vm = GPIO_VM_ENABLE,
125                 .gpio_od_en = GPIO_OD_DISABLE,
126                 .gpio_pu_res = GPIO_PULL_RES2
127         },
128         {
129                 .gpio = 24,
130                 .func = 1,
131                 .pull = GPIO_PULL_UP,
132                 .drvstr = GPIO_10MA,
133                 .oe = GPIO_OE_DISABLE,
134                 .gpio_vm = GPIO_VM_ENABLE,
135                 .gpio_od_en = GPIO_OD_DISABLE,
136                 .gpio_pu_res = GPIO_PULL_RES2
137         },
138         {
139                 .gpio = 25,
140                 .func = 1,
141                 .pull = GPIO_PULL_UP,
142                 .drvstr = GPIO_10MA,
143                 .oe = GPIO_OE_DISABLE,
144                 .gpio_vm = GPIO_VM_ENABLE,
145                 .gpio_od_en = GPIO_OD_DISABLE,
146                 .gpio_pu_res = GPIO_PULL_RES2
147         },
148         {
149                 .gpio = 26,
150                 .func = 1,
151                 .pull = GPIO_PULL_UP,
152                 .drvstr = GPIO_10MA,
153                 .oe = GPIO_OE_DISABLE,
154                 .gpio_vm = GPIO_VM_ENABLE,
155                 .gpio_od_en = GPIO_OD_DISABLE,
156                 .gpio_pu_res = GPIO_PULL_RES2
157         },
158         {
159                 .gpio = 27,
160                 .func = 1,
161                 .pull = GPIO_PULL_UP,
162                 .drvstr = GPIO_16MA,
163                 .oe = GPIO_OE_DISABLE,
164                 .gpio_vm = GPIO_VM_ENABLE,
165                 .gpio_od_en = GPIO_OD_DISABLE,
166                 .gpio_pu_res = GPIO_PULL_RES2
167         },
168         {
169                 .gpio = 28,
170                 .func = 1,
171                 .pull = GPIO_PULL_UP,
172                 .drvstr = GPIO_10MA,
173                 .oe = GPIO_OE_DISABLE,
174                 .gpio_vm = GPIO_VM_ENABLE,
175                 .gpio_od_en = GPIO_OD_DISABLE,
176                 .gpio_pu_res = GPIO_PULL_RES2
177         },
178         {
179                 .gpio = 29,
180                 .func = 1,
181                 .pull = GPIO_PULL_UP,
182                 .drvstr = GPIO_10MA,
183                 .oe = GPIO_OE_DISABLE,
184                 .gpio_vm = GPIO_VM_ENABLE,
185                 .gpio_od_en = GPIO_OD_DISABLE,
186                 .gpio_pu_res = GPIO_PULL_RES2
187         },
188         {
189                 .gpio = 30,
190                 .func = 1,
191                 .pull = GPIO_PULL_UP,
192                 .drvstr = GPIO_10MA,
193                 .oe = GPIO_OE_DISABLE,
194                 .gpio_vm = GPIO_VM_ENABLE,
195                 .gpio_od_en = GPIO_OD_DISABLE,
196                 .gpio_pu_res = GPIO_PULL_RES2
197         },
198         {
199                 .gpio = 31,
200                 .func = 1,
201                 .pull = GPIO_PULL_UP,
202                 .drvstr = GPIO_10MA,
203                 .oe = GPIO_OE_DISABLE,
204                 .gpio_vm = GPIO_VM_ENABLE,
205                 .gpio_od_en = GPIO_OD_DISABLE,
206                 .gpio_pu_res = GPIO_PULL_RES2
207         },
208         {
209                 .gpio = 32,
210                 .func = 1,
211                 .pull = GPIO_NO_PULL,
212                 .drvstr = GPIO_10MA,
213                 .oe = GPIO_OE_DISABLE,
214                 .gpio_vm = GPIO_VM_ENABLE,
215                 .gpio_od_en = GPIO_OD_DISABLE,
216                 .gpio_pu_res = GPIO_PULL_RES2
217         },
218 };
219
220 /* Ipq GPIO access wrapper. */
221 typedef struct
222 {
223         GpioOps gpio_ops;       /* Depthcharge GPIO API wrapper. */
224         gpio_t desc;            /* GPIO description. */
225 } IpqGpio;
226
227 static int get_gpio(struct GpioOps *me)
228 {
229         IpqGpio *gpio = container_of(me, IpqGpio, gpio_ops);
230         return gpio_get_in_value(gpio->desc);
231 }
232
233 static GpioOps *new_gpio_input_from_coreboot(uint32_t port)
234 {
235         IpqGpio *gpio = xzalloc(sizeof(*gpio));
236         gpio->gpio_ops.get = get_gpio;
237         gpio->desc = (gpio_t)port;
238         return &gpio->gpio_ops;
239 }
240
241 static void install_phys_presence_flag(void)
242 {
243         GpioOps *phys_presence = sysinfo_lookup_gpio
244                 ("developer", 1, new_gpio_input_from_coreboot);
245
246         if (!phys_presence) {
247                 printf("%s failed retrieving phys presence GPIO\n", __func__);
248                 return;
249         }
250         flag_install(FLAG_PHYS_PRESENCE, phys_presence);
251 }
252
253 void ipq_configure_gpio(gpio_func_data_t *gpio, uint32_t count)
254 {
255         int i;
256
257         for (i = 0; i < count; i++) {
258                 gpio_tlmm_config(gpio->gpio, gpio->func, gpio->out,
259                                 gpio->pull, gpio->drvstr, gpio->oe,
260                                 gpio->gpio_vm, gpio->gpio_od_en,
261                                 gpio->gpio_pu_res);
262                 gpio++;
263         }
264 }
265
266 void board_mmc_gpio_config(void)
267 {
268         ipq_configure_gpio(mmc_ap_dk04, ARRAY_SIZE(mmc_ap_dk04));
269 }
270
271 #if 0
272 void board_i2s_gpio_config(void)
273 {
274         unsigned i;
275         unsigned char gpio_config_arr[] = {I2S_SYNC, I2S_CLK, I2S_DOUT};
276
277         for (i = 0; i < ARRAY_SIZE(gpio_config_arr); i++) {
278                 gpio_tlmm_config_set(gpio_config_arr[i], GPIO_I2S_FUNC_VAL,
279                                 GPIO_NO_PULL, GPIO_16MA, 1);
280         }
281 }
282
283 void board_dac_gpio_config(void)
284 {
285         gpio_tlmm_config_set(DAC_SDMODE, FUNC_SEL_GPIO, GPIO_NO_PULL,
286                         GPIO_16MA, 1);
287 }
288 #endif
289
290 static void set_ramoops_buffer(void)
291 {
292         uint64_t base, total_size, record_size;
293
294         /*
295          * Hardcoded record and total sizes could be defined through Kconfig.
296          *
297          * The 'total_size' bytes of memory, aligned at 'record_size' boundary
298          * is found at the top of available memory as defined in the coreboot
299          * table and assigned to the ramoops cache.
300          *
301          * This is fairly brittle, as other parts of depthcharge or libpayload
302          * could be using this memory for something. But this is no worse than
303          * hardcoding this area to any particular address.
304          *
305          * A proper solution would be to have coreboot assign this memory and
306          * explicitly describe this in the coreboot memory table.
307          */
308         record_size = 0x20000;
309         total_size = 0x100000;
310         base = 0;
311
312         /* Let's allocate it as high as possible in the available memory */
313         for (int i = 0; i < lib_sysinfo.n_memranges; i++) {
314                 uint64_t new_base, size;
315                 struct memrange *range = lib_sysinfo.memrange + i;
316
317                 size = range->size;
318                 if ((range->type != CB_MEM_RAM) ||
319                     (size < (total_size + record_size)))
320                         continue;
321
322                 /* Record size aligned area is guaranteed to fit. */
323                 new_base = ALIGN_DOWN(range->base + size - total_size,
324                                       record_size);
325                 if (new_base > base)
326                         base = new_base;
327
328         }
329         if (base)
330                 ramoops_buffer(base, total_size, record_size);
331 }
332
333 static uint8_t kb_buffer[4];
334 static int kb_in, kb_out;
335
336 static int dakota_havekey(void)
337 {
338         /*
339          * We want to react to the button press only, i.e. we need to
340          * catch the "unpressed -> pressed" transition.
341          */
342         static uint32_t prev = 1;
343         uint32_t rv = flag_fetch(FLAG_PHYS_PRESENCE);
344
345         if (prev == rv)
346                 return kb_in != kb_out;
347
348         prev = rv;
349         if (!rv)
350                 return kb_in != kb_out;
351
352         if (((kb_in + 1) % sizeof(kb_buffer)) == kb_out) {
353                 printf("%s: keyboard buffer overflow!\n", __func__);
354                 return 0;
355         }
356
357         /* Dev switch was pressed, what's the meaning of it? */
358         if (vboot_in_recovery()) {
359                 /* This must mean ^D, the user wants to switch to dev mode. */
360                 kb_buffer[kb_in++] = 0x4;
361                 kb_in %= sizeof(kb_buffer);
362
363                 if (((kb_in + 1) % sizeof(kb_buffer)) != kb_out)
364                         kb_buffer[kb_in++] = 0xd;
365                 else
366                         /*
367                          * Should never happen, but worse come to worse the
368                          * user will lose the CR and will have to reboot in
369                          * recovery mode again to enter dev mode.
370                          */
371                         printf("%s: keyboard buffer overflow!\n", __func__);
372         } else {
373                 /* This must mean ^U, the user wants to boot from USB. */
374                 kb_buffer[kb_in++] = 0x15;
375         }
376
377         kb_in %= sizeof(kb_buffer);
378
379         return 1;
380 }
381
382 static int dakota_getchar(void)
383 {
384         int storm_char;
385
386         while (!dakota_havekey())
387                 ;
388
389         storm_char = kb_buffer[kb_out++];
390
391         kb_out %= sizeof(kb_buffer);
392
393         return storm_char;
394 }
395
396 static struct console_input_driver dakota_input_driver =
397 {
398         NULL,
399         &dakota_havekey,
400         &dakota_getchar
401 };
402
403 static void ipq_snoc_pnoc_init(void)
404 {
405         /*
406          * IPQ40xx WiFi Global Config
407          * Bit 30:AXID_EN
408          * Enable AXI master bus Axid translating to confirm
409          * all txn submitted by order
410          * Bit 24: Use locally generated socslv_wxi_bvalid
411          * 1:  use locally generate socslv_wxi_bvalid for performance.
412          * 0:  use SNOC socslv_wxi_bvalid.      37
413          */
414         write32(TCSR_WIFI0_GLB_CFG, 0x41000000);
415         write32(TCSR_WIFI1_GLB_CFG, 0x41000000);
416
417         /* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */
418         write32(TCSR_PNOC_SNOC_MEMTYPE_M0_M2, 0x02222222);
419 }
420
421 static int board_setup(void)
422 {
423         sysinfo_install_flags(NULL);
424
425         fill_board_descriptor();
426
427         fit_set_compat(bdescriptor.compat_string);
428
429         install_phys_presence_flag();
430
431         console_add_input_driver(&dakota_input_driver);
432
433         power_set_ops(new_ipq40xx_power_ops());
434
435         SpiController *spi = new_spi(0, 0);
436         flash_set_ops(&new_spi_flash(&spi->ops)->ops);
437
438         QcomMmcHost *mmc = new_qcom_mmc_host(1, MSM_SDC1_BASE, 8);
439
440         if (!mmc)
441                 return -1;
442
443         list_insert_after(&mmc->mmc.ctrlr.list_node,
444                                   &fixed_block_dev_controllers);
445
446         UsbHostController *usb_host1 = new_usb_hc(XHCI, 0x8A00000);
447
448         list_insert_after(&usb_host1->list_node, &usb_host_controllers);
449
450 #if (!CONFIG_MOCK_TPM)
451         Ipq40xxI2c *i2c = new_ipq40xx_i2c(BLSP_QUP_ID_2);
452         tpm_set_ops(&new_slb9635_i2c(&i2c->ops, 0x20)->base.ops);
453 #endif
454
455         DisplayOps *ww_ring_ops = new_ww_ring_display
456                 (&new_ipq40xx_i2c (BLSP_QUP_ID_3)->ops, 0x32);
457
458         display_set_ops(ww_ring_ops);
459
460         display_init();
461
462         write32(ADSS_AUDIO_TXB_CBCR_REG, 0); /* Disable ADSS clock branch */
463
464         ipq_snoc_pnoc_init();
465
466         list_insert_after(&ipq_enet_fixup.list_node, &device_tree_fixups);
467
468         set_ramoops_buffer();
469
470         return 0;
471 }
472 INIT_FUNC(board_setup);