Advertisement
Guest User

Untitled

a guest
Aug 18th, 2020
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 25.99 KB | None | 0 0
  1. typedef __builtin_va_list va_list;
  2. #define va_start(ap, param) __builtin_va_start(ap, param)
  3. #define va_end(ap)          __builtin_va_end(ap)
  4. #define va_arg(ap, type)    __builtin_va_arg(ap, type)
  5.  
  6. #define _U  0x01    /* upper */
  7. #define _L  0x02    /* lower */
  8. #define _D  0x04    /* digit */
  9. #define _C  0x08    /* cntrl */
  10. #define _P  0x10    /* punct */
  11. #define _S  0x20    /* white space (space/lf/tab) */
  12. #define _X  0x40    /* hex digit */
  13. #define _SP 0x80    /* hard space (0x20) */
  14.  
  15. const unsigned char _ctype[] = {
  16. _C,_C,_C,_C,_C,_C,_C,_C,            /* 0-7 */
  17. _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,     /* 8-15 */
  18. _C,_C,_C,_C,_C,_C,_C,_C,            /* 16-23 */
  19. _C,_C,_C,_C,_C,_C,_C,_C,            /* 24-31 */
  20. _S|_SP,_P,_P,_P,_P,_P,_P,_P,            /* 32-39 */
  21. _P,_P,_P,_P,_P,_P,_P,_P,            /* 40-47 */
  22. _D,_D,_D,_D,_D,_D,_D,_D,            /* 48-55 */
  23. _D,_D,_P,_P,_P,_P,_P,_P,            /* 56-63 */
  24. _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,  /* 64-71 */
  25. _U,_U,_U,_U,_U,_U,_U,_U,            /* 72-79 */
  26. _U,_U,_U,_U,_U,_U,_U,_U,            /* 80-87 */
  27. _U,_U,_U,_P,_P,_P,_P,_P,            /* 88-95 */
  28. _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,  /* 96-103 */
  29. _L,_L,_L,_L,_L,_L,_L,_L,            /* 104-111 */
  30. _L,_L,_L,_L,_L,_L,_L,_L,            /* 112-119 */
  31. _L,_L,_L,_P,_P,_P,_P,_C,            /* 120-127 */
  32. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 128-143 */
  33. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 144-159 */
  34. _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
  35. _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
  36. _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
  37. _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
  38. _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
  39. _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
  40.  
  41. #define __ismask(x) (_ctype[(int)(unsigned char)(x)])
  42.  
  43. #define isalnum(c)  ((__ismask(c)&(_U|_L|_D)) != 0)
  44.  
  45.  
  46.  
  47. // from u-boot printf
  48.  
  49.  
  50.  
  51. struct printf_info {
  52.     char *bf;   /* Digit buffer */
  53.     char zs;    /* non-zero if a digit has been written */
  54.     char *outstr;   /* Next output position for sprintf() */
  55.  
  56.     /* Output a character */
  57.     void (*putc)(struct printf_info *info, char ch);
  58. };
  59.  
  60. static void out(struct printf_info *info, char c)
  61. {
  62.     *info->bf++ = c;
  63. }
  64.  
  65. static void out_dgt(struct printf_info *info, char dgt)
  66. {
  67.     out(info, dgt + (dgt < 10 ? '0' : 'a' - 10));
  68.     info->zs = 1;
  69. }
  70.  
  71. static void div_out(struct printf_info *info, unsigned long *num,
  72.             unsigned long div)
  73. {
  74.     unsigned char dgt = 0;
  75.  
  76.     while (*num >= div) {
  77.         *num -= div;
  78.         dgt++;
  79.     }
  80.  
  81.     if (info->zs || dgt > 0)
  82.         out_dgt(info, dgt);
  83. }
  84.  
  85. static void pointer(struct printf_info *info, const char *fmt, void *ptr)
  86. {
  87. #ifdef DEBUG
  88.     unsigned long num = (uintptr_t)ptr;
  89.     unsigned long div;
  90. #endif
  91.  
  92.     switch (*fmt) {
  93. #ifdef DEBUG
  94.     case 'a':
  95.  
  96.         switch (fmt[1]) {
  97.         case 'p':
  98.         default:
  99.             num = *(phys_addr_t *)ptr;
  100.             break;
  101.         }
  102.         break;
  103. #endif
  104. #ifdef CONFIG_SPL_NET_SUPPORT
  105.     case 'm':
  106.         return mac_address_string(info, ptr, false);
  107.     case 'M':
  108.         return mac_address_string(info, ptr, true);
  109.     case 'I':
  110.         if (fmt[1] == '4')
  111.             return ip4_addr_string(info, ptr);
  112. #endif
  113.     default:
  114.         break;
  115.     }
  116. #ifdef DEBUG
  117.     div = 1UL << (sizeof(long) * 8 - 4);
  118.     for (; div; div /= 0x10)
  119.         div_out(info, &num, div);
  120. #endif
  121. }
  122.  
  123. static int _vprintf(struct printf_info *info, const char *fmt, va_list va)
  124. {
  125.     char ch;
  126.     char *p;
  127.     unsigned long num;
  128.     char buf[12];
  129.     unsigned long div;
  130.  
  131.     while ((ch = *(fmt++))) {
  132.         if (ch != '%') {
  133.             info->putc(info, ch);
  134.         } else {
  135.             int lz = 0;
  136.             int width = 0;
  137.             int islong = 0;
  138.  
  139.             ch = *(fmt++);
  140.             if (ch == '-')
  141.                 ch = *(fmt++);
  142.  
  143.             if (ch == '0') {
  144.                 ch = *(fmt++);
  145.                 lz = 1;
  146.             }
  147.  
  148.             if (ch >= '0' && ch <= '9') {
  149.                 width = 0;
  150.                 while (ch >= '0' && ch <= '9') {
  151.                     width = (width * 10) + ch - '0';
  152.                     ch = *fmt++;
  153.                 }
  154.             }
  155.             if (ch == 'l') {
  156.                 ch = *(fmt++);
  157.                 islong = 1;
  158.             }
  159.  
  160.             info->bf = buf;
  161.             p = info->bf;
  162.             info->zs = 0;
  163.  
  164.             switch (ch) {
  165.             case '\0':
  166.                 goto abort;
  167.             case 'u':
  168.             case 'd':
  169.                 div = 1000000000;
  170.                 if (islong) {
  171.                     num = va_arg(va, unsigned long);
  172.                     if (sizeof(long) > 4)
  173.                         div *= div * 10;
  174.                 } else {
  175.                     num = va_arg(va, unsigned int);
  176.                 }
  177.  
  178.                 if (ch == 'd') {
  179.                     if (islong && (long)num < 0) {
  180.                         num = -(long)num;
  181.                         out(info, '-');
  182.                     } else if (!islong && (int)num < 0) {
  183.                         num = -(int)num;
  184.                         out(info, '-');
  185.                     }
  186.                 }
  187.                 if (!num) {
  188.                     out_dgt(info, 0);
  189.                 } else {
  190.                     /* HACK MANUEL!!!!!!!!!!!!!!!!!!!!!!!!!
  191.                     for (; div; div /= 10)
  192.                         div_out(info, &num, div);
  193.                     */
  194.                 }
  195.                 break;
  196.             case 'x':
  197.                 if (islong) {
  198.                     num = va_arg(va, unsigned long);
  199.                     div = 1UL << (sizeof(long) * 8 - 4);
  200.                 } else {
  201.                     num = va_arg(va, unsigned int);
  202.                     div = 0x10000000;
  203.                 }
  204.                 if (!num) {
  205.                     out_dgt(info, 0);
  206.                 } else {
  207.                     for (; div; div /= 0x10)
  208.                         div_out(info, &num, div);
  209.                 }
  210.                 break;
  211.             case 'c':
  212.                 out(info, (char)(va_arg(va, int)));
  213.                 break;
  214.             case 's':
  215.                 p = va_arg(va, char*);
  216.                 break;
  217.             case 'p':
  218.                 pointer(info, fmt, va_arg(va, void *));
  219.                 while (isalnum(fmt[0]))
  220.                     fmt++;
  221.                 break;
  222.             case '%':
  223.                 out(info, '%');
  224.             default:
  225.                 break;
  226.             }
  227.  
  228.             *info->bf = 0;
  229.             info->bf = p;
  230.             while (*info->bf++ && width > 0)
  231.                 width--;
  232.             while (width-- > 0)
  233.                 info->putc(info, lz ? '0' : ' ');
  234.             if (p) {
  235.                 while ((ch = *p++))
  236.                     info->putc(info, ch);
  237.             }
  238.         }
  239.     }
  240.  
  241. abort:
  242.     return 0;
  243. }
  244.  
  245.  
  246. static void putc_normal(struct printf_info *info, char ch)
  247. {
  248.     //putc(ch);
  249.     uart0_putc(ch);
  250. }
  251. int printf(const char *fmt, ...)
  252. {
  253.     struct printf_info info;
  254.  
  255.     va_list va;
  256.     int ret;
  257.  
  258.     info.putc = putc_normal;
  259.     va_start(va, fmt);
  260.     ret = _vprintf(&info, fmt, va);
  261.     va_end(va);
  262.  
  263.     return ret;
  264. }
  265.  
  266.  
  267. /*
  268.  * Copyright (C) 2016  Siarhei Siamashka <siarhei.siamashka@gmail.com>
  269.  *
  270.  * This program is free software: you can redistribute it and/or modify
  271.  * it under the terms of the GNU General Public License as published by
  272.  * the Free Software Foundation, either version 2 of the License, or
  273.  * (at your option) any later version.
  274.  *
  275.  * This program is distributed in the hope that it will be useful,
  276.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  277.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  278.  * GNU General Public License for more details.
  279.  *
  280.  * You should have received a copy of the GNU General Public License
  281.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  282.  */
  283.  
  284. /*
  285.  * Partially based on the uart code from ar100-info
  286.  *
  287.  * (C) Copyright 2013 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
  288.  *
  289.  * This program is free software; you can redistribute it and/or
  290.  * modify it under the terms of the GNU General Public License as
  291.  * published by the Free Software Foundation; either version 2 of
  292.  * the License, or (at your option) any later version.
  293.  *
  294.  * This program is distributed in the hope that it will be useful,
  295.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  296.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  297.  * GNU General Public License for more details.
  298.  *
  299.  * You should have received a copy of the GNU General Public License
  300.  * along with this program; if not, write to the Free Software
  301.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  302.  * MA 02111-1307 USA
  303.  */
  304.  
  305. /*
  306.  * Partially based on the sunxi gpio code from U-Boot
  307.  *
  308.  * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
  309.  *
  310.  * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
  311.  *
  312.  * (C) Copyright 2007-2011
  313.  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  314.  * Tom Cubie <tangliang@allwinnertech.com>
  315.  *
  316.  * SPDX-License-Identifier: GPL-2.0+
  317.  */
  318.  
  319. typedef unsigned int u32;
  320.  
  321. #define set_wbit(addr, v)   (*((volatile unsigned long  *)(addr)) |= (unsigned long)(v))
  322. #define readl(addr)     (*((volatile unsigned long  *)(addr)))
  323. #define writel(v, addr)     (*((volatile unsigned long  *)(addr)) = (unsigned long)(v))
  324.  
  325. #define SUNXI_UART0_BASE    0x01C28000
  326. #define SUNXI_PIO_BASE      0x01C20800
  327. #define AW_CCM_BASE     0x01c20000
  328. #define AW_SRAMCTRL_BASE    0x01c00000
  329.  
  330. #define H6_UART0_BASE       0x05000000
  331. #define H6_PIO_BASE     0x0300B000
  332. #define H6_CCM_BASE     0x03001000
  333. #define H6_SRAMCTRL_BASE    0x03000000
  334.  
  335. /*****************************************************************************
  336.  * GPIO code, borrowed from U-Boot                                           *
  337.  *****************************************************************************/
  338.  
  339. #define SUNXI_GPIO_A    0
  340. #define SUNXI_GPIO_B    1
  341. #define SUNXI_GPIO_C    2
  342. #define SUNXI_GPIO_D    3
  343. #define SUNXI_GPIO_E    4
  344. #define SUNXI_GPIO_F    5
  345. #define SUNXI_GPIO_G    6
  346. #define SUNXI_GPIO_H    7
  347. #define SUNXI_GPIO_I    8
  348.  
  349. struct sunxi_gpio {
  350.     u32 cfg[4];
  351.     u32 dat;
  352.     u32 drv[2];
  353.     u32 pull[2];
  354. };
  355.  
  356. struct sunxi_gpio_reg {
  357.     struct sunxi_gpio gpio_bank[10];
  358. };
  359.  
  360. #define GPIO_BANK(pin)      ((pin) >> 5)
  361. #define GPIO_NUM(pin)       ((pin) & 0x1F)
  362.  
  363. #define GPIO_CFG_INDEX(pin) (((pin) & 0x1F) >> 3)
  364. #define GPIO_CFG_OFFSET(pin)    ((((pin) & 0x1F) & 0x7) << 2)
  365.  
  366. #define GPIO_PULL_INDEX(pin)    (((pin) & 0x1f) >> 4)
  367. #define GPIO_PULL_OFFSET(pin)   ((((pin) & 0x1f) & 0xf) << 1)
  368.  
  369. /* GPIO bank sizes */
  370. #define SUNXI_GPIO_A_NR    (32)
  371. #define SUNXI_GPIO_B_NR    (32)
  372. #define SUNXI_GPIO_C_NR    (32)
  373. #define SUNXI_GPIO_D_NR    (32)
  374. #define SUNXI_GPIO_E_NR    (32)
  375. #define SUNXI_GPIO_F_NR    (32)
  376. #define SUNXI_GPIO_G_NR    (32)
  377. #define SUNXI_GPIO_H_NR    (32)
  378. #define SUNXI_GPIO_I_NR    (32)
  379.  
  380. #define SUNXI_GPIO_NEXT(__gpio) ((__gpio##_START) + (__gpio##_NR) + 0)
  381.  
  382. enum sunxi_gpio_number {
  383.     SUNXI_GPIO_A_START = 0,
  384.     SUNXI_GPIO_B_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_A),
  385.     SUNXI_GPIO_C_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_B),
  386.     SUNXI_GPIO_D_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_C),
  387.     SUNXI_GPIO_E_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_D),
  388.     SUNXI_GPIO_F_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_E),
  389.     SUNXI_GPIO_G_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_F),
  390.     SUNXI_GPIO_H_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_G),
  391.     SUNXI_GPIO_I_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_H),
  392. };
  393.  
  394. /* SUNXI GPIO number definitions */
  395. #define SUNXI_GPA(_nr)          (SUNXI_GPIO_A_START + (_nr))
  396. #define SUNXI_GPB(_nr)          (SUNXI_GPIO_B_START + (_nr))
  397. #define SUNXI_GPC(_nr)          (SUNXI_GPIO_C_START + (_nr))
  398. #define SUNXI_GPD(_nr)          (SUNXI_GPIO_D_START + (_nr))
  399. #define SUNXI_GPE(_nr)          (SUNXI_GPIO_E_START + (_nr))
  400. #define SUNXI_GPF(_nr)          (SUNXI_GPIO_F_START + (_nr))
  401. #define SUNXI_GPG(_nr)          (SUNXI_GPIO_G_START + (_nr))
  402. #define SUNXI_GPH(_nr)          (SUNXI_GPIO_H_START + (_nr))
  403. #define SUNXI_GPI(_nr)          (SUNXI_GPIO_I_START + (_nr))
  404.  
  405. /* GPIO pin function config */
  406. #define SUNXI_GPIO_INPUT        (0)
  407. #define SUNXI_GPIO_OUTPUT       (1)
  408. #define SUN4I_GPB_UART0         (2)
  409. #define SUN5I_GPB_UART0         (2)
  410. #define SUN6I_GPH_UART0         (2)
  411. #define SUN8I_H3_GPA_UART0      (2)
  412. #define SUN8I_V3S_GPB_UART0     (3)
  413. #define SUN50I_H5_GPA_UART0     (2)
  414. #define SUN50I_H6_GPH_UART0 (2)
  415. #define SUN50I_A64_GPB_UART0    (4)
  416. #define SUNXI_GPF_UART0         (4)
  417.  
  418. /* GPIO pin pull-up/down config */
  419. #define SUNXI_GPIO_PULL_DISABLE (0)
  420. #define SUNXI_GPIO_PULL_UP      (1)
  421. #define SUNXI_GPIO_PULL_DOWN    (2)
  422.  
  423. static u32 pio_base;
  424.  
  425. int sunxi_gpio_set_cfgpin(u32 pin, u32 val)
  426. {
  427.     u32 cfg;
  428.     u32 bank = GPIO_BANK(pin);
  429.     u32 index = GPIO_CFG_INDEX(pin);
  430.     u32 offset = GPIO_CFG_OFFSET(pin);
  431.     struct sunxi_gpio *pio =
  432.         &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
  433.     cfg = readl(&pio->cfg[0] + index);
  434.     cfg &= ~(0xf << offset);
  435.     cfg |= val << offset;
  436.     writel(cfg, &pio->cfg[0] + index);
  437.     return 0;
  438. }
  439.  
  440. int sunxi_gpio_set_pull(u32 pin, u32 val)
  441. {
  442.     u32 cfg;
  443.     u32 bank = GPIO_BANK(pin);
  444.     u32 index = GPIO_PULL_INDEX(pin);
  445.     u32 offset = GPIO_PULL_OFFSET(pin);
  446.     struct sunxi_gpio *pio =
  447.         &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
  448.     cfg = readl(&pio->pull[0] + index);
  449.     cfg &= ~(0x3 << offset);
  450.     cfg |= val << offset;
  451.     writel(cfg, &pio->pull[0] + index);
  452.     return 0;
  453. }
  454.  
  455. int sunxi_gpio_output(u32 pin, u32 val)
  456. {
  457.     u32 dat;
  458.     u32 bank = GPIO_BANK(pin);
  459.     u32 num = GPIO_NUM(pin);
  460.     struct sunxi_gpio *pio =
  461.         &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
  462.     dat = readl(&pio->dat);
  463.     if(val)
  464.         dat |= 1 << num;
  465.     else
  466.         dat &= ~(1 << num);
  467.     writel(dat, &pio->dat);
  468.     return 0;
  469. }
  470.  
  471. int sunxi_gpio_input(u32 pin)
  472. {
  473.     u32 dat;
  474.     u32 bank = GPIO_BANK(pin);
  475.     u32 num = GPIO_NUM(pin);
  476.     struct sunxi_gpio *pio =
  477.         &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
  478.     dat = readl(&pio->dat);
  479.     dat >>= num;
  480.     return (dat & 0x1);
  481. }
  482.  
  483. int gpio_direction_input(unsigned gpio)
  484. {
  485.     sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
  486.     return sunxi_gpio_input(gpio);
  487. }
  488.  
  489. int gpio_direction_output(unsigned gpio, int value)
  490. {
  491.     sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
  492.     return sunxi_gpio_output(gpio, value);
  493. }
  494.  
  495. /*****************************************************************************
  496.  * Nearly all the Allwinner SoCs are using the same VER_REG register for     *
  497.  * runtime SoC type identification. For additional details see:              *
  498.  *                                                                           *
  499.  *    https://linux-sunxi.org/SRAM_Controller_Register_Guide                 *
  500.  *                                                                           *
  501.  * Allwinner A80 is an oddball and has a non-standard address of the VER_REG *
  502.  *                                                                           *
  503.  * Allwinner A10s and A13 are using the same SoC type id, but they can be    *
  504.  * differentiated using a certain part of the SID register.                  *
  505.  *                                                                           *
  506.  * Allwinner H6 has its memory map totally reworked, but the SRAM controller *
  507.  * remains similar; the base of it is moved to 0x03000000.                   *
  508.  *****************************************************************************/
  509.  
  510. #define VER_REG         (AW_SRAMCTRL_BASE + 0x24)
  511. #define H6_VER_REG      (H6_SRAMCTRL_BASE + 0x24)
  512. #define SUN4I_SID_BASE    0x01C23800
  513. #define SUN8I_SID_BASE    0x03006000
  514.  
  515. #define SID_PRCTL   0x40    /* SID program/read control register */
  516. #define SID_RDKEY   0x60    /* SID read key value register */
  517.  
  518. #define SID_OP_LOCK 0xAC    /* Efuse operation lock value */
  519. #define SID_READ_START  (1 << 1) /* bit 1 of SID_PRCTL, Software Read Start */
  520.  
  521. u32 sid_read_key(u32 sid_base, u32 offset)
  522. {
  523.     u32 reg_val;
  524.  
  525.     reg_val = (offset & 0x1FF) << 16; /* PG_INDEX value */
  526.     reg_val |= (SID_OP_LOCK << 8) | SID_READ_START; /* request read access */
  527.     writel(reg_val, sid_base + SID_PRCTL);
  528.  
  529.     while (readl(sid_base + SID_PRCTL) & SID_READ_START) ; /* wait while busy */
  530.  
  531.     reg_val = readl(sid_base + SID_RDKEY); /* read SID key value */
  532.     writel(0, sid_base + SID_PRCTL); /* clear SID_PRCTL (removing SID_OP_LOCK) */
  533.  
  534.     return reg_val;
  535. }
  536.  
  537. static u32 soc_id;
  538.  
  539. void soc_detection_init(void)
  540. {
  541.     u32 midr;
  542.     asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (midr));
  543.  
  544.     if (((midr >> 4) & 0xFFF) == 0xC0F) {
  545.         soc_id = 0x1639; /* ARM Cortex-A15, so likely Allwinner A80 */
  546.     } else {
  547.         u32 reg;
  548.  
  549.         /*
  550.          * This register is GICD_IIDR on H6, but unmapped according to
  551.          * other known SoCs' user manuals.
  552.          */
  553.         reg = readl(0x03021008);
  554.  
  555.         if ((reg & 0xfff) == 0x43b) /* Found GICv2 here, so it's a H6 */
  556.             reg = H6_VER_REG;
  557.         else
  558.             reg = VER_REG;
  559.  
  560.         set_wbit(reg, 1 << 15);
  561.         soc_id = readl(reg) >> 16;
  562.     }
  563. }
  564.  
  565. /* Most SoCs can reliably be distinguished by simply checking their ID value */
  566.  
  567. #define soc_is_a10()    (soc_id == 0x1623)
  568. #define soc_is_a20()    (soc_id == 0x1651)
  569. #define soc_is_a31()    (soc_id == 0x1633)
  570. #define soc_is_a80()    (soc_id == 0x1639)
  571. #define soc_is_a64()    (soc_id == 0x1689)
  572. #define soc_is_h5() (soc_id == 0x1718)
  573. #define soc_is_h6() (soc_id == 0x1728)
  574. #define soc_is_r40()    (soc_id == 0x1701)
  575. #define soc_is_v3s()    (soc_id == 0x1681)
  576.  
  577. /* A10s and A13 share the same ID, so we need a little more effort on those */
  578.  
  579. int soc_is_a10s(void)
  580. {
  581.     return soc_id == 0x1625 &&
  582.            (readl(SUN4I_SID_BASE + 8) & 0xf000) == 0x7000;
  583. }
  584.  
  585. int soc_is_a13(void)
  586. {
  587.     return soc_id == 0x1625 &&
  588.            (readl(SUN4I_SID_BASE + 8) & 0xf000) != 0x7000;
  589. }
  590.  
  591. /* H2+ and H3 share the same ID, we can differentiate them by SID_RKEY0 */
  592.  
  593. int soc_is_h2_plus(void)
  594. {
  595.     if (soc_id != 0x1680) return 0;
  596.  
  597.     u32 sid0 = sid_read_key(SUN8I_SID_BASE, 0);
  598.     return (sid0 & 0xff) == 0x42 || (sid0 & 0xff) == 0x83;
  599. }
  600.  
  601. int soc_is_h3(void)
  602. {
  603.     if (soc_id != 0x1680) return 0;
  604.  
  605.     u32 sid0 = sid_read_key(SUN8I_SID_BASE, 0);
  606.     /*
  607.      * Note: according to Allwinner sources, H3 is expected
  608.      * to show up as 0x00, 0x81 or ("H3D") 0x58 here.
  609.      */
  610.     return (sid0 & 0xff) != 0x42 && (sid0 & 0xff) != 0x83;
  611. }
  612.  
  613. /*****************************************************************************
  614.  * UART is mostly the same on A10/A13/A20/A31/H3/A64, except that newer SoCs *
  615.  * have changed the APB numbering scheme (A10/A13/A20 used to have APB0 and  *
  616.  * APB1 names, but newer SoCs just have renamed them into APB1 and APB2).    *
  617.  * The constants below are using the new APB numbering convention.           *
  618.  * Also the newer SoCs have introduced the APB2_RESET register, but writing  *
  619.  * to it effectively goes nowhere on older SoCs and is harmless.             *
  620.  *****************************************************************************/
  621.  
  622. #define CONFIG_CONS_INDEX   1
  623. #define APB2_CFG        (AW_CCM_BASE + 0x058)
  624. #define APB2_GATE       (AW_CCM_BASE + 0x06C)
  625. #define APB2_RESET      (AW_CCM_BASE + 0x2D8)
  626. #define APB2_GATE_UART_SHIFT    (16)
  627. #define APB2_RESET_UART_SHIFT   (16)
  628.  
  629. #define H6_UART_GATE_RESET  (H6_CCM_BASE + 0x90C)
  630. #define H6_UART_GATE_SHIFT  (0)
  631. #define H6_UART_RESET_SHIFT (16)
  632.  
  633. void clock_init_uart_legacy(void)
  634. {
  635.     /* Open the clock gate for UART0 */
  636.     set_wbit(APB2_GATE, 1 << (APB2_GATE_UART_SHIFT + CONFIG_CONS_INDEX - 1));
  637.     /* Deassert UART0 reset (only needed on A31/A64/H3) */
  638.     set_wbit(APB2_RESET, 1 << (APB2_RESET_UART_SHIFT + CONFIG_CONS_INDEX - 1));
  639. }
  640.  
  641. void clock_init_uart_h6(void)
  642. {
  643.     /* Open the clock gate for UART0 */
  644.     set_wbit(H6_UART_GATE_RESET, 1 << (H6_UART_GATE_SHIFT + CONFIG_CONS_INDEX - 1));
  645.     /* Deassert UART0 reset */
  646.     set_wbit(H6_UART_GATE_RESET, 1 << (H6_UART_RESET_SHIFT + CONFIG_CONS_INDEX - 1));
  647. }
  648.  
  649. void clock_init_uart(void)
  650. {
  651.     if (soc_is_h6())
  652.         clock_init_uart_h6();
  653.     else
  654.         clock_init_uart_legacy();
  655. }
  656.  
  657. /*****************************************************************************
  658.  * UART0 pins muxing is different for different SoC variants.                *
  659.  * Allwinner A13 is a bit special, because there are no dedicated UART0 pins *
  660.  * and they are shared with MMC0.                                            *
  661.  *****************************************************************************/
  662.  
  663. void gpio_init(void)
  664. {
  665.     if (soc_is_a10() || soc_is_a20() || soc_is_r40()) {
  666.         sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB_UART0);
  667.         sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB_UART0);
  668.         sunxi_gpio_set_pull(SUNXI_GPB(23), SUNXI_GPIO_PULL_UP);
  669.     } else if (soc_is_a10s()) {
  670.         sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN5I_GPB_UART0);
  671.         sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN5I_GPB_UART0);
  672.         sunxi_gpio_set_pull(SUNXI_GPB(20), SUNXI_GPIO_PULL_UP);
  673.     } else if (soc_is_a13()) {
  674.         /* Disable PB19/PB20 as UART0 to avoid conflict */
  675.         gpio_direction_input(SUNXI_GPB(19));
  676.         gpio_direction_input(SUNXI_GPB(20));
  677.         /* Use SD breakout board to access UART0 on MMC0 pins */
  678.         sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUNXI_GPF_UART0);
  679.         sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUNXI_GPF_UART0);
  680.         sunxi_gpio_set_pull(SUNXI_GPF(4), SUNXI_GPIO_PULL_UP);
  681.     } else if (soc_is_a31()) {
  682.         sunxi_gpio_set_cfgpin(SUNXI_GPH(20), SUN6I_GPH_UART0);
  683.         sunxi_gpio_set_cfgpin(SUNXI_GPH(21), SUN6I_GPH_UART0);
  684.         sunxi_gpio_set_pull(SUNXI_GPH(21), SUNXI_GPIO_PULL_UP);
  685.     } else if (soc_is_a64()) {
  686.         sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN50I_A64_GPB_UART0);
  687.         sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN50I_A64_GPB_UART0);
  688.         sunxi_gpio_set_pull(SUNXI_GPB(9), SUNXI_GPIO_PULL_UP);
  689.     } else if (soc_is_h3() || soc_is_h2_plus()) {
  690.         sunxi_gpio_set_cfgpin(SUNXI_GPA(4), SUN8I_H3_GPA_UART0);
  691.         sunxi_gpio_set_cfgpin(SUNXI_GPA(5), SUN8I_H3_GPA_UART0);
  692.         sunxi_gpio_set_pull(SUNXI_GPA(5), SUNXI_GPIO_PULL_UP);
  693.     } else if (soc_is_h5()) {
  694.         sunxi_gpio_set_cfgpin(SUNXI_GPA(4), SUN50I_H5_GPA_UART0);
  695.         sunxi_gpio_set_cfgpin(SUNXI_GPA(5), SUN50I_H5_GPA_UART0);
  696.         sunxi_gpio_set_pull(SUNXI_GPA(5), SUNXI_GPIO_PULL_UP);
  697.     } else if (soc_is_h6()) {
  698.     sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H6_GPH_UART0);
  699.     sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H6_GPH_UART0);
  700.     sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
  701.     } else if (soc_is_v3s()) {
  702.         sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN8I_V3S_GPB_UART0);
  703.         sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_V3S_GPB_UART0);
  704.         sunxi_gpio_set_pull(SUNXI_GPB(9), SUNXI_GPIO_PULL_UP);
  705.     } else {
  706.         /* Unknown SoC */
  707.         while (1) {}
  708.     }
  709. }
  710.  
  711. /*****************************************************************************/
  712.  
  713. static u32 uart0_base;
  714.  
  715. #define UART0_RBR (uart0_base + 0x0)    /* receive buffer register */
  716. #define UART0_THR (uart0_base + 0x0)    /* transmit holding register */
  717. #define UART0_DLL (uart0_base + 0x0)    /* divisor latch low register */
  718.  
  719. #define UART0_DLH (uart0_base + 0x4)    /* divisor latch high register */
  720. #define UART0_IER (uart0_base + 0x4)    /* interrupt enable reigster */
  721.  
  722. #define UART0_IIR (uart0_base + 0x8)    /* interrupt identity register */
  723. #define UART0_FCR (uart0_base + 0x8)    /* fifo control register */
  724.  
  725. #define UART0_LCR (uart0_base + 0xc)    /* line control register */
  726.  
  727. #define UART0_LSR (uart0_base + 0x14)   /* line status register */
  728.  
  729. #define BAUD_115200    (0xD) /* 24 * 1000 * 1000 / 16 / 115200 = 13 */
  730. #define NO_PARITY      (0)
  731. #define ONE_STOP_BIT   (0)
  732. #define DAT_LEN_8_BITS (3)
  733. #define LC_8_N_1       (NO_PARITY << 3 | ONE_STOP_BIT << 2 | DAT_LEN_8_BITS)
  734.  
  735. void uart0_init(void)
  736. {
  737.     clock_init_uart();
  738.  
  739.     /* select dll dlh */
  740.     writel(0x80, UART0_LCR);
  741.     /* set baudrate */
  742.     writel(0, UART0_DLH);
  743.     writel(BAUD_115200, UART0_DLL);
  744.     /* set line control */
  745.     writel(LC_8_N_1, UART0_LCR);
  746. }
  747.  
  748. void uart0_putc(char c)
  749. {
  750.     while (!(readl(UART0_LSR) & (1 << 6))) {}
  751.     writel(c, UART0_THR);
  752. }
  753.  
  754. void uart0_puts(const char *s)
  755. {
  756.     while (*s) {
  757.         if (*s == '\n')
  758.             uart0_putc('\r');
  759.         uart0_putc(*s++);
  760.     }
  761. }
  762.  
  763. /*****************************************************************************/
  764.  
  765. /* A workaround for https://patchwork.ozlabs.org/patch/622173 */
  766. void __attribute__((section(".start"))) __attribute__((naked)) start(void)
  767. {
  768.     asm volatile("b     main             \n"
  769.              ".long 0xffffffff       \n"
  770.              ".long 0xffffffff       \n"
  771.              ".long 0xffffffff       \n");
  772. }
  773.  
  774. #define EFUSE_LCJS  (0x48)
  775. #define EFUSE_ROTPK (0x70)
  776.  
  777. void print_chip_id() {
  778.     uart0_puts("chip_id: ");
  779.     u32 chip_id[4];
  780.     u32 i = 0;
  781.     for(i=0; i < 4; i++) {
  782.         chip_id[i] = sid_read_key(SUN8I_SID_BASE, 4*i);
  783.         printf("%x:", chip_id[i]);
  784.     }
  785.     uart0_puts("\r\n");
  786. }
  787.  
  788. void print_rotpk() {
  789.     uart0_puts("rotpk_hash: ");
  790.     u32 rotpk_hash[8];
  791.     u32 i = 0;
  792.     for(i=0; i < 8; i++) {
  793.         rotpk_hash[i] = sid_read_key(SUN8I_SID_BASE, EFUSE_ROTPK+4*i);
  794.         printf("%08x:", rotpk_hash[i]);
  795.     }
  796.     uart0_puts("\r\n");
  797. }
  798.  
  799. void print_lcjs() {
  800.     uart0_puts("LCJS:  ");
  801.     u32 LCJS = sid_read_key(SUN8I_SID_BASE, EFUSE_LCJS);
  802.     printf("%08x:", LCJS);
  803.     uart0_puts("\r\n");
  804. }
  805.  
  806. void print_secure() {
  807.  
  808.     uart0_puts("try read sram A2:");
  809.         if (readl(0x40004) == 0) {
  810.         uart0_puts("0x40004==0 non-secure\r\n");
  811.     } else {
  812.         uart0_puts("0x40004!=0 secure\r\n");
  813.     }
  814.     uart0_puts("\r\n");
  815. }
  816.  
  817. void print_stuff() {
  818.     print_chip_id();
  819.     print_rotpk();
  820.     print_lcjs();
  821.     print_secure();
  822.     uart0_puts("\r\n\n");
  823. }
  824.  
  825. enum { BOOT_DEVICE_UNK, BOOT_DEVICE_FEL, BOOT_DEVICE_MMC0, BOOT_DEVICE_SPI };
  826.  
  827. int get_boot_device(void)
  828. {
  829.     u32 *spl_signature = (void *)0x4;
  830.     if (soc_is_a64() || soc_is_a80() || soc_is_h5())
  831.         spl_signature = (void *)0x10004;
  832.     if (soc_is_h6())
  833.         spl_signature = (void *)0x20004;
  834.  
  835.     /* Check the eGON.BT0 magic in the SPL header */
  836.     if (spl_signature[0] != 0x4E4F4765 || spl_signature[1] != 0x3054422E)
  837.         return BOOT_DEVICE_FEL;
  838.  
  839.     u32 boot_dev = spl_signature[9] & 0xFF; /* offset into SPL = 0x28 */
  840.     if (boot_dev == 0)
  841.         return BOOT_DEVICE_MMC0;
  842.     if (boot_dev == 3)
  843.         return BOOT_DEVICE_SPI;
  844.  
  845.     return BOOT_DEVICE_UNK;
  846. }
  847.  
  848. void bases_init(void)
  849. {
  850.     if (soc_is_h6()) {
  851.         pio_base = H6_PIO_BASE;
  852.         uart0_base = H6_UART0_BASE;
  853.     } else {
  854.         pio_base = SUNXI_PIO_BASE;
  855.         uart0_base = SUNXI_UART0_BASE;
  856.     }
  857. }
  858.  
  859. int __attribute__((section(".start"))) main(void)
  860. {
  861.     soc_detection_init();
  862.     bases_init();
  863.     gpio_init();
  864.     uart0_init();
  865.  
  866.     uart0_puts("\nHello from ");
  867.     if (soc_is_a10())
  868.         uart0_puts("Allwinner A10!\n");
  869.     else if (soc_is_a10s())
  870.         uart0_puts("Allwinner A10s!\n");
  871.     else if (soc_is_a13())
  872.         uart0_puts("Allwinner A13!\n");
  873.     else if (soc_is_a20())
  874.         uart0_puts("Allwinner A20!\n");
  875.     else if (soc_is_a31())
  876.         uart0_puts("Allwinner A31/A31s!\n");
  877.     else if (soc_is_a64())
  878.         uart0_puts("Allwinner A64!\n");
  879.     else if (soc_is_h2_plus())
  880.         uart0_puts("Allwinner H2+!\n");
  881.     else if (soc_is_h3())
  882.         uart0_puts("Allwinner H3!\n");
  883.     else if (soc_is_h5())
  884.         uart0_puts("Allwinner H5!\n");
  885.     else if (soc_is_h6())
  886.         uart0_puts("Allwinner H6!\n");
  887.     else if (soc_is_r40())
  888.         uart0_puts("Allwinner R40!\n");
  889.     else if (soc_is_v3s())
  890.         uart0_puts("Allwinner V3s!\n");
  891.     else
  892.         uart0_puts("unknown Allwinner SoC!\n");
  893.     //asm("smc #0");
  894.  
  895.     asm volatile (
  896.         ".arch_extension sec\n"
  897.         "smc #0"
  898.     );
  899.  
  900.     switch (get_boot_device()) {
  901.     case BOOT_DEVICE_FEL:
  902.         print_stuff();
  903.         uart0_puts("Returning back to FEL.\n");
  904.         return 0;
  905.     case BOOT_DEVICE_MMC0:
  906.         uart0_puts("Booted from MMC0, entering an infinite loop.\n");
  907.         while (1) {}
  908.     case BOOT_DEVICE_SPI:
  909.         uart0_puts("Booted from SPI0, entering an infinite loop.\n");
  910.         while (1) {}
  911.     default:
  912.         uart0_puts("Booted from unknown media, entering an infinite loop.\n");
  913.         while (1) {}
  914.     };
  915.  
  916.     return 0;
  917. }
  918.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement