board.c 25.2 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2 3 4 5 6 7 8 9 10 11 12 13
/*
 * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
 * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 *
 * (C) Copyright 2007-2011
 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
 * Tom Cubie <tangliang@allwinnertech.com>
 *
 * Some board init for the Allwinner A10-evb board.
 */

#include <common.h>
14
#include <dm.h>
Simon Glass's avatar
Simon Glass committed
15
#include <env.h>
16
#include <hang.h>
17
#include <image.h>
18
#include <init.h>
19
#include <log.h>
20
#include <mmc.h>
21
#include <axp_pmic.h>
22 23
#include <generic-phy.h>
#include <phy-sun4i-usb.h>
24
#include <asm/arch/clock.h>
25
#include <asm/arch/cpu.h>
26
#include <asm/arch/display.h>
27
#include <asm/arch/dram.h>
Ian Campbell's avatar
Ian Campbell committed
28 29
#include <asm/arch/gpio.h>
#include <asm/arch/mmc.h>
30
#include <asm/arch/spl.h>
31
#include <linux/delay.h>
32
#include <u-boot/crc.h>
33 34 35
#ifndef CONFIG_ARM64
#include <asm/armv7.h>
#endif
36
#include <asm/gpio.h>
37
#include <asm/io.h>
38
#include <u-boot/crc.h>
39
#include <env_internal.h>
40
#include <linux/libfdt.h>
41
#include <nand.h>
42
#include <net.h>
43
#include <spl.h>
44
#include <sy8106a.h>
45
#include <asm/setup.h>
46

47 48 49 50
#if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD)
/* So that we can use pin names in Kconfig and sunxi_name_to_gpio() */
int soft_i2c_gpio_sda;
int soft_i2c_gpio_scl;
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

static int soft_i2c_board_init(void)
{
	int ret;

	soft_i2c_gpio_sda = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SDA);
	if (soft_i2c_gpio_sda < 0) {
		printf("Error invalid soft i2c sda pin: '%s', err %d\n",
		       CONFIG_VIDEO_LCD_PANEL_I2C_SDA, soft_i2c_gpio_sda);
		return soft_i2c_gpio_sda;
	}
	ret = gpio_request(soft_i2c_gpio_sda, "soft-i2c-sda");
	if (ret) {
		printf("Error requesting soft i2c sda pin: '%s', err %d\n",
		       CONFIG_VIDEO_LCD_PANEL_I2C_SDA, ret);
		return ret;
	}

	soft_i2c_gpio_scl = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SCL);
	if (soft_i2c_gpio_scl < 0) {
		printf("Error invalid soft i2c scl pin: '%s', err %d\n",
		       CONFIG_VIDEO_LCD_PANEL_I2C_SCL, soft_i2c_gpio_scl);
		return soft_i2c_gpio_scl;
	}
	ret = gpio_request(soft_i2c_gpio_scl, "soft-i2c-scl");
	if (ret) {
		printf("Error requesting soft i2c scl pin: '%s', err %d\n",
		       CONFIG_VIDEO_LCD_PANEL_I2C_SCL, ret);
		return ret;
	}

	return 0;
}
#else
static int soft_i2c_board_init(void) { return 0; }
86 87
#endif

88 89
DECLARE_GLOBAL_DATA_PTR;

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
void i2c_init_board(void)
{
#ifdef CONFIG_I2C0_ENABLE
#if defined(CONFIG_MACH_SUN4I) || \
    defined(CONFIG_MACH_SUN5I) || \
    defined(CONFIG_MACH_SUN7I) || \
    defined(CONFIG_MACH_SUN8I_R40)
	sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN4I_GPB_TWI0);
	sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN4I_GPB_TWI0);
	clock_twi_onoff(0, 1);
#elif defined(CONFIG_MACH_SUN6I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(14), SUN6I_GPH_TWI0);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(15), SUN6I_GPH_TWI0);
	clock_twi_onoff(0, 1);
