aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2015-05-15 13:15:34 -0500
committerAaron Durbin <adurbin@chromium.org>2015-05-26 22:32:47 +0200
commitc6588c5af94e568bddd8111c3fca736f464042cf (patch)
tree0efa16d6948cfde369932fd18dec46102f807c2f /src/soc
parentdef0fb57dfd91e6599c622a7b2769164a5c02ef0 (diff)
coreboot: introduce boot_device
The boot_device is a region_device that represents the device from which coreboot retrieves and boots its stages. The existing cbfs implementations use the boot_device as the intermediary for accessing the CBFS region. Also, there's currently only support for a read-only view of the boot_device. i.e. one cannot write to the boot_device using this view. However, a writable boot_device could be added in the future. Change-Id: Ic0da796ab161b8025c90631be3423ba6473ad31c Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/10216 Tested-by: build bot (Jenkins) Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com> Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/nvidia/tegra124/Makefile.inc4
-rw-r--r--src/soc/nvidia/tegra124/cbfs.c29
-rw-r--r--src/soc/nvidia/tegra124/include/soc/spi.h5
-rw-r--r--src/soc/nvidia/tegra124/spi.c116
-rw-r--r--src/soc/nvidia/tegra132/Makefile.inc4
-rw-r--r--src/soc/nvidia/tegra132/cbfs.c28
-rw-r--r--src/soc/nvidia/tegra132/include/soc/spi.h5
-rw-r--r--src/soc/nvidia/tegra132/spi.c116
-rw-r--r--src/soc/samsung/exynos5250/alternate_cbfs.c118
-rw-r--r--src/soc/samsung/exynos5250/include/soc/spi.h9
-rw-r--r--src/soc/samsung/exynos5250/spi.c85
-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
14 files changed, 379 insertions, 345 deletions
diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc
index 78054f4511..46ce59d757 100644
--- a/src/soc/nvidia/tegra124/Makefile.inc
+++ b/src/soc/nvidia/tegra124/Makefile.inc
@@ -2,7 +2,6 @@ ifeq ($(CONFIG_SOC_NVIDIA_TEGRA124),y)
bootblock-y += bootblock.c
bootblock-y += bootblock_asm.S
-bootblock-y += cbfs.c
bootblock-y += clock.c
bootblock-y += dma.c
bootblock-y += i2c.c
@@ -22,7 +21,6 @@ bootblock-$(CONFIG_DRIVERS_UART) += uart.c
endif
verstage-y += verstage.c
-verstage-y += cbfs.c
verstage-y += dma.c
verstage-y += monotonic_timer.c
verstage-y += spi.c
@@ -34,7 +32,6 @@ verstage-y += clock.c
verstage-y += i2c.c
verstage-y += cache.c
-romstage-y += cbfs.c
romstage-y += cbmem.c
romstage-y += clock.c
romstage-y += dma.c
@@ -51,7 +48,6 @@ romstage-y += ../tegra/pinmux.c
romstage-y += cache.c
romstage-$(CONFIG_DRIVERS_UART) += uart.c
-ramstage-y += cbfs.c
ramstage-y += cbmem.c
ramstage-y += clock.c
ramstage-y += display.c
diff --git a/src/soc/nvidia/tegra124/cbfs.c b/src/soc/nvidia/tegra124/cbfs.c
deleted file mode 100644
index d82ca9a961..0000000000
--- a/src/soc/nvidia/tegra124/cbfs.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-
-#include <cbfs.h> /* This driver serves as a CBFS media source. */
-#include <soc/spi.h>
-#include <symbols.h>
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
- return initialize_tegra_spi_cbfs_media(media,
- _cbfs_cache, _cbfs_cache_size);
-}
diff --git a/src/soc/nvidia/tegra124/include/soc/spi.h b/src/soc/nvidia/tegra124/include/soc/spi.h
index ab046323b1..cfa3cd2b57 100644
--- a/src/soc/nvidia/tegra124/include/soc/spi.h
+++ b/src/soc/nvidia/tegra124/include/soc/spi.h
@@ -61,11 +61,6 @@ struct tegra_spi_channel {
enum spi_xfer_mode xfer_mode;
};
-struct cbfs_media;
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size);
-
struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
#endif /* __NVIDIA_TEGRA124_SPI_H__ */
diff --git a/src/soc/nvidia/tegra124/spi.c b/src/soc/nvidia/tegra124/spi.c
index 683edd1cf0..0cf54956d3 100644
--- a/src/soc/nvidia/tegra124/spi.c
+++ b/src/soc/nvidia/tegra124/spi.c
@@ -21,6 +21,7 @@
#include <arch/cache.h>
#include <arch/io.h>
#include <assert.h>
+#include <boot_device.h>
#include <console/console.h>
#include <cbfs.h>
#include <delay.h>
@@ -33,6 +34,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <symbols.h>
#include <timer.h>
@@ -800,12 +802,6 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
return ret;
}
-/* SPI as CBFS media. */
-struct tegra_spi_media {
- struct spi_slave *slave;
- struct cbfs_simple_buffer buffer;
-};
-
static int tegra_spi_cbfs_open(struct cbfs_media *media)
{
DEBUG_SPI("tegra_spi_cbfs_open\n");
@@ -823,16 +819,17 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media)
#define JEDEC_FAST_READ_DUAL 0x3b
#define JEDEC_FAST_READ_DUAL_OUTSIZE 0x05
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
- size_t offset, size_t count)
+static struct spi_slave *boot_slave;
+
+static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
+ size_t offset, size_t count)
{
- struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context;
u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE];
unsigned int read_cmd_bytes;
int ret = count;
struct tegra_spi_channel *channel;
- channel = to_tegra_spi(spi->slave->bus);
+ channel = to_tegra_spi(boot_slave->bus);
if (channel->dual_mode) {
/*
@@ -853,9 +850,9 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
spi_read_cmd[2] = (offset >> 8) & 0xff;
spi_read_cmd[3] = offset & 0xff;
- spi_claim_bus(spi->slave);
+ spi_claim_bus(boot_slave);
- if (spi_xfer(spi->slave, spi_read_cmd,
+ if (spi_xfer(boot_slave, spi_read_cmd,
read_cmd_bytes, NULL, 0) < 0) {
ret = -1;
printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n",
@@ -866,7 +863,7 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
if (channel->dual_mode) {
setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT);
}
- if (spi_xfer(spi->slave, NULL, 0, dest, count)) {
+ if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
ret = -1;
printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n",
__func__, count);
@@ -876,56 +873,70 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
tegra_spi_cbfs_read_exit:
/* de-assert /CS */
- spi_release_bus(spi->slave);
- return (ret < 0) ? 0 : ret;
+ spi_release_bus(boot_slave);
+ return ret;
+}
+
+static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
+ size_t offset, size_t count)
+{
+ const struct region_device *boot_dev;
+
+ boot_dev = media->context;
+
+ printk(BIOS_ERR, "%s: reading %zx bytes from %zx\n",
+ __func__, count, offset);
+ if (rdev_readat(boot_dev, dest, offset, count) < 0)
+ return 0;
+
+ return count;
}
static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset,
size_t count)
{
- struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
+ const struct region_device *boot_dev;
void *map;
+
DEBUG_SPI("tegra_spi_cbfs_map\n");
- map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
+
+ boot_dev = media->context;
+
+ map = rdev_mmap(boot_dev, offset, count);
+
+ if (map == NULL)
+ map = (void *)-1;
+
return map;
}
static void *tegra_spi_cbfs_unmap(struct cbfs_media *media,
const void *address)
{
- struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
+ const struct region_device *boot_dev;
+
DEBUG_SPI("tegra_spi_cbfs_unmap\n");
- return cbfs_simple_buffer_unmap(&spi->buffer, address);
-}
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size)
-{
- // TODO Replace static variable to support multiple streams.
- static struct tegra_spi_media context;
- static struct tegra_spi_channel *channel;
+ boot_dev = media->context;
- channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
- channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
+ rdev_munmap(boot_dev, (void *)address);
+ return NULL;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media)
+{
DEBUG_SPI("Initializing CBFS media on SPI\n");
- context.slave = &channel->slave;
- context.buffer.allocated = context.buffer.last_allocate = 0;
- context.buffer.buffer = buffer_address;
- context.buffer.size = buffer_size;
- media->context = (void*)&context;
+ boot_device_init();
+
+ media->context = (void *)boot_device_ro();
media->open = tegra_spi_cbfs_open;
media->close = tegra_spi_cbfs_close;
media->read = tegra_spi_cbfs_read;
media->map = tegra_spi_cbfs_map;
media->unmap = tegra_spi_cbfs_unmap;
-#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
- channel->dual_mode = 1;
-#endif
-
return 0;
}
@@ -937,3 +948,32 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
return &channel->slave;
}
+
+static const struct region_device_ops tegra_spi_ops = {
+ .mmap = mmap_helper_rdev_mmap,
+ .munmap = mmap_helper_rdev_munmap,
+ .readat = tegra_spi_readat,
+};
+
+static struct mmap_helper_region_device mdev =
+ MMAP_HELPER_REGION_INIT(&tegra_spi_ops, 0, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
+{
+ return &mdev.rdev;
+}
+
+void boot_device_init(void)
+{
+ struct tegra_spi_channel *boot_chan;
+
+ boot_chan = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
+ boot_chan->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
+
+#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
+ boot_chan->dual_mode = 1;
+#endif
+ boot_slave = &boot_chan->slave;
+
+ mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+}
diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index 365dab314f..c192055cdf 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -2,7 +2,6 @@ ifeq ($(CONFIG_SOC_NVIDIA_TEGRA132),y)
bootblock-y += bootblock.c
bootblock-y += bootblock_asm.S
-bootblock-y += cbfs.c
bootblock-y += clock.c
bootblock-y += spi.c
bootblock-y += i2c.c
@@ -23,7 +22,6 @@ bootblock-$(CONFIG_DRIVERS_UART) += uart.c
endif
verstage-y += verstage.c
-verstage-y += cbfs.c
verstage-y += dma.c
verstage-y += monotonic_timer.c
verstage-y += spi.c
@@ -39,7 +37,6 @@ verstage-y += i2c.c
romstage-y += 32bit_reset.S
romstage-y += romstage_asm.S
romstage-y += addressmap.c
-romstage-y += cbfs.c
romstage-y += cbmem.c
romstage-y += ccplex.c
romstage-y += clock.c
@@ -63,7 +60,6 @@ romstage-$(CONFIG_DRIVERS_UART) += uart.c
ramstage-y += 32bit_reset.S
ramstage-y += addressmap.c
-ramstage-y += cbfs.c
ramstage-y += cbmem.c
ramstage-y += cpu.c
ramstage-y += cpu_lib.S
diff --git a/src/soc/nvidia/tegra132/cbfs.c b/src/soc/nvidia/tegra132/cbfs.c
deleted file mode 100644
index 7aeb59bc94..0000000000
--- a/src/soc/nvidia/tegra132/cbfs.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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.
- */
-
-#include <cbfs.h> /* This driver serves as a CBFS media source. */
-#include <soc/spi.h>
-#include <symbols.h>
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
- return initialize_tegra_spi_cbfs_media(media,
- _cbfs_cache, _cbfs_cache_size);
-}
diff --git a/src/soc/nvidia/tegra132/include/soc/spi.h b/src/soc/nvidia/tegra132/include/soc/spi.h
index 2fd9562599..4c91c27c7f 100644
--- a/src/soc/nvidia/tegra132/include/soc/spi.h
+++ b/src/soc/nvidia/tegra132/include/soc/spi.h
@@ -62,11 +62,6 @@ struct tegra_spi_channel {
enum spi_xfer_mode xfer_mode;
};
-struct cbfs_media;
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size);
-
struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
#endif /* __NVIDIA_TEGRA132_SPI_H__ */
diff --git a/src/soc/nvidia/tegra132/spi.c b/src/soc/nvidia/tegra132/spi.c
index 7ca66e1ad8..1650057fab 100644
--- a/src/soc/nvidia/tegra132/spi.c
+++ b/src/soc/nvidia/tegra132/spi.c
@@ -21,6 +21,7 @@
#include <arch/cache.h>
#include <arch/io.h>
#include <assert.h>
+#include <boot_device.h>
#include <cbfs.h>
#include <console/console.h>
#include <delay.h>
@@ -33,6 +34,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <symbols.h>
#include <timer.h>
@@ -815,12 +817,6 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
return ret;
}
-/* SPI as CBFS media. */
-struct tegra_spi_media {
- struct spi_slave *slave;
- struct cbfs_simple_buffer buffer;
-};
-
static int tegra_spi_cbfs_open(struct cbfs_media *media)
{
DEBUG_SPI("tegra_spi_cbfs_open\n");
@@ -838,16 +834,17 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media)
#define JEDEC_FAST_READ_DUAL 0x3b
#define JEDEC_FAST_READ_DUAL_OUTSIZE 0x05
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
- size_t offset, size_t count)
+static struct spi_slave *boot_slave;
+
+static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
+ size_t offset, size_t count)
{
- struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context;
u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE];
unsigned int read_cmd_bytes;
int ret = count;
struct tegra_spi_channel *channel;
- channel = to_tegra_spi(spi->slave->bus);
+ channel = to_tegra_spi(boot_slave->bus);
if (channel->dual_mode) {
/*
@@ -868,9 +865,9 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
spi_read_cmd[2] = (offset >> 8) & 0xff;
spi_read_cmd[3] = offset & 0xff;
- spi_claim_bus(spi->slave);
+ spi_claim_bus(boot_slave);
- if (spi_xfer(spi->slave, spi_read_cmd,
+ if (spi_xfer(boot_slave, spi_read_cmd,
read_cmd_bytes, NULL, 0) < 0) {
ret = -1;
printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n",
@@ -881,7 +878,7 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
if (channel->dual_mode) {
setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT);
}
- if (spi_xfer(spi->slave, NULL, 0, dest, count)) {
+ if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
ret = -1;
printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n",
__func__, count);
@@ -891,56 +888,70 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
tegra_spi_cbfs_read_exit:
/* de-assert /CS */
- spi_release_bus(spi->slave);
- return (ret < 0) ? 0 : ret;
+ spi_release_bus(boot_slave);
+ return ret;
+}
+
+static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
+ size_t offset, size_t count)
+{
+ const struct region_device *boot_dev;
+
+ boot_dev = media->context;
+
+ DEBUG_SPI("%s: reading %zx bytes from %zx\n", __func__, count, offset);
+
+ if (rdev_readat(boot_dev, dest, offset, count) < 0)
+ return 0;
+
+ return count;
}
static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset,
size_t count)
{
- struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
+ const struct region_device *boot_dev;
void *map;
+
DEBUG_SPI("tegra_spi_cbfs_map\n");
- map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
+
+ boot_dev = media->context;
+
+ map = rdev_mmap(boot_dev, offset, count);
+
+ if (map == NULL)
+ map = (void *)-1;
+
return map;
}
static void *tegra_spi_cbfs_unmap(struct cbfs_media *media,
const void *address)
{
- struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
+ const struct region_device *boot_dev;
+
DEBUG_SPI("tegra_spi_cbfs_unmap\n");
- return cbfs_simple_buffer_unmap(&spi->buffer, address);
-}
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size)
-{
- // TODO Replace static variable to support multiple streams.
- static struct tegra_spi_media context;
- static struct tegra_spi_channel *channel;
+ boot_dev = media->context;
- channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
- channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
+ rdev_munmap(boot_dev, (void *)address);
+ return NULL;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media)
+{
DEBUG_SPI("Initializing CBFS media on SPI\n");
- context.slave = &channel->slave;
- context.buffer.allocated = context.buffer.last_allocate = 0;
- context.buffer.buffer = buffer_address;
- context.buffer.size = buffer_size;
- media->context = (void*)&context;
+ boot_device_init();
+
+ media->context = (void *)boot_device_ro();
media->open = tegra_spi_cbfs_open;
media->close = tegra_spi_cbfs_close;
media->read = tegra_spi_cbfs_read;
media->map = tegra_spi_cbfs_map;
media->unmap = tegra_spi_cbfs_unmap;
-#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
- channel->dual_mode = 1;
-#endif
-
return 0;
}
@@ -952,3 +963,32 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
return &channel->slave;
}
+
+static const struct region_device_ops tegra_spi_ops = {
+ .mmap = mmap_helper_rdev_mmap,
+ .munmap = mmap_helper_rdev_munmap,
+ .readat = tegra_spi_readat,
+};
+
+static struct mmap_helper_region_device mdev =
+ MMAP_HELPER_REGION_INIT(&tegra_spi_ops, 0, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
+{
+ return &mdev.rdev;
+}
+
+void boot_device_init(void)
+{
+ struct tegra_spi_channel *boot_chan;
+
+ boot_chan = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
+ boot_chan->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
+
+#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
+ boot_chan->dual_mode = 1;
+#endif
+ boot_slave = &boot_chan->slave;
+
+ mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+}
diff --git a/src/soc/samsung/exynos5250/alternate_cbfs.c b/src/soc/samsung/exynos5250/alternate_cbfs.c
index 2e2aeec562..546018a35a 100644
--- a/src/soc/samsung/exynos5250/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5250/alternate_cbfs.c
@@ -19,6 +19,7 @@
#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>
@@ -45,7 +46,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;
@@ -80,7 +81,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__
/*
@@ -111,66 +112,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/exynos5250/include/soc/spi.h b/src/soc/samsung/exynos5250/include/soc/spi.h
index 92236aecba..298db1a851 100644
--- a/src/soc/samsung/exynos5250/include/soc/spi.h
+++ b/src/soc/samsung/exynos5250/include/soc/spi.h
@@ -20,8 +20,7 @@
#ifndef CPU_SAMSUNG_EXYNOS5250_SPI_H
#define CPU_SAMSUNG_EXYNOS5250_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 {
@@ -92,8 +91,6 @@ int exynos_spi_open(struct exynos_spi *regs);
int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off);
int exynos_spi_close(struct exynos_spi *regs);
-/* 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/exynos5250/spi.c b/src/soc/samsung/exynos5250/spi.c
index 4f32487623..adf31e4e78 100644
--- a/src/soc/samsung/exynos5250/spi.c
+++ b/src/soc/samsung/exynos5250/spi.c
@@ -20,11 +20,13 @@
#include <arch/io.h>
#include <assert.h>
+#include <boot_device.h>
#include <console/console.h>
#include <soc/clk.h>
#include <soc/gpio.h>
#include <soc/spi.h>
#include <stdlib.h>
+#include <symbols.h>
#if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI
# define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "EXYNOS_SPI: " x)
@@ -144,70 +146,47 @@ int exynos_spi_close(struct exynos_spi *regs)
return 0;
}
-// SPI as CBFS media.
-struct exynos_spi_media {
- struct exynos_spi *regs;
- 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 exynos_spi_open(spi->regs);
-}
-
-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");
- return exynos_spi_close(spi->regs);
-}
+static struct exynos_spi *boot_slave_regs;
-static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
- size_t offset, size_t count) {
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest,
+ size_t offset, size_t count)
+{
int bytes;
DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
- bytes = exynos_spi_read(spi->regs, dest, count, offset);
- // Flush and re-open the device.
- exynos_spi_close(spi->regs);
- exynos_spi_open(spi->regs);
+ exynos_spi_open(boot_slave_regs);
+ bytes = exynos_spi_read(boot_slave_regs, dest, count, offset);
+ exynos_spi_close(boot_slave_regs);
return bytes;
}
-static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset,
- size_t count) {
- struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+static void *exynos_spi_map(const struct region_device *rdev,
+ size_t offset, size_t count)
+{
DEBUG_SPI("exynos_spi_cbfs_map\n");
- // See exynos_spi_rx_tx for I/O alignment limitation.
+ // 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) {
- 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);
-}
+static const struct region_device_ops exynos_spi_ops = {
+ .mmap = exynos_spi_map,
+ .munmap = mmap_helper_rdev_munmap,
+ .readat = exynos_spi_readat,
+};
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
- void *buffer_address,
- size_t buffer_size) {
- // TODO Replace static variable to support multiple streams.
- static struct exynos_spi_media context;
- DEBUG_SPI("initialize_exynos_spi_cbfs_media\n");
-
- context.regs = (void*)EXYNOS5_SPI1_BASE;
- 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;
+static struct mmap_helper_region_device mdev =
+ MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE);
- return 0;
+void exynos_init_spi_boot_device(void)
+{
+ boot_slave_regs = (void *)EXYNOS5_SPI1_BASE;
+
+ mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+}
+
+const struct region_device *exynos_spi_boot_device(void)
+{
+ return &mdev.rdev;
}
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;
}