summaryrefslogtreecommitdiff
path: root/src/mainboard/ti/beaglebone
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainboard/ti/beaglebone')
-rw-r--r--src/mainboard/ti/beaglebone/Kconfig8
-rw-r--r--src/mainboard/ti/beaglebone/Makefile.inc5
-rw-r--r--src/mainboard/ti/beaglebone/board.fmd10
-rw-r--r--src/mainboard/ti/beaglebone/sd_media.c124
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;
+}