1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <boot_device.h>
5 #include <console/console.h>
7 #include <commonlib/storage/sd_mmc.h>
10 #include <soc/ti/am335x/mmc.h>
11 #include <soc/ti/am335x/header.h>
13 // Where the coreboot image is expected to be located on the SD card
14 // Only certain locations are allowed - check the AM335x technical reference
15 // manual for more details.
16 #define COREBOOT_IMAGE_OFFSET (128 * KiB)
18 #define SD_BLOCK_SIZE 512
20 static struct am335x_mmc_host sd_host
;
21 static struct storage_media media
;
23 static size_t partial_block_read(uint8_t *dest
, uint64_t block
, uint32_t offset
, uint32_t count
)
25 static uint8_t overflow_block
[SD_BLOCK_SIZE
];
27 uint64_t blocks_read
= storage_block_read(&media
, block
, 1, &overflow_block
);
29 if (blocks_read
!= 1) {
30 printk(BIOS_ERR
, "Expected to read 1 block but read: %llu\n", blocks_read
);
34 assert((offset
+ count
) <= SD_BLOCK_SIZE
);
37 for (int overflow_index
= offset
; overflow_index
< (offset
+ count
); overflow_index
++)
38 dest
[dest_index
++] = overflow_block
[overflow_index
];
43 // This supports reads from a SD card that aren't necessarily aligned to the
45 static ssize_t
sd_readat(const struct region_device
*rdev
, void *dest
, size_t offset
,
48 uint8_t *buffer
= (uint8_t *)dest
;
50 uint64_t block_start
= offset
/ SD_BLOCK_SIZE
;
51 uint64_t block_end
= (offset
+ count
) / SD_BLOCK_SIZE
;
52 uint64_t blocks
= block_end
- block_start
+ 1;
54 // Read the last first, which might not be aligned on a SD block
55 uint32_t first_block_offset
= offset
% SD_BLOCK_SIZE
;
56 size_t first_block_to_read
= MIN(SD_BLOCK_SIZE
- first_block_offset
, count
);
57 size_t bytes_read
= partial_block_read(buffer
, block_start
, first_block_offset
,
66 // Read all the "whole" blocks between the start and end blocks
67 uint64_t to_read
= blocks
- 2;
68 uint64_t blocks_read
=
69 storage_block_read(&media
, block_start
+ 1, to_read
, (void *)buffer
);
71 if (blocks_read
!= to_read
) {
72 printk(BIOS_ERR
, "Expecting to read %llu blocks but only read %llu\n",
73 to_read
, blocks_read
);
74 return blocks_read
* SD_BLOCK_SIZE
;
77 buffer
+= to_read
* SD_BLOCK_SIZE
;
78 bytes_read
+= to_read
* SD_BLOCK_SIZE
;
81 // Read the last block, which might not be aligned on a SD block
82 bytes_read
+= partial_block_read(buffer
, block_end
, 0, count
- bytes_read
);
87 static const struct region_device_ops am335x_sd_ops
= {
88 .mmap
= mmap_helper_rdev_mmap
,
89 .munmap
= mmap_helper_rdev_munmap
,
93 extern struct omap_image_headers headers
;
95 static struct mmap_helper_region_device sd_mdev
= MMAP_HELPER_DEV_INIT(
96 &am335x_sd_ops
, COREBOOT_IMAGE_OFFSET
+ sizeof(headers
), CONFIG_ROM_SIZE
,
99 static bool init_done
= false;
101 void boot_device_init(void)
106 sd_host
.sd_clock_hz
= 96000000;
107 sd_host
.reg
= (void *)MMCHS0_BASE
;
108 am335x_mmc_init_storage(&sd_host
);
109 storage_setup_media(&media
, &sd_host
.sd_mmc_ctrlr
);
110 storage_display_setup(&media
);
115 const struct region_device
*boot_device_ro(void)
117 return &sd_mdev
.rdev
;