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