#elif defined(CONFIG_MACH_SUN8I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(2), SUN8I_GPH_TWI0);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(3), SUN8I_GPH_TWI0);
	clock_twi_onoff(0, 1);
108 109 110 111
#elif defined(CONFIG_MACH_SUN50I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_GPH_TWI0);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_GPH_TWI0);
	clock_twi_onoff(0, 1);
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
#endif
#endif

#ifdef CONFIG_I2C1_ENABLE
#if defined(CONFIG_MACH_SUN4I) || \
    defined(CONFIG_MACH_SUN7I) || \
    defined(CONFIG_MACH_SUN8I_R40)
	sunxi_gpio_set_cfgpin(SUNXI_GPB(18), SUN4I_GPB_TWI1);
	sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN4I_GPB_TWI1);
	clock_twi_onoff(1, 1);
#elif defined(CONFIG_MACH_SUN5I)
	sunxi_gpio_set_cfgpin(SUNXI_GPB(15), SUN5I_GPB_TWI1);
	sunxi_gpio_set_cfgpin(SUNXI_GPB(16), SUN5I_GPB_TWI1);
	clock_twi_onoff(1, 1);
#elif defined(CONFIG_MACH_SUN6I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(16), SUN6I_GPH_TWI1);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(17), SUN6I_GPH_TWI1);
	clock_twi_onoff(1, 1);
#elif defined(CONFIG_MACH_SUN8I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(4), SUN8I_GPH_TWI1);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(5), SUN8I_GPH_TWI1);
	clock_twi_onoff(1, 1);
134 135 136 137
#elif defined(CONFIG_MACH_SUN50I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(2), SUN50I_GPH_TWI1);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(3), SUN50I_GPH_TWI1);
	clock_twi_onoff(1, 1);
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
#endif
#endif

#ifdef CONFIG_I2C2_ENABLE
#if defined(CONFIG_MACH_SUN4I) || \
    defined(CONFIG_MACH_SUN7I) || \
    defined(CONFIG_MACH_SUN8I_R40)
	sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN4I_GPB_TWI2);
	sunxi_gpio_set_cfgpin(SUNXI_GPB(21), SUN4I_GPB_TWI2);
	clock_twi_onoff(2, 1);
#elif defined(CONFIG_MACH_SUN5I)
	sunxi_gpio_set_cfgpin(SUNXI_GPB(17), SUN5I_GPB_TWI2);
	sunxi_gpio_set_cfgpin(SUNXI_GPB(18), SUN5I_GPB_TWI2);
	clock_twi_onoff(2, 1);
#elif defined(CONFIG_MACH_SUN6I)
	sunxi_gpio_set_cfgpin(SUNXI_GPH(18), SUN6I_GPH_TWI2);
	sunxi_gpio_set_cfgpin(SUNXI_GPH(19), SUN6I_GPH_TWI2);
	clock_twi_onoff(2, 1);
#elif defined(CONFIG_MACH_SUN8I)
	sunxi_gpio_set_cfgpin(SUNXI_GPE(12), SUN8I_GPE_TWI2);
	sunxi_gpio_set_cfgpin(SUNXI_GPE(13), SUN8I_GPE_TWI2);
	clock_twi_onoff(2, 1);
160 161 162 163
#elif defined(CONFIG_MACH_SUN50I)
	sunxi_gpio_set_cfgpin(SUNXI_GPE(14), SUN50I_GPE_TWI2);
	sunxi_gpio_set_cfgpin(SUNXI_GPE(15), SUN50I_GPE_TWI2);
	clock_twi_onoff(2, 1);
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
#endif
#endif

#ifdef CONFIG_I2C3_ENABLE
#if defined(CONFIG_MACH_SUN6I)
	sunxi_gpio_set_cfgpin(SUNXI_GPG(10), SUN6I_GPG_TWI3);
	sunxi_gpio_set_cfgpin(SUNXI_GPG(11), SUN6I_GPG_TWI3);
	clock_twi_onoff(3, 1);
