SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / board / sunxi / board.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
4  * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
5  *
6  * (C) Copyright 2007-2011
7  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
8  * Tom Cubie <tangliang@allwinnertech.com>
9  *
10  * Some board init for the Allwinner A10-evb board.
11  */
12
13 #include <common.h>
14 #include <mmc.h>
15 #include <axp_pmic.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/cpu.h>
18 #include <asm/arch/display.h>
19 #include <asm/arch/dram.h>
20 #include <asm/arch/gpio.h>
21 #include <asm/arch/mmc.h>
22 #include <asm/arch/spl.h>
23 #include <asm/arch/usb_phy.h>
24 #ifndef CONFIG_ARM64
25 #include <asm/armv7.h>
26 #endif
27 #include <asm/gpio.h>
28 #include <asm/io.h>
29 #include <crc.h>
30 #include <environment.h>
31 #include <linux/libfdt.h>
32 #include <nand.h>
33 #include <net.h>
34 #include <spl.h>
35 #include <sy8106a.h>
36 #include <asm/setup.h>
37
38 #if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD)
39 /* So that we can use pin names in Kconfig and sunxi_name_to_gpio() */
40 int soft_i2c_gpio_sda;
41 int soft_i2c_gpio_scl;
42
43 static int soft_i2c_board_init(void)
44 {
45         int ret;
46
47         soft_i2c_gpio_sda = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SDA);
48         if (soft_i2c_gpio_sda < 0) {
49                 printf("Error invalid soft i2c sda pin: '%s', err %d\n",
50                        CONFIG_VIDEO_LCD_PANEL_I2C_SDA, soft_i2c_gpio_sda);
51                 return soft_i2c_gpio_sda;
52         }
53         ret = gpio_request(soft_i2c_gpio_sda, "soft-i2c-sda");
54         if (ret) {
55                 printf("Error requesting soft i2c sda pin: '%s', err %d\n",
56                        CONFIG_VIDEO_LCD_PANEL_I2C_SDA, ret);
57                 return ret;
58         }
59
60         soft_i2c_gpio_scl = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SCL);
61         if (soft_i2c_gpio_scl < 0) {
62                 printf("Error invalid soft i2c scl pin: '%s', err %d\n",
63                        CONFIG_VIDEO_LCD_PANEL_I2C_SCL, soft_i2c_gpio_scl);
64                 return soft_i2c_gpio_scl;
65         }
66         ret = gpio_request(soft_i2c_gpio_scl, "soft-i2c-scl");
67         if (ret) {
68                 printf("Error requesting soft i2c scl pin: '%s', err %d\n",
69                        CONFIG_VIDEO_LCD_PANEL_I2C_SCL, ret);
70                 return ret;
71         }
72
73         return 0;
74 }
75 #else
76 static int soft_i2c_board_init(void) { return 0; }
77 #endif
78
79 DECLARE_GLOBAL_DATA_PTR;
80
81 void i2c_init_board(void)
82 {
83 #ifdef CONFIG_I2C0_ENABLE
84 #if defined(CONFIG_MACH_SUN4I) || \
85     defined(CONFIG_MACH_SUN5I) || \
86     defined(CONFIG_MACH_SUN7I) || \
87     defined(CONFIG_MACH_SUN8I_R40)
88         sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN4I_GPB_TWI0);
89         sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN4I_GPB_TWI0);
90         clock_twi_onoff(0, 1);
91 #elif defined(CONFIG_MACH_SUN6I)
92         sunxi_gpio_set_cfgpin(SUNXI_GPH(14), SUN6I_GPH_TWI0);
93         sunxi_gpio_set_cfgpin(SUNXI_GPH(15), SUN6I_GPH_TWI0);
94         clock_twi_onoff(0, 1);
95 #elif defined(CONFIG_MACH_SUN8I)
96         sunxi_gpio_set_cfgpin(SUNXI_GPH(2), SUN8I_GPH_TWI0);
97         sunxi_gpio_set_cfgpin(SUNXI_GPH(3), SUN8I_GPH_TWI0);
98         clock_twi_onoff(0, 1);
99 #endif
100 #endif
101
102 #ifdef CONFIG_I2C1_ENABLE
103 #if defined(CONFIG_MACH_SUN4I) || \
104     defined(CONFIG_MACH_SUN7I) || \
105     defined(CONFIG_MACH_SUN8I_R40)
106         sunxi_gpio_set_cfgpin(SUNXI_GPB(18), SUN4I_GPB_TWI1);
107         sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN4I_GPB_TWI1);
108         clock_twi_onoff(1, 1);
109 #elif defined(CONFIG_MACH_SUN5I)
110         sunxi_gpio_set_cfgpin(SUNXI_GPB(15), SUN5I_GPB_TWI1);
111         sunxi_gpio_set_cfgpin(SUNXI_GPB(16), SUN5I_GPB_TWI1);
112         clock_twi_onoff(1, 1);
113 #elif defined(CONFIG_MACH_SUN6I)
114         sunxi_gpio_set_cfgpin(SUNXI_GPH(16), SUN6I_GPH_TWI1);
115         sunxi_gpio_set_cfgpin(SUNXI_GPH(17), SUN6I_GPH_TWI1);
116         clock_twi_onoff(1, 1);
117 #elif defined(CONFIG_MACH_SUN8I)
118         sunxi_gpio_set_cfgpin(SUNXI_GPH(4), SUN8I_GPH_TWI1);
119         sunxi_gpio_set_cfgpin(SUNXI_GPH(5), SUN8I_GPH_TWI1);
120         clock_twi_onoff(1, 1);
121 #endif
122 #endif
123
124 #ifdef CONFIG_I2C2_ENABLE
125 #if defined(CONFIG_MACH_SUN4I) || \
126     defined(CONFIG_MACH_SUN7I) || \
127     defined(CONFIG_MACH_SUN8I_R40)
128         sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN4I_GPB_TWI2);
129         sunxi_gpio_set_cfgpin(SUNXI_GPB(21), SUN4I_GPB_TWI2);
130         clock_twi_onoff(2, 1);
131 #elif defined(CONFIG_MACH_SUN5I)
132         sunxi_gpio_set_cfgpin(SUNXI_GPB(17), SUN5I_GPB_TWI2);
133         sunxi_gpio_set_cfgpin(SUNXI_GPB(18), SUN5I_GPB_TWI2);
134         clock_twi_onoff(2, 1);
135 #elif defined(CONFIG_MACH_SUN6I)
136         sunxi_gpio_set_cfgpin(SUNXI_GPH(18), SUN6I_GPH_TWI2);
137         sunxi_gpio_set_cfgpin(SUNXI_GPH(19), SUN6I_GPH_TWI2);
138         clock_twi_onoff(2, 1);
139 #elif defined(CONFIG_MACH_SUN8I)
140         sunxi_gpio_set_cfgpin(SUNXI_GPE(12), SUN8I_GPE_TWI2);
141         sunxi_gpio_set_cfgpin(SUNXI_GPE(13), SUN8I_GPE_TWI2);
142         clock_twi_onoff(2, 1);
143 #endif
144 #endif
145
146 #ifdef CONFIG_I2C3_ENABLE
147 #if defined(CONFIG_MACH_SUN6I)
148         sunxi_gpio_set_cfgpin(SUNXI_GPG(10), SUN6I_GPG_TWI3);
149         sunxi_gpio_set_cfgpin(SUNXI_GPG(11), SUN6I_GPG_TWI3);
150         clock_twi_onoff(3, 1);
151 #elif defined(CONFIG_MACH_SUN7I) || \
152       defined(CONFIG_MACH_SUN8I_R40)
153         sunxi_gpio_set_cfgpin(SUNXI_GPI(0), SUN7I_GPI_TWI3);
154         sunxi_gpio_set_cfgpin(SUNXI_GPI(1), SUN7I_GPI_TWI3);
155         clock_twi_onoff(3, 1);
156 #endif
157 #endif
158
159 #ifdef CONFIG_I2C4_ENABLE
160 #if defined(CONFIG_MACH_SUN7I) || \
161     defined(CONFIG_MACH_SUN8I_R40)
162         sunxi_gpio_set_cfgpin(SUNXI_GPI(2), SUN7I_GPI_TWI4);
163         sunxi_gpio_set_cfgpin(SUNXI_GPI(3), SUN7I_GPI_TWI4);
164         clock_twi_onoff(4, 1);
165 #endif
166 #endif
167
168 #ifdef CONFIG_R_I2C_ENABLE
169         clock_twi_onoff(5, 1);
170         sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);
171         sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_H3_GPL_R_TWI);
172 #endif
173 }
174
175 #if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT)
176 enum env_location env_get_location(enum env_operation op, int prio)
177 {
178         switch (prio) {
179         case 0:
180                 return ENVL_FAT;
181
182         case 1:
183                 return ENVL_MMC;
184
185         default:
186                 return ENVL_UNKNOWN;
187         }
188 }
189 #endif
190
191 /* add board specific code here */
192 int board_init(void)
193 {
194         __maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
195
196         gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
197
198 #ifndef CONFIG_ARM64
199         asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
200         debug("id_pfr1: 0x%08x\n", id_pfr1);
201         /* Generic Timer Extension available? */
202         if ((id_pfr1 >> CPUID_ARM_GENTIMER_SHIFT) & 0xf) {
203                 uint32_t freq;
204
205                 debug("Setting CNTFRQ\n");
206
207                 /*
208                  * CNTFRQ is a secure register, so we will crash if we try to
209                  * write this from the non-secure world (read is OK, though).
210                  * In case some bootcode has already set the correct value,
211                  * we avoid the risk of writing to it.
212                  */
213                 asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(freq));
214                 if (freq != COUNTER_FREQUENCY) {
215                         debug("arch timer frequency is %d Hz, should be %d, fixing ...\n",
216                               freq, COUNTER_FREQUENCY);
217 #ifdef CONFIG_NON_SECURE
218                         printf("arch timer frequency is wrong, but cannot adjust it\n");
219 #else
220                         asm volatile("mcr p15, 0, %0, c14, c0, 0"
221                                      : : "r"(COUNTER_FREQUENCY));
222 #endif
223                 }
224         }
225 #endif /* !CONFIG_ARM64 */
226
227         ret = axp_gpio_init();
228         if (ret)
229                 return ret;
230
231 #ifdef CONFIG_SATAPWR
232         satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
233         gpio_request(satapwr_pin, "satapwr");
234         gpio_direction_output(satapwr_pin, 1);
235         /* Give attached sata device time to power-up to avoid link timeouts */
236         mdelay(500);
237 #endif
238 #ifdef CONFIG_MACPWR
239         macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
240         gpio_request(macpwr_pin, "macpwr");
241         gpio_direction_output(macpwr_pin, 1);
242 #endif
243
244 #ifdef CONFIG_DM_I2C
245         /*
246          * Temporary workaround for enabling I2C clocks until proper sunxi DM
247          * clk, reset and pinctrl drivers land.
248          */
249         i2c_init_board();
250 #endif
251
252         /* Uses dm gpio code so do this here and not in i2c_init_board() */
253         return soft_i2c_board_init();
254 }
255
256 int dram_init(void)
257 {
258         gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
259
260         return 0;
261 }
262
263 #if defined(CONFIG_NAND_SUNXI)
264 static void nand_pinmux_setup(void)
265 {
266         unsigned int pin;
267
268         for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(19); pin++)
269                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
270
271 #if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN7I
272         for (pin = SUNXI_GPC(20); pin <= SUNXI_GPC(22); pin++)
273                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
274 #endif
275         /* sun4i / sun7i do have a PC23, but it is not used for nand,
276          * only sun7i has a PC24 */
277 #ifdef CONFIG_MACH_SUN7I
278         sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_NAND);
279 #endif
280 }
281
282 static void nand_clock_setup(void)
283 {
284         struct sunxi_ccm_reg *const ccm =
285                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
286
287         setbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
288 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I || \
289     defined CONFIG_MACH_SUN9I || defined CONFIG_MACH_SUN50I
290         setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_NAND0));
291 #endif
292         setbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
293 }
294
295 void board_nand_init(void)
296 {
297         nand_pinmux_setup();
298         nand_clock_setup();
299 #ifndef CONFIG_SPL_BUILD
300         sunxi_nand_init();
301 #endif
302 }
303 #endif
304
305 #ifdef CONFIG_MMC
306 static void mmc_pinmux_setup(int sdc)
307 {
308         unsigned int pin;
309         __maybe_unused int pins;
310
311         switch (sdc) {
312         case 0:
313                 /* SDC0: PF0-PF5 */
314                 for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
315                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPF_SDC0);
316                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
317                         sunxi_gpio_set_drv(pin, 2);
318                 }
319                 break;
320
321         case 1:
322                 pins = sunxi_name_to_gpio_bank(CONFIG_MMC1_PINS);
323
324 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
325     defined(CONFIG_MACH_SUN8I_R40)
326                 if (pins == SUNXI_GPIO_H) {
327                         /* SDC1: PH22-PH-27 */
328                         for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) {
329                                 sunxi_gpio_set_cfgpin(pin, SUN4I_GPH_SDC1);
330                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
331                                 sunxi_gpio_set_drv(pin, 2);
332                         }
333                 } else {
334                         /* SDC1: PG0-PG5 */
335                         for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
336                                 sunxi_gpio_set_cfgpin(pin, SUN4I_GPG_SDC1);
337                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
338                                 sunxi_gpio_set_drv(pin, 2);
339                         }
340                 }
341 #elif defined(CONFIG_MACH_SUN5I)
342                 /* SDC1: PG3-PG8 */
343                 for (pin = SUNXI_GPG(3); pin <= SUNXI_GPG(8); pin++) {
344                         sunxi_gpio_set_cfgpin(pin, SUN5I_GPG_SDC1);
345                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
346                         sunxi_gpio_set_drv(pin, 2);
347                 }
348 #elif defined(CONFIG_MACH_SUN6I)
349                 /* SDC1: PG0-PG5 */
350                 for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
351                         sunxi_gpio_set_cfgpin(pin, SUN6I_GPG_SDC1);
352                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
353                         sunxi_gpio_set_drv(pin, 2);
354                 }
355 #elif defined(CONFIG_MACH_SUN8I)
356                 if (pins == SUNXI_GPIO_D) {
357                         /* SDC1: PD2-PD7 */
358                         for (pin = SUNXI_GPD(2); pin <= SUNXI_GPD(7); pin++) {
359                                 sunxi_gpio_set_cfgpin(pin, SUN8I_GPD_SDC1);
360                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
361                                 sunxi_gpio_set_drv(pin, 2);
362                         }
363                 } else {
364                         /* SDC1: PG0-PG5 */
365                         for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
366                                 sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1);
367                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
368                                 sunxi_gpio_set_drv(pin, 2);
369                         }
370                 }
371 #endif
372                 break;
373
374         case 2:
375                 pins = sunxi_name_to_gpio_bank(CONFIG_MMC2_PINS);
376
377 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
378                 /* SDC2: PC6-PC11 */
379                 for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); pin++) {
380                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
381                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
382                         sunxi_gpio_set_drv(pin, 2);
383                 }
384 #elif defined(CONFIG_MACH_SUN5I)
385                 if (pins == SUNXI_GPIO_E) {
386                         /* SDC2: PE4-PE9 */
387                         for (pin = SUNXI_GPE(4); pin <= SUNXI_GPD(9); pin++) {
388                                 sunxi_gpio_set_cfgpin(pin, SUN5I_GPE_SDC2);
389                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
390                                 sunxi_gpio_set_drv(pin, 2);
391                         }
392                 } else {
393                         /* SDC2: PC6-PC15 */
394                         for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
395                                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
396                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
397                                 sunxi_gpio_set_drv(pin, 2);
398                         }
399                 }
400 #elif defined(CONFIG_MACH_SUN6I)
401                 if (pins == SUNXI_GPIO_A) {
402                         /* SDC2: PA9-PA14 */
403                         for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
404                                 sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC2);
405                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
406                                 sunxi_gpio_set_drv(pin, 2);
407                         }
408                 } else {
409                         /* SDC2: PC6-PC15, PC24 */
410                         for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
411                                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
412                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
413                                 sunxi_gpio_set_drv(pin, 2);
414                         }
415
416                         sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
417                         sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
418                         sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
419                 }
420 #elif defined(CONFIG_MACH_SUN8I_R40)
421                 /* SDC2: PC6-PC15, PC24 */
422                 for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
423                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
424                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
425                         sunxi_gpio_set_drv(pin, 2);
426                 }
427
428                 sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
429                 sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
430                 sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
431 #elif defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I)
432                 /* SDC2: PC5-PC6, PC8-PC16 */
433                 for (pin = SUNXI_GPC(5); pin <= SUNXI_GPC(6); pin++) {
434                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
435                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
436                         sunxi_gpio_set_drv(pin, 2);
437                 }
438
439                 for (pin = SUNXI_GPC(8); pin <= SUNXI_GPC(16); pin++) {
440                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
441                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
442                         sunxi_gpio_set_drv(pin, 2);
443                 }
444 #elif defined(CONFIG_MACH_SUN9I)
445                 /* SDC2: PC6-PC16 */
446                 for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(16); pin++) {
447                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
448                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
449                         sunxi_gpio_set_drv(pin, 2);
450                 }
451 #endif
452                 break;
453
454         case 3:
455                 pins = sunxi_name_to_gpio_bank(CONFIG_MMC3_PINS);
456
457 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
458     defined(CONFIG_MACH_SUN8I_R40)
459                 /* SDC3: PI4-PI9 */
460                 for (pin = SUNXI_GPI(4); pin <= SUNXI_GPI(9); pin++) {
461                         sunxi_gpio_set_cfgpin(pin, SUNXI_GPI_SDC3);
462                         sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
463                         sunxi_gpio_set_drv(pin, 2);
464                 }
465 #elif defined(CONFIG_MACH_SUN6I)
466                 if (pins == SUNXI_GPIO_A) {
467                         /* SDC3: PA9-PA14 */
468                         for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
469                                 sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC3);
470                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
471                                 sunxi_gpio_set_drv(pin, 2);
472                         }
473                 } else {
474                         /* SDC3: PC6-PC15, PC24 */
475                         for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
476                                 sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3);
477                                 sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
478                                 sunxi_gpio_set_drv(pin, 2);
479                         }
480
481                         sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3);
482                         sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
483                         sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
484                 }
485 #endif
486                 break;
487
488         default:
489                 printf("sunxi: invalid MMC slot %d for pinmux setup\n", sdc);
490                 break;
491         }
492 }
493
494 int board_mmc_init(bd_t *bis)
495 {
496         __maybe_unused struct mmc *mmc0, *mmc1;
497         __maybe_unused char buf[512];
498
499         mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
500         mmc0 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
501         if (!mmc0)
502                 return -1;
503
504 #if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
505         mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
506         mmc1 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
507         if (!mmc1)
508                 return -1;
509 #endif
510
511         return 0;
512 }
513 #endif
514
515 #ifdef CONFIG_SPL_BUILD
516 void sunxi_board_init(void)
517 {
518         int power_failed = 0;
519
520 #ifdef CONFIG_SY8106A_POWER
521         power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT);
522 #endif
523
524 #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
525         defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
526         defined CONFIG_AXP818_POWER
527         power_failed = axp_init();
528
529 #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
530         defined CONFIG_AXP818_POWER
531         power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
532 #endif
533         power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
534         power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
535 #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
536         power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
537 #endif
538 #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
539         defined CONFIG_AXP818_POWER
540         power_failed |= axp_set_dcdc5(CONFIG_AXP_DCDC5_VOLT);
541 #endif
542
543 #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
544         defined CONFIG_AXP818_POWER
545         power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
546 #endif
547         power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
548 #if !defined(CONFIG_AXP152_POWER)
549         power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
550 #endif
551 #ifdef CONFIG_AXP209_POWER
552         power_failed |= axp_set_aldo4(CONFIG_AXP_ALDO4_VOLT);
553 #endif
554
555 #if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP809_POWER) || \
556         defined(CONFIG_AXP818_POWER)
557         power_failed |= axp_set_dldo(1, CONFIG_AXP_DLDO1_VOLT);
558         power_failed |= axp_set_dldo(2, CONFIG_AXP_DLDO2_VOLT);
559 #if !defined CONFIG_AXP809_POWER
560         power_failed |= axp_set_dldo(3, CONFIG_AXP_DLDO3_VOLT);
561         power_failed |= axp_set_dldo(4, CONFIG_AXP_DLDO4_VOLT);
562 #endif
563         power_failed |= axp_set_eldo(1, CONFIG_AXP_ELDO1_VOLT);
564         power_failed |= axp_set_eldo(2, CONFIG_AXP_ELDO2_VOLT);
565         power_failed |= axp_set_eldo(3, CONFIG_AXP_ELDO3_VOLT);
566 #endif
567
568 #ifdef CONFIG_AXP818_POWER
569         power_failed |= axp_set_fldo(1, CONFIG_AXP_FLDO1_VOLT);
570         power_failed |= axp_set_fldo(2, CONFIG_AXP_FLDO2_VOLT);
571         power_failed |= axp_set_fldo(3, CONFIG_AXP_FLDO3_VOLT);
572 #endif
573
574 #if defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
575         power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
576 #endif
577 #endif
578         printf("DRAM:");
579         gd->ram_size = sunxi_dram_init();
580         printf(" %d MiB\n", (int)(gd->ram_size >> 20));
581         if (!gd->ram_size)
582                 hang();
583
584         /*
585          * Only clock up the CPU to full speed if we are reasonably
586          * assured it's being powered with suitable core voltage
587          */
588         if (!power_failed)
589                 clock_set_pll1(CONFIG_SYS_CLK_FREQ);
590         else
591                 printf("Failed to set core voltage! Can't set CPU frequency\n");
592 }
593 #endif
594
595 #ifdef CONFIG_USB_GADGET
596 int g_dnl_board_usb_cable_connected(void)
597 {
598         return sunxi_usb_phy_vbus_detect(0);
599 }
600 #endif
601
602 #ifdef CONFIG_SERIAL_TAG
603 void get_board_serial(struct tag_serialnr *serialnr)
604 {
605         char *serial_string;
606         unsigned long long serial;
607
608         serial_string = env_get("serial#");
609
610         if (serial_string) {
611                 serial = simple_strtoull(serial_string, NULL, 16);
612
613                 serialnr->high = (unsigned int) (serial >> 32);
614                 serialnr->low = (unsigned int) (serial & 0xffffffff);
615         } else {
616                 serialnr->high = 0;
617                 serialnr->low = 0;
618         }
619 }
620 #endif
621
622 /*
623  * Check the SPL header for the "sunxi" variant. If found: parse values
624  * that might have been passed by the loader ("fel" utility), and update
625  * the environment accordingly.
626  */
627 static void parse_spl_header(const uint32_t spl_addr)
628 {
629         struct boot_file_head *spl = (void *)(ulong)spl_addr;
630         if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0)
631                 return; /* signature mismatch, no usable header */
632
633         uint8_t spl_header_version = spl->spl_signature[3];
634         if (spl_header_version != SPL_HEADER_VERSION) {
635                 printf("sunxi SPL version mismatch: expected %u, got %u\n",
636                        SPL_HEADER_VERSION, spl_header_version);
637                 return;
638         }
639         if (!spl->fel_script_address)
640                 return;
641
642         if (spl->fel_uEnv_length != 0) {
643                 /*
644                  * data is expected in uEnv.txt compatible format, so "env
645                  * import -t" the string(s) at fel_script_address right away.
646                  */
647                 himport_r(&env_htab, (char *)(uintptr_t)spl->fel_script_address,
648                           spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
649                 return;
650         }
651         /* otherwise assume .scr format (mkimage-type script) */
652         env_set_hex("fel_scriptaddr", spl->fel_script_address);
653 }
654
655 /*
656  * Note this function gets called multiple times.
657  * It must not make any changes to env variables which already exist.
658  */
659 static void setup_environment(const void *fdt)
660 {
661         char serial_string[17] = { 0 };
662         unsigned int sid[4];
663         uint8_t mac_addr[6];
664         char ethaddr[16];
665         int i, ret;
666
667         ret = sunxi_get_sid(sid);
668         if (ret == 0 && sid[0] != 0) {
669                 /*
670                  * The single words 1 - 3 of the SID have quite a few bits
671                  * which are the same on many models, so we take a crc32
672                  * of all 3 words, to get a more unique value.
673                  *
674                  * Note we only do this on newer SoCs as we cannot change
675                  * the algorithm on older SoCs since those have been using
676                  * fixed mac-addresses based on only using word 3 for a
677                  * long time and changing a fixed mac-address with an
678                  * u-boot update is not good.
679                  */
680 #if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
681     !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
682     !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
683                 sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
684 #endif
685
686                 /* Ensure the NIC specific bytes of the mac are not all 0 */
687                 if ((sid[3] & 0xffffff) == 0)
688                         sid[3] |= 0x800000;
689
690                 for (i = 0; i < 4; i++) {
691                         sprintf(ethaddr, "ethernet%d", i);
692                         if (!fdt_get_alias(fdt, ethaddr))
693                                 continue;
694
695                         if (i == 0)
696                                 strcpy(ethaddr, "ethaddr");
697                         else
698                                 sprintf(ethaddr, "eth%daddr", i);
699
700                         if (env_get(ethaddr))
701                                 continue;
702
703                         /* Non OUI / registered MAC address */
704                         mac_addr[0] = (i << 4) | 0x02;
705                         mac_addr[1] = (sid[0] >>  0) & 0xff;
706                         mac_addr[2] = (sid[3] >> 24) & 0xff;
707                         mac_addr[3] = (sid[3] >> 16) & 0xff;
708                         mac_addr[4] = (sid[3] >>  8) & 0xff;
709                         mac_addr[5] = (sid[3] >>  0) & 0xff;
710
711                         eth_env_set_enetaddr(ethaddr, mac_addr);
712                 }
713
714                 if (!env_get("serial#")) {
715                         snprintf(serial_string, sizeof(serial_string),
716                                 "%08x%08x", sid[0], sid[3]);
717
718                         env_set("serial#", serial_string);
719                 }
720         }
721 }
722
723 int misc_init_r(void)
724 {
725         __maybe_unused int ret;
726         uint boot;
727
728         env_set("fel_booted", NULL);
729         env_set("fel_scriptaddr", NULL);
730         env_set("mmc_bootdev", NULL);
731
732         boot = sunxi_get_boot_device();
733         /* determine if we are running in FEL mode */
734         if (boot == BOOT_DEVICE_BOARD) {
735                 env_set("fel_booted", "1");
736                 parse_spl_header(SPL_ADDR);
737         /* or if we booted from MMC, and which one */
738         } else if (boot == BOOT_DEVICE_MMC1) {
739                 env_set("mmc_bootdev", "0");
740         } else if (boot == BOOT_DEVICE_MMC2) {
741                 env_set("mmc_bootdev", "1");
742         }
743
744         setup_environment(gd->fdt_blob);
745
746 #ifndef CONFIG_MACH_SUN9I
747         ret = sunxi_usb_phy_probe();
748         if (ret)
749                 return ret;
750 #endif
751
752 #ifdef CONFIG_USB_ETHER
753         usb_ether_init();
754 #endif
755
756         return 0;
757 }
758
759 int ft_board_setup(void *blob, bd_t *bd)
760 {
761         int __maybe_unused r;
762
763         /*
764          * Call setup_environment again in case the boot fdt has
765          * ethernet aliases the u-boot copy does not have.
766          */
767         setup_environment(blob);
768
769 #ifdef CONFIG_VIDEO_DT_SIMPLEFB
770         r = sunxi_simplefb_setup(blob);
771         if (r)
772                 return r;
773 #endif
774         return 0;
775 }
776
777 #ifdef CONFIG_SPL_LOAD_FIT
778 int board_fit_config_name_match(const char *name)
779 {
780         struct boot_file_head *spl = (void *)(ulong)SPL_ADDR;
781         const char *cmp_str = (void *)(ulong)SPL_ADDR;
782
783         /* Check if there is a DT name stored in the SPL header and use that. */
784         if (spl->dt_name_offset) {
785                 cmp_str += spl->dt_name_offset;
786         } else {
787 #ifdef CONFIG_DEFAULT_DEVICE_TREE
788                 cmp_str = CONFIG_DEFAULT_DEVICE_TREE;
789 #else
790                 return 0;
791 #endif
792         };
793
794 /* Differentiate the two Pine64 board DTs by their DRAM size. */
795         if (strstr(name, "-pine64") && strstr(cmp_str, "-pine64")) {
796                 if ((gd->ram_size > 512 * 1024 * 1024))
797                         return !strstr(name, "plus");
798                 else
799                         return !!strstr(name, "plus");
800         } else {
801                 return strcmp(name, cmp_str);
802         }
803 }
804 #endif