From 2ac07f75d1977008e829d00bcce16143e171765d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 26 Feb 2016 00:46:07 -0600 Subject: arm: Add support for LEGO MINDSTORMS EV3 This is based on the davinci da850evm. It can boot from either the on-board 16MB flash or from a microSD card. It also reads board information from an I2C EEPROM. The EV3 itself initally boots from write-protected EEPROM, so no u-boot SPL is needed. Signed-off-by: David Lechner Reviewed-by: Tom Rini --- board/lego/ev3/Kconfig | 12 ++++ board/lego/ev3/MAINTAINERS | 6 ++ board/lego/ev3/Makefile | 10 +++ board/lego/ev3/README | 32 +++++++++ board/lego/ev3/legoev3.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 236 insertions(+) create mode 100644 board/lego/ev3/Kconfig create mode 100644 board/lego/ev3/MAINTAINERS create mode 100644 board/lego/ev3/Makefile create mode 100644 board/lego/ev3/README create mode 100644 board/lego/ev3/legoev3.c (limited to 'board/lego/ev3') diff --git a/board/lego/ev3/Kconfig b/board/lego/ev3/Kconfig new file mode 100644 index 0000000..14b3f0c --- /dev/null +++ b/board/lego/ev3/Kconfig @@ -0,0 +1,12 @@ +if TARGET_LEGOEV3 + +config SYS_BOARD + default "ev3" + +config SYS_VENDOR + default "lego" + +config SYS_CONFIG_NAME + default "legoev3" + +endif diff --git a/board/lego/ev3/MAINTAINERS b/board/lego/ev3/MAINTAINERS new file mode 100644 index 0000000..11b3261 --- /dev/null +++ b/board/lego/ev3/MAINTAINERS @@ -0,0 +1,6 @@ +LEGOEV3 BOARD +M: David Lechner +S: Maintained +F: board/lego/ev3/ +F: include/configs/legoev3.h +F: configs/legoev3_defconfig diff --git a/board/lego/ev3/Makefile b/board/lego/ev3/Makefile new file mode 100644 index 0000000..f3e717a --- /dev/null +++ b/board/lego/ev3/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += legoev3.o diff --git a/board/lego/ev3/README b/board/lego/ev3/README new file mode 100644 index 0000000..1a50ca9 --- /dev/null +++ b/board/lego/ev3/README @@ -0,0 +1,32 @@ +Summary +======= + +LEGO MINDSTORMS EV3 is a toy robot produced by the LEGO Group. It is based +on the davinci da850 evm. The EV3 has a 16MB spi flash and a SDHC microSD card +reader. + +Booting +======= + +The EV3 contains a bootloader in EEPROM that loads u-boot.bin from address 0x0 +of the spi flash memory. Using the default configuration, u-boot will check to +see if there is a boot.scr file on the first FAT partition of the mmc. If there +is, it will run the script and boot the kernel from the uImage file also in +the FAT partition. Otherwise, it will load a kernel and rootfs from the flash. +The kernel must be stored at address 0x50000 on the flash and have a maximum +size of 3MiB. The rootfs must be a squasfs image and stored at 0x350000 in the +flash and have a maximum size of 9.3MiB. The flash starting at 0xCB0000 is +reserved for user data. + +Writing image to flash +====================== + +The EEPROM contains a program for uploading an image file to the flash memory. +The program is started by holding down the right button on the EV3 when powering +it on. You can also `run fwupdateboot` in the u-boot shell to reboot into this +mode. The image can then be uploaded using the official LEGO MINDSTORMS EV3 +software or a 3rd party program capable of uploading a firmware file. + +If you are booting from the microSD card, it is enough to just write uboot.bin +to the flash. If you are not using a microSD card, you will need to create an +image file using the layout described above. diff --git a/board/lego/ev3/legoev3.c b/board/lego/ev3/legoev3.c new file mode 100644 index 0000000..a791b97 --- /dev/null +++ b/board/lego/ev3/legoev3.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016 David Lechner + * + * Based on da850evm.c + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * Based on da830evm.c. Original Copyrights follow: + * + * Copyright (C) 2009 Nick Thompson, GE Fanuc, Ltd. + * Copyright (C) 2007 Sergey Kubushyn + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_DAVINCI_MMC +#include +#include +#endif + +DECLARE_GLOBAL_DATA_PTR; + +u8 board_rev; + +#define EEPROM_I2C_ADDR 0x50 +#define EEPROM_REV_OFFSET 0x3F00 +#define EEPROM_MAC_OFFSET 0x3F06 + +#ifdef CONFIG_DAVINCI_MMC +static struct davinci_mmc mmc_sd0 = { + .reg_base = (struct davinci_mmc_regs *)DAVINCI_MMC_SD0_BASE, + .host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */ + .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + .version = MMC_CTLR_VERSION_2, +}; + +int board_mmc_init(bd_t *bis) +{ + mmc_sd0.input_clk = clk_get(DAVINCI_MMCSD_CLKID); + + /* Add slot-0 to mmc subsystem */ + return davinci_mmc_init(bis, &mmc_sd0); +} +#endif + +const struct pinmux_resource pinmuxes[] = { + PINMUX_ITEM(spi0_pins_base), + PINMUX_ITEM(spi0_pins_scs0), + PINMUX_ITEM(uart1_pins_txrx), + PINMUX_ITEM(i2c0_pins), + PINMUX_ITEM(mmc0_pins), +}; + +const int pinmuxes_size = ARRAY_SIZE(pinmuxes); + +const struct lpsc_resource lpsc[] = { + { DAVINCI_LPSC_SPI0 }, /* Serial Flash */ + { DAVINCI_LPSC_UART1 }, /* console */ + { DAVINCI_LPSC_MMC_SD }, +}; + +const int lpsc_size = ARRAY_SIZE(lpsc); + +u32 get_board_rev(void) +{ + u8 buf[2]; + + if (!board_rev) { + if (i2c_read(EEPROM_I2C_ADDR, EEPROM_REV_OFFSET, 2, buf, 2)) { + printf("\nBoard revision read failed!\n"); + } else { + /* + * Board rev 3 has MAC address at EEPROM_REV_OFFSET. + * Other revisions have checksum at EEPROM_REV_OFFSET+1 + * to detect this. + */ + if ((buf[0] ^ buf[1]) == 0xFF) + board_rev = buf[0]; + else + board_rev = 3; + } + } + + return board_rev; +} + +/* + * The Bluetooth MAC address serves as the board serial number. + */ +void get_board_serial(struct tag_serialnr *serialnr) +{ + u32 offset; + u8 buf[6]; + + if (!board_rev) + board_rev = get_board_rev(); + + /* Board rev 3 has MAC address where rev should be */ + offset = (board_rev == 3) ? EEPROM_REV_OFFSET : EEPROM_MAC_OFFSET; + + if (i2c_read(EEPROM_I2C_ADDR, offset, 2, buf, 6)) { + printf("\nBoard serial read failed!\n"); + } else { + u8 *nr; + + nr = (u8 *)&serialnr->low; + nr[0] = buf[5]; + nr[1] = buf[4]; + nr[2] = buf[3]; + nr[3] = buf[2]; + nr = (u8 *)&serialnr->high; + nr[0] = buf[1]; + nr[1] = buf[0]; + nr[2] = 0; + nr[3] = 0; + } +} + +int board_early_init_f(void) +{ + /* + * Power on required peripherals + * ARM does not have access by default to PSC0 and PSC1 + * assuming here that the DSP bootloader has set the IOPU + * such that PSC access is available to ARM + */ + if (da8xx_configure_lpsc_items(lpsc, ARRAY_SIZE(lpsc))) + return 1; + + return 0; +} + +int board_init(void) +{ +#ifndef CONFIG_USE_IRQ + irq_init(); +#endif + + /* arch number of the board */ + /* LEGO didn't register for a unique number and uses da850evm */ + gd->bd->bi_arch_number = MACH_TYPE_DAVINCI_DA850_EVM; + + /* address of boot parameters */ + gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; + + /* setup the SUSPSRC for ARM to control emulation suspend */ + writel(readl(&davinci_syscfg_regs->suspsrc) & + ~(DAVINCI_SYSCFG_SUSPSRC_EMAC | DAVINCI_SYSCFG_SUSPSRC_I2C | + DAVINCI_SYSCFG_SUSPSRC_SPI0 | DAVINCI_SYSCFG_SUSPSRC_TIMER0 | + DAVINCI_SYSCFG_SUSPSRC_UART1), + &davinci_syscfg_regs->suspsrc); + + /* configure pinmux settings */ + if (davinci_configure_pin_mux_items(pinmuxes, ARRAY_SIZE(pinmuxes))) + return 1; + + /* enable the console UART */ + writel((DAVINCI_UART_PWREMU_MGMT_FREE | DAVINCI_UART_PWREMU_MGMT_URRST | + DAVINCI_UART_PWREMU_MGMT_UTRST), + &davinci_uart1_ctrl_regs->pwremu_mgmt); + + return 0; +} -- cgit v1.1