#elif defined(CONFIG_MACH_SUN7I) || \
      defined(CONFIG_MACH_SUN8I_R40)
	sunxi_gpio_set_cfgpin(SUNXI_GPI(0), SUN7I_GPI_TWI3);
	sunxi_gpio_set_cfgpin(SUNXI_GPI(1), SUN7I_GPI_TWI3);
	clock_twi_onoff(3, 1);
#endif
#endif

#ifdef CONFIG_I2C4_ENABLE
#if defined(CONFIG_MACH_SUN7I) || \
    defined(CONFIG_MACH_SUN8I_R40)
	sunxi_gpio_set_cfgpin(SUNXI_GPI(2), SUN7I_GPI_TWI4);
	sunxi_gpio_set_cfgpin(SUNXI_GPI(3), SUN7I_GPI_TWI4);
	clock_twi_onoff(4, 1);
#endif
#endif

#ifdef CONFIG_R_I2C_ENABLE
190 191 192 193 194
#ifdef CONFIG_MACH_SUN50I
	clock_twi_onoff(5, 1);
	sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI);
	sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI);
#else
195 196 197 198
	clock_twi_onoff(5, 1);
	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);
	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_H3_GPL_R_TWI);
#endif
199
#endif
200 201
}

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT)
enum env_location env_get_location(enum env_operation op, int prio)
{
	switch (prio) {
	case 0:
		return ENVL_FAT;

	case 1:
		return ENVL_MMC;

	default:
		return ENVL_UNKNOWN;
	}
}
#endif

218 219 220 221
#ifdef CONFIG_DM_MMC
static void mmc_pinmux_setup(int sdc);
#endif

222 223 224
/* add board specific code here */
int board_init(void)
{
225
	__maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
226 227 228

	gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);

229
#ifndef CONFIG_ARM64
230 231 232
	asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
	debug("id_pfr1: 0x%08x\n", id_pfr1);
	/* Generic Timer Extension available? */
233 234 235
	if ((id_pfr1 >> CPUID_ARM_GENTIMER_SHIFT) & 0xf) {
		uint32_t freq;

236
		debug("Setting CNTFRQ\n");
237 238 239 240 241 242 243 244

		/*
		 * CNTFRQ is a secure register, so we will crash if we try to
		 * write this from the non-secure world (read is OK, though).
		 * In case some bootcode has already set the correct value,
		 * we avoid the risk of writing to it.
		 */
		asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(freq));
245
		if (freq != COUNTER_FREQUENCY) {
246
			debug("arch timer frequency is %d Hz, should be %d, fixing ...\n",
247
			      freq, COUNTER_FREQUENCY);
248 249 250 251
#ifdef CONFIG_NON_SECURE
			printf("arch timer frequency is wrong, but cannot adjust it\n");
#else
			asm volatile("mcr p15, 0, %0, c14, c0, 0"
252
				     : : "r"(COUNTER_FREQUENCY));
253 254
#endif
		}
255
	}
256
#endif /* !CONFIG_ARM64 */
257

258 259 260 261
	ret = axp_gpio_init();
	if (ret)
		return ret;

262
#ifdef CONFIG_SATAPWR
263 264 265
	satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
	gpio_request(satapwr_pin, "satapwr");
	gpio_direction_output(satapwr_pin, 1);
266 267
	/* Give attached sata device time to power-up to avoid link timeouts */
	mdelay(500);
268
#endif
269
#ifdef CONFIG_MACPWR
270 271 272
	macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
	gpio_request(macpwr_pin, "macpwr");
	gpio_direction_output(macpwr_pin, 1);
273 274
#endif

275 276 277 278 279 280 281 282
#ifdef CONFIG_DM_I2C
	/*
	 * Temporary workaround for enabling I2C clocks until proper sunxi DM
	 * clk, reset and pinctrl drivers land.
	 */
	i2c_init_board();
#endif

283 284 285 286 287 288 289 290 291 292 293
#ifdef CONFIG_DM_MMC
	/*
	 * Temporary workaround for enabling MMC clocks until a sunxi DM
	 * pinctrl driver lands.
	 */
	mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
	mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
