summaryrefslogtreecommitdiff
path: root/src/soc/samsung/exynos5420
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/samsung/exynos5420')
-rw-r--r--src/soc/samsung/exynos5420/alternate_cbfs.c118
-rw-r--r--src/soc/samsung/exynos5420/include/soc/spi.h9
-rw-r--r--src/soc/samsung/exynos5420/spi.c78
3 files changed, 107 insertions, 98 deletions
diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c
index b30ed6bff7..9bba748a84 100644
--- a/src/soc/samsung/exynos5420/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5420/alternate_cbfs.c
@@ -20,6 +20,7 @@
#include <arch/cache.h>
#include <assert.h>
+#include <boot_device.h>
#include <cbfs.h> /* This driver serves as a CBFS media source. */
#include <console/console.h>
#include <soc/alternate_cbfs.h>
@@ -46,7 +47,7 @@
* 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(void)
{
#ifdef __PRE_RAM__
static int first_run = 1;
@@ -84,7 +85,7 @@ static int usb_cbfs_open(struct cbfs_media *media)
* this seems like a safer approach. It also makes it easy to pass our image
* down to payloads.
*/
-static int sdmmc_cbfs_open(struct cbfs_media *media)
+static int sdmmc_cbfs_open(void)
{
#ifdef __PRE_RAM__
/*
@@ -118,66 +119,109 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
return 0;
}
-static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
+static int exynos_cbfs_open(struct cbfs_media *media) {
+ return 0;
+}
+
+static int exynos_cbfs_close(struct cbfs_media *media) {
+ return 0;
+}
+
+static size_t exynos_cbfs_read(struct cbfs_media *media, void *dest,
+ size_t offset, size_t count) {
+ const struct region_device *boot_dev;
+
+ boot_dev = media->context;
+
+ if (rdev_readat(boot_dev, dest, offset, count) < 0)
+ return 0;
-static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
- size_t offset, size_t count)
-{
- ASSERT(offset + count < _cbfs_cache_size);
- memcpy(dest, _cbfs_cache + offset, count);
return count;
}
-static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset,
- size_t count)
-{
- ASSERT(offset + count < _cbfs_cache_size);
- return _cbfs_cache + offset;
+static void *exynos_cbfs_map(struct cbfs_media *media, size_t offset,
+ size_t count) {
+ const struct region_device *boot_dev;
+ void *ptr;
+
+ boot_dev = media->context;
+
+ ptr = rdev_mmap(boot_dev, offset, count);
+
+ if (ptr == NULL)
+ return (void *)-1;
+
+ return ptr;
}
-static void *alternate_cbfs_unmap(struct cbfs_media *media,
- const void *buffer) { return 0; }
+static void *exynos_cbfs_unmap(struct cbfs_media *media,
+ const void *address) {
+ const struct region_device *boot_dev;
-static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
-{
- printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
+ boot_dev = media->context;
- media->open = sdmmc_cbfs_open;
- media->close = alternate_cbfs_close;
- media->read = alternate_cbfs_read;
- media->map = alternate_cbfs_map;
- media->unmap = alternate_cbfs_unmap;
+ rdev_munmap(boot_dev, (void *)address);
- return 0;
+ return NULL;
}
-static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
+int init_default_cbfs_media(struct cbfs_media *media)
{
- printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
+ boot_device_init();
- 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;
+ media->context = (void *)boot_device_ro();
+
+ if (media->context == NULL)
+ return -1;
+
+ media->open = exynos_cbfs_open;
+ media->close = exynos_cbfs_close;
+ media->read = exynos_cbfs_read;
+ media->map = exynos_cbfs_map;
+ media->unmap = exynos_cbfs_unmap;
return 0;
}
-int init_default_cbfs_media(struct cbfs_media *media)
+static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
+
+const struct region_device *boot_device_ro(void)
{
if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
- return initialize_exynos_usb_cbfs_media(media);
+ return &alternate_rdev.rdev;
+
+ switch (exynos_power->om_stat & OM_STAT_MASK) {
+ case OM_STAT_SDMMC:
+ return &alternate_rdev.rdev;
+ case OM_STAT_SPI:
+ return exynos_spi_boot_device();
+ default:
+ printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
+ exynos_power->om_stat);
+ return NULL;
+ }
+}
+
+void boot_device_init(void)
+{
+ mem_region_device_init(&alternate_rdev, _cbfs_cache, _cbfs_cache_size);
+
+ if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) {
+ printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
+ usb_cbfs_open();
+ return;
+ }
switch (exynos_power->om_stat & OM_STAT_MASK) {
case OM_STAT_SDMMC:
- return initialize_exynos_sdmmc_cbfs_media(media);
+ printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
+ sdmmc_cbfs_open();
+ break;
case OM_STAT_SPI:
- return initialize_exynos_spi_cbfs_media(media,
- _cbfs_cache, _cbfs_cache_size);
+ exynos_init_spi_boot_device();
+ break;
default:
printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
exynos_power->om_stat);
- return 1;
}
}
diff --git a/src/soc/samsung/exynos5420/include/soc/spi.h b/src/soc/samsung/exynos5420/include/soc/spi.h
index cf778003be..77d5ffc8c7 100644
--- a/src/soc/samsung/exynos5420/include/soc/spi.h
+++ b/src/soc/samsung/exynos5420/include/soc/spi.h
@@ -20,8 +20,7 @@
#ifndef CPU_SAMSUNG_EXYNOS5420_SPI_H
#define CPU_SAMSUNG_EXYNOS5420_SPI_H
-/* This driver serves as a CBFS media source. */
-#include <cbfs.h>
+#include <boot_device.h>
/* SPI peripheral register map; padded to 64KB */
struct exynos_spi {
@@ -91,8 +90,6 @@ check_member(exynos_spi, fb_clk, 0x2c);
#define SPI_RX_BYTE_SWAP (1 << 6)
#define SPI_RX_HWORD_SWAP (1 << 7)
-/* Serve as CBFS media source */
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size);
+void exynos_init_spi_boot_device(void);
+const struct region_device *exynos_spi_boot_device(void);
#endif
diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c
index 5f298036ef..2edc3374dd 100644
--- a/src/soc/samsung/exynos5420/spi.c
+++ b/src/soc/samsung/exynos5420/spi.c
@@ -26,6 +26,7 @@
#include <spi_flash.h>
#include <stdlib.h>
#include <string.h>
+#include <symbols.h>
#define EXYNOS_SPI_MAX_TRANSFER_BYTES (65535)
@@ -242,76 +243,43 @@ static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len,
return len;
}
-// SPI as CBFS media.
-struct exynos_spi_media {
- struct spi_slave *slave;
- struct cbfs_simple_buffer buffer;
-};
-
-static int exynos_spi_cbfs_open(struct cbfs_media *media)
-{
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
- DEBUG_SPI("exynos_spi_cbfs_open\n");
- return spi_claim_bus(spi->slave);
-}
-
-static int exynos_spi_cbfs_close(struct cbfs_media *media)
-{
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
- DEBUG_SPI("exynos_spi_cbfs_close\n");
- spi_release_bus(spi->slave);
- return 0;
-}
+static struct exynos_spi_slave *boot_slave;
-static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
- size_t offset, size_t count)
+static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest,
+ size_t offset, size_t count)
{
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
- int bytes;
DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
- bytes = exynos_spi_read(spi->slave, dest, count, offset);
- return bytes;
+ return exynos_spi_read(&boot_slave->slave, dest, count, offset);
}
-static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset,
- size_t count)
+static void *exynos_spi_map(const struct region_device *rdev,
+ size_t offset, size_t count)
{
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
DEBUG_SPI("exynos_spi_cbfs_map\n");
// exynos: spi_rx_tx may work in 4 byte-width-transmission mode and
// requires buffer memory address to be aligned.
if (count % 4)
count += 4 - (count % 4);
- return cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
+ return mmap_helper_rdev_mmap(rdev, offset, count);
}
-static void *exynos_spi_cbfs_unmap(struct cbfs_media *media,
- const void *address)
+static const struct region_device_ops exynos_spi_ops = {
+ .mmap = exynos_spi_map,
+ .munmap = mmap_helper_rdev_munmap,
+ .readat = exynos_spi_readat,
+};
+
+static struct mmap_helper_region_device mdev =
+ MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE);
+
+void exynos_init_spi_boot_device(void)
{
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
- DEBUG_SPI("exynos_spi_cbfs_unmap\n");
- return cbfs_simple_buffer_unmap(&spi->buffer, address);
+ boot_slave = &exynos_spi_slaves[1];
+
+ mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
}
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size)
+const struct region_device *exynos_spi_boot_device(void)
{
- // TODO Replace static variable to support multiple streams.
- static struct exynos_spi_media context;
- static struct exynos_spi_slave *eslave = &exynos_spi_slaves[1];
- DEBUG_SPI("initialize_exynos_spi_cbfs_media\n");
-
- context.slave = &eslave->slave;
- context.buffer.allocated = context.buffer.last_allocate = 0;
- context.buffer.buffer = buffer_address;
- context.buffer.size = buffer_size;
- media->context = (void*)&context;
- media->open = exynos_spi_cbfs_open;
- media->close = exynos_spi_cbfs_close;
- media->read = exynos_spi_cbfs_read;
- media->map = exynos_spi_cbfs_map;
- media->unmap = exynos_spi_cbfs_unmap;
-
- return 0;
+ return &mdev.rdev;
}