]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/karo/txsd/txsd.c
arm64: add support for Ka-Ro TXSD-410E
[karo-tx-uboot.git] / board / karo / txsd / txsd.c
1 /*
2  * Board init file for TXSD-410E
3  *
4  * (C) Copyright 2017  Lothar Waßmann <LW@KARO-electronics.de>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <console.h>
11 #include <dm.h>
12 #include <fdt_support.h>
13 #include <lcd.h>
14 #include <led.h>
15 #include <mmc.h>
16 #include <usb.h>
17 #include <usb_ether.h>
18 #include <asm/gpio.h>
19 #ifdef DEBUG
20 #include <asm/armv8/mmu.h>
21 #endif
22 #include <linux/fb.h>
23 #include <spmi/spmi.h>
24 #include <power/pmic.h>
25 #include <power/pmic-qcom-smd-rpm.h>
26
27 #include "../common/karo.h"
28
29 DECLARE_GLOBAL_DATA_PTR;
30
31 #ifdef CONFIG_SHOW_ACTIVITY
32
33 enum {
34         LED_STATE_INIT,
35         LED_STATE_ACTIVE,
36         LED_STATE_DISABLED,
37 };
38
39 static int led_state = LED_STATE_INIT;
40
41 #define FDT_USER_LED_LABEL      "txsd-410e:green:user1"
42
43 void show_activity(int arg)
44 {
45         static struct udevice *led_dev;
46         static ulong last;
47         int ret;
48
49         if (led_state == LED_STATE_ACTIVE) {
50                 static int led_on;
51
52                 if (get_timer(last) > CONFIG_SYS_HZ) {
53                         last = get_timer(0);
54                         led_on = !led_on;
55                         ret = led_set_on(led_dev, led_on);
56                         if (ret != 0)
57                                 goto disable;
58                 }
59         } else if (led_state == LED_STATE_DISABLED) {
60                 return;
61         } else if (led_state == LED_STATE_INIT) {
62                 ret = led_get_by_label(FDT_USER_LED_LABEL, &led_dev);
63                 if (ret) {
64                         printf("No '%s' LED found in DTB\n",
65                                 FDT_USER_LED_LABEL);
66                         goto disable;
67                 }
68                 last = get_timer(0);
69                 led_state = LED_STATE_ACTIVE;
70         } else {
71                 printf("Invalid LED state: %d @ %p\n", led_state, &led_state);
72                 goto disable;
73         }
74         return;
75
76 disable:
77         led_state = LED_STATE_DISABLED;
78 }
79 #endif
80
81 #ifdef CONFIG_LCD
82 vidinfo_t panel_info = {
83         /* set to max. size supported by SoC */
84         .vl_col = 1920,
85         .vl_row = 1080,
86
87         .vl_bpix = LCD_COLOR32,    /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
88 };
89
90 static int lcd_enabled = 1;
91 static int lcd_bl_polarity;
92 static struct gpio_desc lcd_bl_gpio;
93
94 void lcd_enable(void)
95 {
96         if (lcd_bl_gpio.dev) {
97                 dm_gpio_set_dir_flags(&lcd_bl_gpio, GPIOD_IS_OUT |
98                                 (lcd_bl_polarity ? GPIOD_ACTIVE_LOW : 0));
99         }
100 }
101
102 void lcd_ctrl_init(void *lcdbase)
103 {
104         int color_depth = 24;
105         const char *video_mode = karo_get_vmode(getenv("video_mode"));
106         const char *vm;
107         unsigned long val;
108         int refresh = 60;
109         struct fb_videomode *p;
110         struct fb_videomode fb_mode;
111         int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
112
113         if (karo_get_fb_mode(NULL, &p) <= 0)
114                 goto disable;
115
116         if (!lcd_enabled) {
117                 debug("LCD disabled\n");
118                 goto disable;
119         }
120
121         if (had_ctrlc() || video_mode == NULL) {
122                 debug("Disabling LCD\n");
123                 lcd_enabled = 0;
124                 if (had_ctrlc())
125                         setenv("splashimage", NULL);
126                 goto disable;
127         }
128
129         karo_fdt_move_fdt();
130         karo_fdt_get_backlight_gpio(gd->fdt_blob, &lcd_bl_gpio);
131         lcd_bl_polarity = karo_fdt_get_backlight_polarity(gd->fdt_blob);
132
133         vm = video_mode;
134         if (karo_fdt_get_fb_mode(gd->fdt_blob, video_mode, &fb_mode) == 0) {
135                 p = &fb_mode;
136                 debug("Using video mode from FDT\n");
137                 vm += strlen(vm);
138                 if (fb_mode.xres > panel_info.vl_col ||
139                         fb_mode.yres > panel_info.vl_row) {
140                         printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
141                                 fb_mode.xres, fb_mode.yres,
142                                 panel_info.vl_col, panel_info.vl_row);
143                         lcd_enabled = 0;
144                         goto disable;
145                 }
146         }
147         if (p->name != NULL)
148                 debug("Trying compiled-in video modes\n");
149         while (p->name != NULL) {
150                 if (strcmp(p->name, vm) == 0) {
151                         debug("Using video mode: '%s'\n", p->name);
152                         vm += strlen(vm);
153                         break;
154                 }
155                 p++;
156         }
157         if (*vm != '\0')
158                 debug("Trying to decode video_mode: '%s'\n", vm);
159         while (*vm != '\0') {
160                 if (*vm >= '0' && *vm <= '9') {
161                         char *end;
162
163                         val = simple_strtoul(vm, &end, 0);
164                         if (end > vm) {
165                                 if (!xres_set) {
166                                         if (val > panel_info.vl_col)
167                                                 val = panel_info.vl_col;
168                                         p->xres = val;
169                                         panel_info.vl_col = val;
170                                         xres_set = 1;
171                                 } else if (!yres_set) {
172                                         if (val > panel_info.vl_row)
173                                                 val = panel_info.vl_row;
174                                         p->yres = val;
175                                         panel_info.vl_row = val;
176                                         yres_set = 1;
177                                 } else if (!bpp_set) {
178                                         switch (val) {
179                                         case 24:
180                                         case 18:
181                                                 color_depth = val;
182                                                 break;
183
184                                         default:
185                                                 printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
186                                                         (int)(end - vm), vm, color_depth);
187                                         }
188                                         bpp_set = 1;
189                                 } else if (!refresh_set) {
190                                         refresh = val;
191                                         refresh_set = 1;
192                                 }
193                         }
194                         vm = end;
195                 }
196                 switch (*vm) {
197                 case '@':
198                         bpp_set = 1;
199                         /* fallthru */
200                 case '-':
201                         yres_set = 1;
202                         /* fallthru */
203                 case 'x':
204                         xres_set = 1;
205                         /* fallthru */
206                 case 'M':
207                 case 'R':
208                         vm++;
209                         break;
210
211                 default:
212                         if (*vm != '\0')
213                                 vm++;
214                 }
215         }
216         if (p->xres == 0 || p->yres == 0) {
217                 int num_modes = karo_get_fb_mode(NULL, &p);
218                 int i;
219
220                 printf("Invalid video mode: %s\n", getenv("video_mode"));
221                 lcd_enabled = 0;
222                 printf("Supported video modes are:");
223                 for (i = 0; i < num_modes; i++, p++) {
224                         if (p->name)
225                                 printf(" %s", p->name);
226                 }
227                 printf("\n");
228                 goto disable;
229         }
230         if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
231                 printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
232                         p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
233                 lcd_enabled = 0;
234                 goto disable;
235         }
236         panel_info.vl_col = p->xres;
237         panel_info.vl_row = p->yres;
238
239         switch (color_depth) {
240         case 8:
241                 panel_info.vl_bpix = LCD_COLOR8;
242                 break;
243         case 16:
244                 panel_info.vl_bpix = LCD_COLOR16;
245                 break;
246         default:
247                 panel_info.vl_bpix = LCD_COLOR32;
248         }
249
250         p->pixclock = KHZ2PICOS(refresh *
251                 (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
252                 (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) /
253                                 1000);
254         debug("Pixel clock set to %lu.%03lu MHz\n",
255                 PICOS2KHZ(p->pixclock) / 1000, PICOS2KHZ(p->pixclock) % 1000);
256
257         if (p != &fb_mode) {
258                 int ret;
259
260                 debug("Creating new display-timing node from '%s'\n",
261                         video_mode);
262                 ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
263                 if (ret)
264                         printf("Failed to create new display-timing node from '%s': %d\n",
265                                 video_mode, ret);
266         }
267
268 #if 0
269         gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
270         imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads,
271                                         ARRAY_SIZE(stk5_lcd_pads));
272 #endif
273         if (karo_load_splashimage(0) == 0) {
274                 debug("Initializing LCD controller\n");
275         } else {
276                 debug("Skipping initialization of LCD controller\n");
277         }
278         return;
279
280 disable:
281         lcd_enabled = 0;
282         panel_info.vl_col = 0;
283         panel_info.vl_row = 0;
284 }
285 #endif /* CONFIG_LCD */
286
287 void txsd_mmc_preinit(void)
288 {
289         struct udevice *mmcdev;
290
291         for (uclass_first_device(UCLASS_MMC, &mmcdev); mmcdev;
292              uclass_next_device(&mmcdev)) {
293                 struct mmc *m = mmc_get_mmc_dev(mmcdev);
294                 if (m)
295                         mmc_set_preinit(m, 1);
296         }
297 }
298
299 int dram_init(void)
300 {
301 #ifdef DEBUG
302         const struct mm_region *mm = mem_map;
303         int i;
304
305         for (i = 0; mm->size; i++, mm++) {
306                 printf("MMU region[%d]=%08llx..%08llx -> %08llx..%08llx size: %08llx Attrs: %08llx\n",
307                         i, mm->phys, mm->phys + mm->size - 1,
308                         mm->virt, mm->virt + mm->size - 1, mm->size, mm->attrs);
309         }
310 #endif
311 #if CONFIG_NR_DRAM_BANKS == 1
312         gd->ram_size = PHYS_SDRAM_1_SIZE;
313 #else
314         gd->ram_size = PHYS_SDRAM_1_SIZE + PHYS_SDRAM_2_SIZE;
315 #endif
316         return 0;
317 }
318
319 void dram_init_banksize(void)
320 {
321         gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
322         gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
323         printf("RAM bank 0 size set to %lluMiB\n", gd->bd->bi_dram[0].size / SZ_1M);
324 #if CONFIG_NR_DRAM_BANKS > 1
325         gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
326         gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
327         printf("RAM bank 1 size set to %lluMiB\n", gd->bd->bi_dram[1].size / SZ_1M);
328 #endif
329         printf("Total RAM size: %lluMiB\n", gd->ram_size / SZ_1M);
330 }
331
332 /* run with default environment */
333 int board_init(void)
334 {
335         if (ctrlc()) {
336                 printf("<CTRL-C> detected; safeboot enabled\n");
337                 return 0;
338         }
339         txsd_mmc_preinit();
340         return 0;
341 }
342
343 /* run with env from mass storage device */
344 static inline int fdt_err_to_errno(int fdterr)
345 {
346         switch (-fdterr) {
347         case FDT_ERR_NOTFOUND:
348                 return -ENOENT;
349         case FDT_ERR_EXISTS:
350                 return -EEXIST;
351         case FDT_ERR_NOSPACE:
352                 return -ENOMEM;
353         case FDT_ERR_BADOFFSET:
354         case FDT_ERR_BADPATH:
355         case FDT_ERR_BADPHANDLE:
356         case FDT_ERR_BADSTATE:
357                 return -EINVAL;
358         case FDT_ERR_TRUNCATED:
359                 return -EILSEQ;
360         case FDT_ERR_BADMAGIC:
361         case FDT_ERR_BADVERSION:
362         case FDT_ERR_BADSTRUCTURE:
363         case FDT_ERR_BADLAYOUT:
364         case FDT_ERR_INTERNAL:
365         case FDT_ERR_BADNCELLS:
366         case FDT_ERR_TOODEEP:
367                 return -EINVAL;
368         }
369         return -EBADFD;
370 }
371
372 int board_prepare_usb(enum usb_init_type type)
373 {
374         static struct gpio_desc vbusen;
375         static int inited;
376         int ret;
377
378         printf("Setting up USB port as %s\n",
379                 type == USB_INIT_HOST ? "host" :
380                 USB_INIT_DEVICE ? "device" : "invalid");
381         if (type != USB_INIT_HOST && type != USB_INIT_DEVICE)
382                 printf("Invalid USB type: %08x\n", type);
383
384         if (!inited) {
385                 int off = fdt_path_offset(gd->fdt_blob, "usbhost");
386
387                 if (off < 0) {
388                         printf("Could not find 'usbost' node: %s\n",
389                                 fdt_strerror(off));
390                         return -ENODEV;
391                 }
392                 ret = gpio_request_by_name_nodev(gd->fdt_blob, off,
393                                                 "switch-gpio", 0, &vbusen, 0);
394                 if (ret) {
395                         printf("Failed to request VBUSEN GPIO: %d\n", ret);
396                         return ret;
397                 }
398                 inited = 1;
399         }
400
401         ret = dm_gpio_set_value(&vbusen, type == USB_INIT_HOST);
402         if (ret == 0)
403                 ret = dm_gpio_set_dir_flags(&vbusen, GPIOD_IS_OUT);
404         if (ret == 0)
405                 ret = dm_gpio_set_value(&vbusen, type == USB_INIT_HOST);
406
407         return ret;
408 }
409
410 static int karo_spmi_init(void)
411 {
412         int ret;
413         struct udevice *dev;
414
415         ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
416         if (ret)
417                 return ret;
418
419         /* Configure PON_PS_HOLD_RESET_CTL for HARD reset */
420         ret = spmi_reg_write(dev, 0, 8, 0x5a, 7);
421         return ret;
422 }
423
424 /* Check for <CTRL-C> - if pressed - stop autoboot */
425 int misc_init_r(void)
426 {
427         unsigned long fdt_addr __maybe_unused = getenv_ulong("fdtaddr", 16, 0);
428         int ret;
429
430         env_cleanup();
431
432         if (had_ctrlc()) {
433                 setenv_ulong("safeboot", 1);
434                 return 0;
435         }
436                 setenv("safeboot", NULL);
437
438         ret = karo_spmi_init();
439         if (ret)
440                 printf("Failed to initialize SPMI interface: %d\n", ret);
441
442         karo_fdt_move_fdt();
443
444         if (getenv("usbethaddr") && !had_ctrlc()) {
445                 uchar mac_addr[ETH_ALEN];
446
447                 ret = usb_init();
448                 if (ret < 0) {
449                         printf("USB init failed: %d\n", ret);
450                         return 0;
451                 }
452                 if (eth_getenv_enetaddr("usbethaddr", mac_addr))
453                         printf("MAC address: %pM\n", mac_addr);
454
455         } else {
456                 printf("'usbethaddr' not set; skipping USB initialization\n");
457         }
458         return 0;
459 }
460
461 #ifdef CONFIG_QCOM_SMD_RPM
462 #define LDO(n, uV, en)  uint32_t ldo##n[] = {                   \
463                 LDOA_RES_TYPE, n, KEY_SOFTWARE_ENABLE, 4, GENERIC_##en, \
464                 KEY_MICRO_VOLT, 4, uV, }
465
466 static LDO(2, 1200000, ENABLE);         // LPDDR
467 static LDO(3, 1150000, ENABLE);         // VDD_MEM, PLL, USB
468 static LDO(5, 1800000, ENABLE);         // LPDDR I/O
469 static LDO(7, 1800000, ENABLE);         // WLAN OSC, PLL2, VDDA2, USBPHY
470 static LDO(8, 2900000, ENABLE);         // eMMC
471 static LDO(15, 1800000, ENABLE);        // Basisboard VDDIO + L16
472 static LDO(16, 1800000, ENABLE);        // Basisboard VDDIO + L15 (55mA)
473 static LDO(17, 3300000, ENABLE);        // Basisboard VDD33 (450mA)
474
475 static LDO(1, 1225000, DISABLE);        // ext. Conn.
476 static LDO(6, 1800000, DISABLE);        // MIPI + Temp Sens.
477 static LDO(9, 3300000, DISABLE);        // WLAN
478 static LDO(11, 1900000, ENABLE);        // JTAG, ext. Conn. OWIRE
479 static LDO(12, 2900000, ENABLE);        // SD-Card
480 static LDO(13, 3075000, ENABLE);        // USBPHY
481
482 static LDO(4, 1800000, DISABLE);        // NC
483 static LDO(10, 1000000, DISABLE);       // NC
484 static LDO(14, 1000000, DISABLE);       // NC
485 static LDO(18, 1000000, DISABLE);       // NC
486
487 #define _debug(fmt...) do {} while (0)
488
489 static inline void __smd_regulator_control(uint32_t *data, size_t len,
490                                 const char *name)
491 {
492         int ret;
493
494         _debug("%s@%d: %sabling %s: %u.%03uV\n", __func__, __LINE__,
495                 data[4] == GENERIC_ENABLE ? "En" : "Dis", name,
496                 data[7] / 1000000, data[7] / 1000 % 1000);
497         ret = rpm_send_data(data, len, RPM_REQUEST_TYPE);
498         if (ret)
499                 printf("Failed to configure regulator %s\n", name);
500         udelay(10000);
501 }
502
503 #define smd_regulator_control(n)        __smd_regulator_control(n, sizeof(n), #n)
504
505 static void smd_pmic_setup(void)
506 {
507         smd_rpm_init();
508
509         smd_regulator_control(ldo1);
510         smd_regulator_control(ldo2);
511         smd_regulator_control(ldo3);
512         smd_regulator_control(ldo4);
513         smd_regulator_control(ldo5);
514         smd_regulator_control(ldo6);
515         smd_regulator_control(ldo7);
516         smd_regulator_control(ldo8);
517         smd_regulator_control(ldo9);
518         smd_regulator_control(ldo10);
519         smd_regulator_control(ldo11);
520         smd_regulator_control(ldo12);
521         smd_regulator_control(ldo13);
522         smd_regulator_control(ldo14);
523         smd_regulator_control(ldo15);
524         smd_regulator_control(ldo16);
525         smd_regulator_control(ldo17);
526         smd_regulator_control(ldo18);
527
528         /* turn off unused regulators */
529         smd_regulator_control(ldo4);
530         smd_regulator_control(ldo10);
531         smd_regulator_control(ldo14);
532         smd_regulator_control(ldo18);
533
534         /* enable all essential regulators */
535         smd_regulator_control(ldo2);
536         smd_regulator_control(ldo3);
537         smd_regulator_control(ldo5);
538         smd_regulator_control(ldo7);
539         smd_regulator_control(ldo8);
540         smd_regulator_control(ldo15);
541         smd_regulator_control(ldo16);
542         smd_regulator_control(ldo17);
543
544         /* setup optional regulators */
545         smd_regulator_control(ldo1);
546         smd_regulator_control(ldo6);
547         smd_regulator_control(ldo9);
548         smd_regulator_control(ldo11);
549         smd_regulator_control(ldo12);
550         smd_regulator_control(ldo13);
551
552         smd_rpm_uninit();
553 }
554 #else
555 static inline void smd_pmic_setup(void)
556 {
557 }
558 #endif
559
560 int board_late_init(void)
561 {
562         if (!getenv("safeboot") && !ctrlc())
563                 smd_pmic_setup();
564
565         clear_ctrlc();
566         return 0;
567 }
568
569 static const char *txsd_touchpanels[] = {
570         "edt,edt-ft5x06",
571         "eeti,egalax_ts",
572 };
573
574 int ft_board_setup(void *blob, bd_t *bd)
575 {
576         int ret;
577         const char *video_mode = karo_get_vmode(getenv("video_mode"));
578
579         ret = fdt_increase_size(blob, 4096);
580         if (ret) {
581                 printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
582                 return ret;
583         }
584         karo_fdt_fixup_touchpanel(blob, txsd_touchpanels,
585                                 ARRAY_SIZE(txsd_touchpanels));
586         karo_fdt_update_fb_mode(blob, video_mode);
587         smd_rpm_uninit();
588         return 0;
589 }
590
591 static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
592 {
593         int ret;
594         struct udevice *dev;
595
596         ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
597         if (ret) {
598                 printf("Failed to get SPMI bus: %d\n", ret);
599                 return CMD_RET_FAILURE;
600         }
601
602         ret = spmi_reg_write(dev, 0, 8, 0x8f, 8);
603         if (ret)
604                 return CMD_RET_FAILURE;
605
606         do_reset(NULL, 0, 0, NULL);
607         return CMD_RET_FAILURE;
608 }
609
610 U_BOOT_CMD(
611         fastboot, 2, 1, do_fastboot,
612         "reboot into Fastboot protocol\n",
613         "    - run as a fastboot usb device"
614 );