#endif
#endif	/* CONFIG_DM_MMC */

294 295
	/* Uses dm gpio code so do this here and not in i2c_init_board() */
	return soft_i2c_board_init();
296 297
}

298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
/*
 * On older SoCs the SPL is actually at address zero, so using NULL as
 * an error value does not work.
 */
#define INVALID_SPL_HEADER ((void *)~0UL)

static struct boot_file_head * get_spl_header(uint8_t req_version)
{
	struct boot_file_head *spl = (void *)(ulong)SPL_ADDR;
	uint8_t spl_header_version = spl->spl_signature[3];

	/* Is there really the SPL header (still) there? */
	if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0)
		return INVALID_SPL_HEADER;

	if (spl_header_version < req_version) {
		printf("sunxi SPL version mismatch: expected %u, got %u\n",
		       req_version, spl_header_version);
		return INVALID_SPL_HEADER;
	}

	return spl;
}

322 323
int dram_init(void)
{
324 325 326 327 328 329 330 331 332 333
	struct boot_file_head *spl = get_spl_header(SPL_DRAM_HEADER_VERSION);

	if (spl == INVALID_SPL_HEADER)
		gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0,
					    PHYS_SDRAM_0_SIZE);
	else
		gd->ram_size = (phys_addr_t)spl->dram_size << 20;

	if (gd->ram_size > CONFIG_SUNXI_DRAM_MAX_SIZE)
		gd->ram_size = CONFIG_SUNXI_DRAM_MAX_SIZE;
334 335 336 337

	return 0;
}

338
#if defined(CONFIG_NAND_SUNXI)
339 340 341 342
static void nand_pinmux_setup(void)
{
	unsigned int pin;

343
	for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(19); pin++)
344 345
		sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);

346 347 348 349 350 351 352
#if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN7I
	for (pin = SUNXI_GPC(20); pin <= SUNXI_GPC(22); pin++)
		sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
#endif
	/* sun4i / sun7i do have a PC23, but it is not used for nand,
	 * only sun7i has a PC24 */
#ifdef CONFIG_MACH_SUN7I
353
	sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_NAND);
354
#endif
355 356 357 358 359 360
}

static void nand_clock_setup(void)
{
	struct sunxi_ccm_reg *const ccm =
		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
361

362
	setbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
363 364 365
#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I || \
    defined CONFIG_MACH_SUN9I || defined CONFIG_MACH_SUN50I
	setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_NAND0));
366
#endif
367 368
	setbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
}
369 370 371 372 373

void board_nand_init(void)
{
	nand_pinmux_setup();
	nand_clock_setup();
374 375 376
#ifndef CONFIG_SPL_BUILD
	sunxi_nand_init();
#endif
377
}
378 379
#endif

380
#ifdef CONFIG_MMC
Ian Campbell's avatar
Ian Campbell committed
381 382 383
static void mmc_pinmux_setup(int sdc)
{
	unsigned int pin;
384
	__maybe_unused int pins;
Ian Campbell's avatar
Ian Campbell committed
385 386 387

	switch (sdc) {
	case 0:
388
		/* SDC0: PF0-PF5 */
Ian Campbell's avatar
Ian Campbell committed
389
		for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
390
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPF_SDC0);
Ian Campbell's avatar
Ian Campbell committed
391 392 393 394 395 396
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}
		break;

	case 1:
397 398
		pins = sunxi_name_to_gpio_bank(CONFIG_MMC1_PINS);

399 400
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
    defined(CONFIG_MACH_SUN8I_R40)
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
		if (pins == SUNXI_GPIO_H) {
			/* SDC1: PH22-PH-27 */
			for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN4I_GPH_SDC1);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		} else {
			/* SDC1: PG0-PG5 */
			for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN4I_GPG_SDC1);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		}
#elif defined(CONFIG_MACH_SUN5I)
		/* SDC1: PG3-PG8 */
