From 45d2ff317c0c077e6f83602a81bc915aa195d3f7 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Mon, 12 Aug 2013 18:04:06 -0700 Subject: exynos5420: Implement support to boot with USB A-A firmware upload This patch ports the USB A-A firmware upload functionality from exynos5250 over to exynos5420. Essentially just like a conflictless cherry-pick of 9e69421f5f0eebf88c09913dee90082feab2856c. It also fixes the exact same bug with SPI initialization for Pit and Kirby. Old-Change-Id: Ief0ed54c0beb2701e51201041f9bc426b2167747 Signed-off-by: Julius Werner Reviewed-on: https://gerrit.chromium.org/gerrit/65751 Reviewed-by: David Hendricks (cherry picked from commit 5dff43f929478f83939221df13b961a69f89b132) exynos5: Fix trivial style nits A few curly braces on the wrong line. Old-Change-Id: I4ddac4476c6509dc1716e8c1915fbdb67d346786 Signed-off-by: Julius Werner Reviewed-on: https://gerrit.chromium.org/gerrit/66153 Reviewed-by: Ronald G. Minnich (cherry picked from commit 41e3fd9eaafe36433723f4e96a6d94c04e5fbafb) Squashed two related commits. Change-Id: I22d579693b5e7270aacb45bbe3557e40893dd1f8 Signed-off-by: Isaac Christensen Reviewed-on: http://review.coreboot.org/6500 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan --- src/cpu/samsung/exynos5250/alternate_cbfs.c | 15 ++-- src/cpu/samsung/exynos5420/Makefile.inc | 6 +- src/cpu/samsung/exynos5420/alternate_cbfs.c | 115 ++++++++++++++++++++++++++++ src/cpu/samsung/exynos5420/alternate_cbfs.h | 44 +++++++++++ src/cpu/samsung/exynos5420/cpu.h | 16 ---- src/cpu/samsung/exynos5420/pinmux.c | 5 +- src/cpu/samsung/exynos5420/spi.c | 7 -- 7 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 src/cpu/samsung/exynos5420/alternate_cbfs.c create mode 100644 src/cpu/samsung/exynos5420/alternate_cbfs.h (limited to 'src/cpu/samsung') diff --git a/src/cpu/samsung/exynos5250/alternate_cbfs.c b/src/cpu/samsung/exynos5250/alternate_cbfs.c index 15494863f2..49c9d4c194 100644 --- a/src/cpu/samsung/exynos5250/alternate_cbfs.c +++ b/src/cpu/samsung/exynos5250/alternate_cbfs.c @@ -43,7 +43,8 @@ * rest of the firmware's lifetime and all subsequent stages (which will not * have __PRE_RAM__ defined) can just directly reference it there. */ -static int usb_cbfs_open(struct cbfs_media *media) { +static int usb_cbfs_open(struct cbfs_media *media) +{ #ifdef __PRE_RAM__ static int first_run = 1; int (*irom_load_usb)(void) = *irom_load_image_from_usb_ptr; @@ -72,14 +73,16 @@ static int usb_cbfs_open(struct cbfs_media *media) { static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) { + size_t offset, size_t count) +{ ASSERT(offset + count < alternate_cbfs_size); memcpy(dest, alternate_cbfs_buffer + offset, count); return count; } static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) { + size_t count) +{ ASSERT(offset + count < alternate_cbfs_size); return alternate_cbfs_buffer + offset; } @@ -87,7 +90,8 @@ static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, static void *alternate_cbfs_unmap(struct cbfs_media *media, const void *buffer) { return 0; } -static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) { +static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +{ printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); media->open = usb_cbfs_open; @@ -99,7 +103,8 @@ static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) { return 0; } -int init_default_cbfs_media(struct cbfs_media *media) { +int init_default_cbfs_media(struct cbfs_media *media) +{ if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) return initialize_exynos_usb_cbfs_media(media); diff --git a/src/cpu/samsung/exynos5420/Makefile.inc b/src/cpu/samsung/exynos5420/Makefile.inc index 319162707b..bb6d8fed3a 100644 --- a/src/cpu/samsung/exynos5420/Makefile.inc +++ b/src/cpu/samsung/exynos5420/Makefile.inc @@ -3,7 +3,7 @@ # image outside of CBFS INTERMEDIATE += exynos5420_add_bl1 -bootblock-y += spi.c +bootblock-y += spi.c alternate_cbfs.c bootblock-y += pinmux.c mct.c power.c # Clock is required for UART bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += clock_init.c @@ -16,7 +16,7 @@ bootblock-y += wakeup.c bootblock-y += gpio.c bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += timer.c -romstage-y += spi.c +romstage-y += spi.c alternate_cbfs.c romstage-y += smp.c romstage-y += clock.c romstage-y += clock_init.c @@ -36,7 +36,7 @@ romstage-y += i2c.c #romstage-y += wdt.c romstage-y += cbmem.c -ramstage-y += spi.c +ramstage-y += spi.c alternate_cbfs.c ramstage-y += clock.c ramstage-y += clock_init.c ramstage-y += pinmux.c diff --git a/src/cpu/samsung/exynos5420/alternate_cbfs.c b/src/cpu/samsung/exynos5420/alternate_cbfs.c new file mode 100644 index 0000000000..49c9d4c194 --- /dev/null +++ b/src/cpu/samsung/exynos5420/alternate_cbfs.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include /* This driver serves as a CBFS media source. */ +#include +#include +#include +#include "alternate_cbfs.h" +#include "spi.h" + +/* This allows USB A-A firmware upload from a compatible host in four parts: + * The first two are the bare BL1 and the Coreboot boot block, which are just + * written to their respective loading addresses. These transfers are initiated + * by the IROM / BL1, so this code has nothing to do with them. + * + * The third transfer is a valid CBFS image that contains only the romstage, + * and must be small enough to fit into alternate_cbfs_size[__BOOT_BLOCK__] in + * IRAM. It is loaded when this function gets called in the boot block, and + * the normal CBFS code extracts the romstage from it. + * + * The fourth transfer is also a CBFS image, but can be of arbitrary size and + * should contain all available stages/payloads/etc. It is loaded when this + * function is called a second time at the end of the romstage, and copied to + * alternate_cbfs_buffer[!__BOOT_BLOCK__] in DRAM. It will reside there for the + * rest of the firmware's lifetime and all subsequent stages (which will not + * have __PRE_RAM__ defined) can just directly reference it there. + */ +static int usb_cbfs_open(struct cbfs_media *media) +{ +#ifdef __PRE_RAM__ + static int first_run = 1; + int (*irom_load_usb)(void) = *irom_load_image_from_usb_ptr; + + if (!first_run) + return 0; + + if (!irom_load_usb()) { + printk(BIOS_ERR, "Unable to load CBFS image via USB!\n"); + return -1; + } + + /* + * We need to trust the host/irom to copy the image to our + * alternate_cbfs_buffer address... there is no way to control or even + * check the transfer size or target address from our side. + */ + + printk(BIOS_DEBUG, "USB A-A transfer successful, CBFS image should now" + " be at %p\n", alternate_cbfs_buffer); + first_run = 0; +#endif + return 0; +} + +static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } + +static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) +{ + ASSERT(offset + count < alternate_cbfs_size); + memcpy(dest, alternate_cbfs_buffer + offset, count); + return count; +} + +static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) +{ + ASSERT(offset + count < alternate_cbfs_size); + return alternate_cbfs_buffer + offset; +} + +static void *alternate_cbfs_unmap(struct cbfs_media *media, + const void *buffer) { return 0; } + +static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +{ + printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); + + media->open = usb_cbfs_open; + media->close = alternate_cbfs_close; + media->read = alternate_cbfs_read; + media->map = alternate_cbfs_map; + media->unmap = alternate_cbfs_unmap; + + return 0; +} + +int init_default_cbfs_media(struct cbfs_media *media) +{ + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) + return initialize_exynos_usb_cbfs_media(media); + + /* TODO: implement SDMMC (and possibly other) boot mode */ + + return initialize_exynos_spi_cbfs_media(media, + (void*)CONFIG_CBFS_CACHE_ADDRESS, CONFIG_CBFS_CACHE_SIZE); +} diff --git a/src/cpu/samsung/exynos5420/alternate_cbfs.h b/src/cpu/samsung/exynos5420/alternate_cbfs.h new file mode 100644 index 0000000000..4e9dff9f29 --- /dev/null +++ b/src/cpu/samsung/exynos5420/alternate_cbfs.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H +#define CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H + +/* These are pointers to function pointers. Double indirection! */ +void * * const irom_sdmmc_read_blocks_ptr = (void * *)0x02020030; +void * * const irom_msh_read_from_fifo_emmc_ptr = (void * *)0x02020044; +void * * const irom_msh_end_boot_op_emmc_ptr = (void * *)0x02020048; +void * * const irom_spi_sf_read_ptr = (void * *)0x02020058; +void * * const irom_load_image_from_usb_ptr = (void * *)0x02020070; + +#define SECONDARY_BASE_BOOT_USB 0xfeed0002 +u32 * const iram_secondary_base = (u32 *)0x02020018; + +#if defined(__BOOT_BLOCK__) + /* A small space in IRAM to hold the romstage-only image */ + void * const alternate_cbfs_buffer = (void *)CONFIG_CBFS_CACHE_ADDRESS; + size_t const alternate_cbfs_size = CONFIG_CBFS_CACHE_SIZE; +#else + /* Just put this anywhere in RAM that's far enough from anything else */ + /* TODO: Find a better way to "reserve" this region? */ + void * const alternate_cbfs_buffer = (void *)0x77400000; + size_t const alternate_cbfs_size = 0xc00000; +#endif + +#endif /* CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H */ diff --git a/src/cpu/samsung/exynos5420/cpu.h b/src/cpu/samsung/exynos5420/cpu.h index 8d3d48bda4..44b3464711 100644 --- a/src/cpu/samsung/exynos5420/cpu.h +++ b/src/cpu/samsung/exynos5420/cpu.h @@ -26,22 +26,6 @@ #define EXYNOS_PRO_ID 0x10000000 -/* Address of address of function that copys data from SD or MMC */ -#define EXYNOS_COPY_MMC_FNPTR_ADDR 0x02020030 - -/* Address of address of function that copys data from SPI */ -#define EXYNOS_COPY_SPI_FNPTR_ADDR 0x02020058 - -/* Address of address of function that copys data through USB */ -#define EXYNOS_COPY_USB_FNPTR_ADDR 0x02020070 - -/* Boot mode values */ -#define EXYNOS_USB_SECONDARY_BOOT 0xfeed0002 - -#define EXYNOS_IRAM_SECONDARY_BASE 0x02020018 - -#define EXYNOS_I2C_SPACING 0x10000 - /* EXYNOS5 */ #define EXYNOS5_GPIO_PART6_BASE 0x03860000 /* Z<6:0> */ #define EXYNOS5_PRO_ID 0x10000000 diff --git a/src/cpu/samsung/exynos5420/pinmux.c b/src/cpu/samsung/exynos5420/pinmux.c index 507ee869a8..7843487a12 100644 --- a/src/cpu/samsung/exynos5420/pinmux.c +++ b/src/cpu/samsung/exynos5420/pinmux.c @@ -139,8 +139,11 @@ static void exynos_pinmux_spi(int start, int cfg) { int i; - for (i = start; i < start + 4; i++) + for (i = start; i < start + 4; i++) { gpio_cfg_pin(i, cfg); + gpio_set_pull(i, GPIO_PULL_NONE); + gpio_set_drv(i, GPIO_DRV_3X); + } } void exynos_pinmux_spi0(void) diff --git a/src/cpu/samsung/exynos5420/spi.c b/src/cpu/samsung/exynos5420/spi.c index 46b9ced4b3..7b9febcb58 100644 --- a/src/cpu/samsung/exynos5420/spi.c +++ b/src/cpu/samsung/exynos5420/spi.c @@ -408,10 +408,3 @@ int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, return 0; } - -int init_default_cbfs_media(struct cbfs_media *media) { - return initialize_exynos_spi_cbfs_media( - media, - (void*)CONFIG_CBFS_CACHE_ADDRESS, - CONFIG_CBFS_CACHE_SIZE); -} -- cgit v1.2.3