diff options
Diffstat (limited to 'src/mainboard/ti/beaglebone')
-rw-r--r-- | src/mainboard/ti/beaglebone/Kconfig | 8 | ||||
-rw-r--r-- | src/mainboard/ti/beaglebone/Makefile.inc | 5 | ||||
-rw-r--r-- | src/mainboard/ti/beaglebone/board.fmd | 10 | ||||
-rw-r--r-- | src/mainboard/ti/beaglebone/sd_media.c | 124 |
4 files changed, 145 insertions, 2 deletions
diff --git a/src/mainboard/ti/beaglebone/Kconfig b/src/mainboard/ti/beaglebone/Kconfig index 5be310cf80..ab3d38189f 100644 --- a/src/mainboard/ti/beaglebone/Kconfig +++ b/src/mainboard/ti/beaglebone/Kconfig @@ -5,8 +5,10 @@ if BOARD_TI_BEAGLEBONE config BOARD_SPECIFIC_OPTIONS def_bool y select SOC_TI_AM335X - select BOARD_ROMSIZE_KB_4096 + select BOARD_ROMSIZE_KB_32768 select MISSING_BOARD_RESET + select COMMONLIB_STORAGE + select COMMONLIB_STORAGE_SD config MAINBOARD_DIR string @@ -28,4 +30,8 @@ config UART_FOR_CONSOLE int default 0 +config FMDFILE + string + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd" + endif # BOARD_TI_BEAGLEBONE diff --git a/src/mainboard/ti/beaglebone/Makefile.inc b/src/mainboard/ti/beaglebone/Makefile.inc index a703939f01..0207a13962 100644 --- a/src/mainboard/ti/beaglebone/Makefile.inc +++ b/src/mainboard/ti/beaglebone/Makefile.inc @@ -2,6 +2,9 @@ bootblock-y += bootblock.c bootblock-y += leds.c +bootblock-y += sd_media.c + romstage-y += romstage.c +romstage-y += sd_media.c -#ramstage-y += ramstage.c +ramstage-y += sd_media.c diff --git a/src/mainboard/ti/beaglebone/board.fmd b/src/mainboard/ti/beaglebone/board.fmd new file mode 100644 index 0000000000..c0e4281b4d --- /dev/null +++ b/src/mainboard/ti/beaglebone/board.fmd @@ -0,0 +1,10 @@ +SDCARD@0x000 32M { + BIOS@0x0 109K { + BOOTBLOCK@0x0 20K + } + + PAYLOAD { + FMAP 2K + COREBOOT(CBFS) 31M + } +} diff --git a/src/mainboard/ti/beaglebone/sd_media.c b/src/mainboard/ti/beaglebone/sd_media.c new file mode 100644 index 0000000000..7e04f211dd --- /dev/null +++ b/src/mainboard/ti/beaglebone/sd_media.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <boot_device.h> +#include <symbols.h> +#include <console/console.h> +#include <assert.h> +#include <commonlib/storage/sd_mmc.h> +#include <cbmem.h> + +#include <soc/ti/am335x/mmc.h> +#include <soc/ti/am335x/header.h> + +// Where the coreboot image is expected to be located on the SD card +// Only certain locations are allowed - check the AM335x technical reference +// manual for more details. +#define COREBOOT_IMAGE_OFFSET (128 * KiB) + +#define SD_BLOCK_SIZE 512 + +static struct am335x_mmc_host sd_host; +static struct storage_media media; + +static size_t partial_block_read(uint8_t *dest, uint64_t block, uint32_t offset, uint32_t count) +{ + static uint8_t overflow_block[SD_BLOCK_SIZE]; + + uint64_t blocks_read = storage_block_read(&media, block, 1, &overflow_block); + + if (blocks_read != 1) { + printk(BIOS_ERR, "Expected to read 1 block but read: %llu\n", blocks_read); + return 0; + } + + assert((offset + count) <= SD_BLOCK_SIZE); + + int dest_index = 0; + for (int overflow_index = offset; overflow_index < (offset + count); overflow_index++) + dest[dest_index++] = overflow_block[overflow_index]; + + return count; +} + +// This supports reads from a SD card that aren't necessarily aligned to the +// sd block size +static ssize_t sd_readat(const struct region_device *rdev, void *dest, size_t offset, + size_t count) +{ + uint8_t *buffer = (uint8_t *)dest; + + uint64_t block_start = offset / SD_BLOCK_SIZE; + uint64_t block_end = (offset + count) / SD_BLOCK_SIZE; + uint64_t blocks = block_end - block_start + 1; + + // Read the last first, which might not be aligned on a SD block + uint32_t first_block_offset = offset % SD_BLOCK_SIZE; + size_t first_block_to_read = MIN(SD_BLOCK_SIZE - first_block_offset, count); + size_t bytes_read = partial_block_read(buffer, block_start, first_block_offset, + first_block_to_read); + + if (blocks == 1) + return bytes_read; + + buffer += bytes_read; + + if (blocks > 2) { + // Read all the "whole" blocks between the start and end blocks + uint64_t to_read = blocks - 2; + uint64_t blocks_read = + storage_block_read(&media, block_start + 1, to_read, (void *)buffer); + + if (blocks_read != to_read) { + printk(BIOS_ERR, "Expecting to read %llu blocks but only read %llu\n", + to_read, blocks_read); + return blocks_read * SD_BLOCK_SIZE; + } + + buffer += to_read * SD_BLOCK_SIZE; + bytes_read += to_read * SD_BLOCK_SIZE; + } + + // Read the last block, which might not be aligned on a SD block + bytes_read += partial_block_read(buffer, block_end, 0, count - bytes_read); + + return bytes_read; +} + +static const struct region_device_ops am335x_sd_ops = { + .mmap = mmap_helper_rdev_mmap, + .munmap = mmap_helper_rdev_munmap, + .readat = sd_readat, +}; + +extern struct omap_image_headers headers; + +static struct mmap_helper_region_device sd_mdev = MMAP_HELPER_REGION_INIT( + &am335x_sd_ops, COREBOOT_IMAGE_OFFSET + sizeof(headers), CONFIG_ROM_SIZE); + +static bool init_done = false; + +void boot_device_init(void) +{ + if (init_done) + return; + + sd_host.sd_clock_hz = 96000000; + sd_host.reg = (void *)MMCHS0_BASE; + am335x_mmc_init_storage(&sd_host); + storage_setup_media(&media, &sd_host.sd_mmc_ctrlr); + storage_display_setup(&media); + + if (ENV_BOOTBLOCK) { + mmap_helper_device_init(&sd_mdev, _cbfs_cache, REGION_SIZE(cbfs_cache)); + } else { + mmap_helper_device_init(&sd_mdev, _postram_cbfs_cache, + REGION_SIZE(postram_cbfs_cache)); + } + + init_done = true; +} + +const struct region_device *boot_device_ro(void) +{ + return &sd_mdev.rdev; +} |