418
		for (pin = SUNXI_GPG(3); pin <= SUNXI_GPG(8); pin++) {
419
			sunxi_gpio_set_cfgpin(pin, SUN5I_GPG_SDC1);
Ian Campbell's avatar
Ian Campbell committed
420 421 422
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
#elif defined(CONFIG_MACH_SUN6I)
		/* SDC1: PG0-PG5 */
		for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
			sunxi_gpio_set_cfgpin(pin, SUN6I_GPG_SDC1);
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}
#elif defined(CONFIG_MACH_SUN8I)
		if (pins == SUNXI_GPIO_D) {
			/* SDC1: PD2-PD7 */
			for (pin = SUNXI_GPD(2); pin <= SUNXI_GPD(7); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN8I_GPD_SDC1);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		} else {
			/* SDC1: PG0-PG5 */
			for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		}
#endif
Ian Campbell's avatar
Ian Campbell committed
447 448 449
		break;

	case 2:
450 451 452 453
		pins = sunxi_name_to_gpio_bank(CONFIG_MMC2_PINS);

#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
		/* SDC2: PC6-PC11 */
Ian Campbell's avatar
Ian Campbell committed
454
		for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); pin++) {
455
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
Ian Campbell's avatar
Ian Campbell committed
456 457 458
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
#elif defined(CONFIG_MACH_SUN5I)
		if (pins == SUNXI_GPIO_E) {
			/* SDC2: PE4-PE9 */
			for (pin = SUNXI_GPE(4); pin <= SUNXI_GPD(9); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN5I_GPE_SDC2);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		} else {
			/* SDC2: PC6-PC15 */
			for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		}
#elif defined(CONFIG_MACH_SUN6I)
		if (pins == SUNXI_GPIO_A) {
			/* SDC2: PA9-PA14 */
			for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC2);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		} else {
			/* SDC2: PC6-PC15, PC24 */
			for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}

			sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
			sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
		}
495 496 497 498 499 500 501 502 503 504 505
#elif defined(CONFIG_MACH_SUN8I_R40)
		/* SDC2: PC6-PC15, PC24 */
		for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}

		sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
		sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
		sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
506
#elif defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I)
507 508 509 510 511 512 513 514 515 516 517
		/* SDC2: PC5-PC6, PC8-PC16 */
		for (pin = SUNXI_GPC(5); pin <= SUNXI_GPC(6); pin++) {
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}

		for (pin = SUNXI_GPC(8); pin <= SUNXI_GPC(16); pin++) {
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
Icenowy Zheng's avatar
Icenowy Zheng committed
518 519 520 521 522 523 524
		}
#elif defined(CONFIG_MACH_SUN50I_H6)
		/* SDC2: PC4-PC14 */
		for (pin = SUNXI_GPC(4); pin <= SUNXI_GPC(14); pin++) {
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
525
		}
526 527 528 529 530 531 532
#elif defined(CONFIG_MACH_SUN9I)
		/* SDC2: PC6-PC16 */
		for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(16); pin++) {
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}
533
#endif
Ian Campbell's avatar
Ian Campbell committed
534 535 536
		break;

	case 3:
537 538
		pins = sunxi_name_to_gpio_bank(CONFIG_MMC3_PINS);

539 540
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
    defined(CONFIG_MACH_SUN8I_R40)
541
		/* SDC3: PI4-PI9 */
Ian Campbell's avatar
Ian Campbell committed
542
		for (pin = SUNXI_GPI(4); pin <= SUNXI_GPI(9); pin++) {
543
			sunxi_gpio_set_cfgpin(pin, SUNXI_GPI_SDC3);
Ian Campbell's avatar
Ian Campbell committed
544 545 546
			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(pin, 2);
		}
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
#elif defined(CONFIG_MACH_SUN6I)
		if (pins == SUNXI_GPIO_A) {
			/* SDC3: PA9-PA14 */
			for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC3);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}
		} else {
			/* SDC3: PC6-PC15, PC24 */
			for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
				sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3);
				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
				sunxi_gpio_set_drv(pin, 2);
			}

			sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3);
			sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
			sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
		}
