u-boot-brain/board/sunxi/board.c
Hans de Goede 2fcf033d36 sunxi: axp: Move axp gpio code to a separate axpi-gpio driver
Move the axp-gpio code out of the drivers/power/axp*.c code, and into
a new separate axpi-gpio driver.

This change drops supports for the gpio3 pin on the axp209, as that requires
special handling, and no boards are using it.

Besides cleaning things up by moving the code to a separate driver, as
a bonus this change also adds support for the (non vusb) gpio pins on the
axp221 and the gpio pins on the axp152.

The new axp-gpio driver gets its own Kconfig option, and is only enabled
on boards which need it. Besides that it only gets enabled in the regular
u-boot build and not for the SPL as we never need it in the SPL.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Ian Campbell <ijc@hellion.org.uk>
2015-05-04 16:51:53 +02:00

526 lines
14 KiB
C

/*
* (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.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <mmc.h>
#ifdef CONFIG_AXP152_POWER
#include <axp152.h>
#endif
#ifdef CONFIG_AXP209_POWER
#include <axp209.h>
#endif
#ifdef CONFIG_AXP221_POWER
#include <axp221.h>
#endif
#include <asm/arch/clock.h>
#include <asm/arch/cpu.h>
#include <asm/arch/display.h>
#include <asm/arch/dram.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mmc.h>
#include <asm/arch/usbc.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <linux/usb/musb.h>
#include <net.h>
#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;
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; }
#endif
DECLARE_GLOBAL_DATA_PTR;
/* add board specific code here */
int board_init(void)
{
int id_pfr1, ret;
gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
debug("id_pfr1: 0x%08x\n", id_pfr1);
/* Generic Timer Extension available? */
if ((id_pfr1 >> 16) & 0xf) {
debug("Setting CNTFRQ\n");
/* CNTFRQ == 24 MHz */
asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r"(24000000));
}
ret = axp_gpio_init();
if (ret)
return ret;
/* Uses dm gpio code so do this here and not in i2c_init_board() */
return soft_i2c_board_init();
}
int dram_init(void)
{
gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
return 0;
}
#ifdef CONFIG_GENERIC_MMC
static void mmc_pinmux_setup(int sdc)
{
unsigned int pin;
__maybe_unused int pins;
switch (sdc) {
case 0:
/* SDC0: PF0-PF5 */
for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
sunxi_gpio_set_cfgpin(pin, SUNXI_GPF_SDC0);
sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
sunxi_gpio_set_drv(pin, 2);
}
break;
case 1:
pins = sunxi_name_to_gpio_bank(CONFIG_MMC1_PINS);
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
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 */
for (pin = SUNXI_GPG(3); pin <= SUNXI_GPG(8); pin++) {
sunxi_gpio_set_cfgpin(pin, SUN5I_GPG_SDC1);
sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
sunxi_gpio_set_drv(pin, 2);
}
#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
break;
case 2:
pins = sunxi_name_to_gpio_bank(CONFIG_MMC2_PINS);
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
/* SDC2: PC6-PC11 */
for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); 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_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);
}
#elif defined(CONFIG_MACH_SUN8I)
/* 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);
}
#endif
break;
case 3:
pins = sunxi_name_to_gpio_bank(CONFIG_MMC3_PINS);
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
/* SDC3: PI4-PI9 */
for (pin = SUNXI_GPI(4); pin <= SUNXI_GPI(9); pin++) {
sunxi_gpio_set_cfgpin(pin, SUNXI_GPI_SDC3);
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) {
/* 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
break;
default:
printf("sunxi: invalid MMC slot %d for pinmux setup\n", sdc);
break;
}
}
int board_mmc_init(bd_t *bis)
{
__maybe_unused struct mmc *mmc0, *mmc1;
__maybe_unused char buf[512];
mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
mmc0 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
if (!mmc0)
return -1;
#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
mmc1 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
if (!mmc1)
return -1;
#endif
#if CONFIG_MMC_SUNXI_SLOT == 0 && CONFIG_MMC_SUNXI_SLOT_EXTRA == 2
/*
* Both mmc0 and mmc2 are bootable, figure out where we're booting
* from. Try mmc0 first, just like the brom does.
*/
if (mmc_getcd(mmc0) && mmc_init(mmc0) == 0 &&
mmc0->block_dev.block_read(0, 16, 1, buf) == 1) {
buf[12] = 0;
if (strcmp(&buf[4], "eGON.BT0") == 0)
return 0;
}
/* no bootable card in mmc0, so we must be booting from mmc2, swap */
mmc0->block_dev.dev = 1;
mmc1->block_dev.dev = 0;
#endif
return 0;
}
#endif
void i2c_init_board(void)
{
#ifdef CONFIG_I2C0_ENABLE
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
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);
#endif
#endif
#ifdef CONFIG_I2C1_ENABLE
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
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);
#endif
#endif
#ifdef CONFIG_I2C2_ENABLE
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
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);
#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)
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)
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_SPL_BUILD
void sunxi_board_init(void)
{
int power_failed = 0;
unsigned long ramsize;
#ifdef CONFIG_AXP152_POWER
power_failed = axp152_init();
power_failed |= axp152_set_dcdc2(1400);
power_failed |= axp152_set_dcdc3(1500);
power_failed |= axp152_set_dcdc4(1250);
power_failed |= axp152_set_ldo2(3000);
#endif
#ifdef CONFIG_AXP209_POWER
power_failed |= axp209_init();
power_failed |= axp209_set_dcdc2(1400);
power_failed |= axp209_set_dcdc3(1250);
power_failed |= axp209_set_ldo2(3000);
power_failed |= axp209_set_ldo3(2800);
power_failed |= axp209_set_ldo4(2800);
#endif
#ifdef CONFIG_AXP221_POWER
power_failed = axp221_init();
power_failed |= axp221_set_dcdc1(CONFIG_AXP221_DCDC1_VOLT);
power_failed |= axp221_set_dcdc2(1200); /* A31:VDD-GPU, A23:VDD-SYS */
power_failed |= axp221_set_dcdc3(1200); /* VDD-CPU */
#ifdef CONFIG_MACH_SUN6I
power_failed |= axp221_set_dcdc4(1200); /* A31:VDD-SYS */
#else
power_failed |= axp221_set_dcdc4(0); /* A23:unused */
#endif
power_failed |= axp221_set_dcdc5(1500); /* VCC-DRAM */
power_failed |= axp221_set_dldo1(CONFIG_AXP221_DLDO1_VOLT);
power_failed |= axp221_set_dldo4(CONFIG_AXP221_DLDO4_VOLT);
power_failed |= axp221_set_aldo1(CONFIG_AXP221_ALDO1_VOLT);
power_failed |= axp221_set_aldo2(CONFIG_AXP221_ALDO2_VOLT);
power_failed |= axp221_set_aldo3(CONFIG_AXP221_ALDO3_VOLT);
power_failed |= axp221_set_eldo(3, CONFIG_AXP221_ELDO3_VOLT);
#endif
printf("DRAM:");
ramsize = sunxi_dram_init();
printf(" %lu MiB\n", ramsize >> 20);
if (!ramsize)
hang();
/*
* Only clock up the CPU to full speed if we are reasonably
* assured it's being powered with suitable core voltage
*/
if (!power_failed)
clock_set_pll1(CONFIG_SYS_CLK_FREQ);
else
printf("Failed to set core voltage! Can't set CPU frequency\n");
}
#endif
#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET)
static struct musb_hdrc_config musb_config = {
.multipoint = 1,
.dyn_fifo = 1,
.num_eps = 6,
.ram_bits = 11,
};
static struct musb_hdrc_platform_data musb_plat = {
#if defined(CONFIG_MUSB_HOST)
.mode = MUSB_HOST,
#else
.mode = MUSB_PERIPHERAL,
#endif
.config = &musb_config,
.power = 250,
.platform_ops = &sunxi_musb_ops,
};
#endif
#ifdef CONFIG_USB_GADGET
int g_dnl_board_usb_cable_connected(void)
{
return sunxi_usbc_vbus_detect(0);
}
#endif
#ifdef CONFIG_MISC_INIT_R
int misc_init_r(void)
{
char serial_string[17] = { 0 };
unsigned int sid[4];
uint8_t mac_addr[6];
int ret;
ret = sunxi_get_sid(sid);
if (ret == 0 && sid[0] != 0 && sid[3] != 0) {
if (!getenv("ethaddr")) {
/* Non OUI / registered MAC address */
mac_addr[0] = 0x02;
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;
eth_setenv_enetaddr("ethaddr", mac_addr);
}
if (!getenv("serial#")) {
snprintf(serial_string, sizeof(serial_string),
"%08x%08x", sid[0], sid[3]);
setenv("serial#", serial_string);
}
}
#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET)
musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE);
#endif
return 0;
}
#endif
#ifdef CONFIG_OF_BOARD_SETUP
int ft_board_setup(void *blob, bd_t *bd)
{
#ifdef CONFIG_VIDEO_DT_SIMPLEFB
return sunxi_simplefb_setup(blob);
#endif
}
#endif /* CONFIG_OF_BOARD_SETUP */