#endif
Ian Campbell's avatar
Ian Campbell committed
568 569 570 571 572 573 574 575
		break;

	default:
		printf("sunxi: invalid MMC slot %d for pinmux setup\n", sdc);
		break;
	}
}

576
int board_mmc_init(struct bd_info *bis)
Ian Campbell's avatar
Ian Campbell committed
577
{
578 579
	__maybe_unused struct mmc *mmc0, *mmc1;

Ian Campbell's avatar
Ian Campbell committed
580
	mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
581 582 583 584
	mmc0 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
	if (!mmc0)
		return -1;

585
#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
Ian Campbell's avatar
Ian Campbell committed
586
	mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
587 588 589 590 591
	mmc1 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
	if (!mmc1)
		return -1;
#endif

Ian Campbell's avatar
Ian Campbell committed
592 593 594 595
	return 0;
}
#endif

596
#ifdef CONFIG_SPL_BUILD
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611

static void sunxi_spl_store_dram_size(phys_addr_t dram_size)
{
	struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);

	if (spl == INVALID_SPL_HEADER)
		return;

	/* Promote the header version for U-Boot proper, if needed. */
	if (spl->spl_signature[3] < SPL_DRAM_HEADER_VERSION)
		spl->spl_signature[3] = SPL_DRAM_HEADER_VERSION;

	spl->dram_size = dram_size >> 20;
}

612 613
void sunxi_board_init(void)
{
614
	int power_failed = 0;
615

616 617 618 619
#ifdef CONFIG_SY8106A_POWER
	power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT);
#endif

620
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
621 622
	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
	defined CONFIG_AXP818_POWER
623 624
	power_failed = axp_init();

625 626
#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
	defined CONFIG_AXP818_POWER
627
	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
Hans de Goede's avatar
Hans de Goede committed
628
#endif
629 630
	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
631
#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
632
	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
633
#endif
634 635
#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
	defined CONFIG_AXP818_POWER
636
	power_failed |= axp_set_dcdc5(CONFIG_AXP_DCDC5_VOLT);
637 638
#endif

639 640
#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
	defined CONFIG_AXP818_POWER
641 642 643
	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
#endif
	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
644
#if !defined(CONFIG_AXP152_POWER)
645 646 647 648 649 650
	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
#endif
#ifdef CONFIG_AXP209_POWER
	power_failed |= axp_set_aldo4(CONFIG_AXP_ALDO4_VOLT);
#endif

651 652
#if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP809_POWER) || \
	defined(CONFIG_AXP818_POWER)
653 654
	power_failed |= axp_set_dldo(1, CONFIG_AXP_DLDO1_VOLT);
	power_failed |= axp_set_dldo(2, CONFIG_AXP_DLDO2_VOLT);
655
#if !defined CONFIG_AXP809_POWER
656 657
	power_failed |= axp_set_dldo(3, CONFIG_AXP_DLDO3_VOLT);
	power_failed |= axp_set_dldo(4, CONFIG_AXP_DLDO4_VOLT);
658
#endif
659 660 661 662
	power_failed |= axp_set_eldo(1, CONFIG_AXP_ELDO1_VOLT);
	power_failed |= axp_set_eldo(2, CONFIG_AXP_ELDO2_VOLT);
	power_failed |= axp_set_eldo(3, CONFIG_AXP_ELDO3_VOLT);
#endif
663 664 665 666 667

#ifdef CONFIG_AXP818_POWER
	power_failed |= axp_set_fldo(1, CONFIG_AXP_FLDO1_VOLT);
	power_failed |= axp_set_fldo(2, CONFIG_AXP_FLDO2_VOLT);
	power_failed |= axp_set_fldo(3, CONFIG_AXP_FLDO3_VOLT);
668 669 670
#endif

#if defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
671
	power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
672
#endif
673
#endif
674 675 676 677 678 679 680
	printf("DRAM:");
	gd->ram_size = sunxi_dram_init();
	printf(" %d MiB\n", (int)(gd->ram_size >> 20));
	if (!gd->ram_size)
		hang();

	sunxi_spl_store_dram_size(gd->ram_size);
681

682 683 684 685 686
	/*
	 * Only clock up the CPU to full speed if we are reasonably
	 * assured it's being powered with suitable core voltage
	 */
	if (!power_failed)
687
		clock_set_pll1(CONFIG_SYS_CLK_FREQ);
688
	else
689
		printf("Failed to set core voltage! Can't set CPU frequency\n");
690 691
}
#endif
692

693 694 695
#ifdef CONFIG_USB_GADGET
int g_dnl_board_usb_cable_connected(void)
{
696 697 698 699
	struct udevice *dev;
	struct phy phy;
	int ret;

700
	ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
	if (ret) {
		pr_err("%s: Cannot find USB device\n", __func__);
		return ret;
	}

	ret = generic_phy_get_by_name(dev, "usb", &phy);
	if (ret) {
		pr_err("failed to get %s USB PHY\n", dev->name);
		return ret;
	}

	ret = generic_phy_init(&phy);
	if (ret) {
		pr_err("failed to init %s USB PHY\n", dev->name);
		return ret;
	}

	ret = sun4i_usb_phy_vbus_detect(&phy);
	if (ret == 1) {
		pr_err("A charger is plugged into the OTG\n");
		return -ENODEV;
	}

	return ret;
725 726 727
}
#endif

728 729 730 731 732 733
#ifdef CONFIG_SERIAL_TAG
void get_board_serial(struct tag_serialnr *serialnr)
{
	char *serial_string;
	unsigned long long serial;

734
	serial_string = env_get("serial#");
735 736 737 738 739 740 741 742 743 744 745 746 747

	if (serial_string) {
		serial = simple_strtoull(serial_string, NULL, 16);

		serialnr->high = (unsigned int) (serial >> 32);
		serialnr->low = (unsigned int) (serial & 0xffffffff);
	} else {
		serialnr->high = 0;
		serialnr->low = 0;
	}
}
#endif

748 749 750 751 752 753 754
/*
 * Check the SPL header for the "sunxi" variant. If found: parse values
 * that might have been passed by the loader ("fel" utility), and update
 * the environment accordingly.
 */
static void parse_spl_header(const uint32_t spl_addr)
{
755
	struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
756

757
	if (spl == INVALID_SPL_HEADER)
758
		return;
759

760 761 762 763 764 765 766 767
	if (!spl->fel_script_address)
		return;

	if (spl->fel_uEnv_length != 0) {
		/*
		 * data is expected in uEnv.txt compatible format, so "env
		 * import -t" the string(s) at fel_script_address right away.
		 */
768
		himport_r(&env_htab, (char *)(uintptr_t)spl->fel_script_address,
769 770
			  spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
		return;
771
	}
772
	/* otherwise assume .scr format (mkimage-type script) */
773
	env_set_hex("fel_scriptaddr", spl->fel_script_address);
774 775
}

776 777 778 779 780
/*
 * Note this function gets called multiple times.
 * It must not make any changes to env variables which already exist.
 */
static void setup_environment(const void *fdt)
781
{
782
	char serial_string[17] = { 0 };
783
	unsigned int sid[4];
784
	uint8_t mac_addr[6];
785 786
	char ethaddr[16];
	int i, ret;
787

788
	ret = sunxi_get_sid(sid);
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
	if (ret == 0 && sid[0] != 0) {
		/*
		 * The single words 1 - 3 of the SID have quite a few bits
		 * which are the same on many models, so we take a crc32
		 * of all 3 words, to get a more unique value.
		 *
		 * Note we only do this on newer SoCs as we cannot change
		 * the algorithm on older SoCs since those have been using
		 * fixed mac-addresses based on only using word 3 for a
		 * long time and changing a fixed mac-address with an
		 * u-boot update is not good.
		 */
#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
		sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
#endif

807 808 809 810
		/* Ensure the NIC specific bytes of the mac are not all 0 */
		if ((sid[3] & 0xffffff) == 0)
			sid[3] |= 0x800000;

811 812 813 814 815 816 817 818 819 820
		for (i = 0; i < 4; i++) {
			sprintf(ethaddr, "ethernet%d", i);
			if (!fdt_get_alias(fdt, ethaddr))
				continue;

			if (i == 0)
				strcpy(ethaddr, "ethaddr");
			else
				sprintf(ethaddr, "eth%daddr", i);

821
			if (env_get(ethaddr))
822 823
				continue;

824
			/* Non OUI / registered MAC address */
825
			mac_addr[0] = (i << 4) | 0x02;
826 827 828 829 830 831
			mac_addr[1] = (sid[0] >>  0) & 0xff;
			mac_addr[2] = (sid[3] >> 24) & 0xff;
			mac_addr[3] = (sid[3] >> 16) & 0xff;
			mac_addr[4] = (sid[3] >>  8) & 0xff;
			mac_addr[5] = (sid[3] >>  0) & 0xff;

832
			eth_env_set_enetaddr(ethaddr, mac_addr);
833
		}
834

835
		if (!env_get("serial#")) {
836 837
			snprintf(serial_string, sizeof(serial_string),
				"%08x%08x", sid[0], sid[3]);
838

839
			env_set("serial#", serial_string);
840
		}
841
	}
842 843 844 845
}

int misc_init_r(void)
{
846
	uint boot;
847

848 849
	env_set("fel_booted", NULL);
	env_set("fel_scriptaddr", NULL);
850
	env_set("mmc_bootdev", NULL);
851 852

	boot = sunxi_get_boot_device();
853
	/* determine if we are running in FEL mode */
854
	if (boot == BOOT_DEVICE_BOARD) {
855
		env_set("fel_booted", "1");
856
		parse_spl_header(SPL_ADDR);
857 858 859 860 861
	/* or if we booted from MMC, and which one */
	} else if (boot == BOOT_DEVICE_MMC1) {
		env_set("mmc_bootdev", "0");
	} else if (boot == BOOT_DEVICE_MMC2) {
		env_set("mmc_bootdev", "1");
862 863 864
	}

	setup_environment(gd->fdt_blob);
865

866
#ifdef CONFIG_USB_ETHER
Maxime Ripard's avatar
Maxime Ripard committed
867
	usb_ether_init();
868
#endif
Maxime Ripard's avatar
Maxime Ripard committed
869

870 871
	return 0;
}
872

873
int ft_board_setup(void *blob, struct bd_info *bd)
874
{
875 876
	int __maybe_unused r;

877 878 879 880 881 882
	/*
	 * Call setup_environment again in case the boot fdt has
	 * ethernet aliases the u-boot copy does not have.
	 */
	setup_environment(blob);

883
#ifdef CONFIG_VIDEO_DT_SIMPLEFB
884 885 886
	r = sunxi_simplefb_setup(blob);
	if (r)
		return r;
887
#endif
888
	return 0;
889
}
890 891 892 893

#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{
894 895
	struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);
	const char *cmp_str = (const char *)spl;
896

897
	/* Check if there is a DT name stored in the SPL header and use that. */
898
	if (spl != INVALID_SPL_HEADER && spl->dt_name_offset) {
899 900
		cmp_str += spl->dt_name_offset;
	} else {
901
#ifdef CONFIG_DEFAULT_DEVICE_TREE
902
		cmp_str = CONFIG_DEFAULT_DEVICE_TREE;
903
#else
904
		return 0;
905
#endif
906
	};
907

908
#ifdef CONFIG_PINE64_DT_SELECTION
909 910 911 912 913 914 915 916 917
/* Differentiate the two Pine64 board DTs by their DRAM size. */
	if (strstr(name, "-pine64") && strstr(cmp_str, "-pine64")) {
		if ((gd->ram_size > 512 * 1024 * 1024))
			return !strstr(name, "plus");
		else
			return !!strstr(name, "plus");
	} else {
		return strcmp(name, cmp_str);
	}
918 919
#endif
	return strcmp(name, cmp_str);
920 921
}
#endif