summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2016-02-29 15:25:57 -0700
committerSimon Glass <sjg@chromium.org>2016-03-14 15:34:50 -0600
commit40fd050890e08eb6d064aaf074cf3a8b75d1251e (patch)
treec7833a964277e045db74e4f5e602efc23b8a9bde /drivers/block
parent7ded959e4d5b93c10a8b57a0a391fb35cefb85ce (diff)
downloadtalos-obmc-uboot-40fd050890e08eb6d064aaf074cf3a8b75d1251e.tar.gz
talos-obmc-uboot-40fd050890e08eb6d064aaf074cf3a8b75d1251e.zip
dm: sandbox: Add driver-model block-device support for sandbox
Update the host driver to support driver model for block devices. A future commit will remove the old code, but for now it is useful to be able to use it both with and without CONFIG_BLK. Signed-off-by: Simon Glass <sjg@chromium.org> Tested-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/sandbox.c118
1 files changed, 117 insertions, 1 deletions
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index dde9d6845f..6d41508d5c 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -4,14 +4,20 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#include <config.h>
#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <fdtdec.h>
#include <part.h>
#include <os.h>
#include <malloc.h>
#include <sandboxblockdev.h>
#include <asm/errno.h>
+#include <dm/device-internal.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_BLK
static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES];
static struct host_block_dev *find_host_device(int dev)
@@ -21,7 +27,17 @@ static struct host_block_dev *find_host_device(int dev)
return NULL;
}
+#endif
+
+#ifdef CONFIG_BLK
+static unsigned long host_block_read(struct udevice *dev,
+ unsigned long start, lbaint_t blkcnt,
+ void *buffer)
+{
+ struct host_block_dev *host_dev = dev_get_priv(dev);
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#else
static unsigned long host_block_read(struct blk_desc *block_dev,
unsigned long start, lbaint_t blkcnt,
void *buffer)
@@ -31,6 +47,7 @@ static unsigned long host_block_read(struct blk_desc *block_dev,
if (!host_dev)
return -1;
+#endif
if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) ==
-1) {
@@ -43,12 +60,21 @@ static unsigned long host_block_read(struct blk_desc *block_dev,
return -1;
}
+#ifdef CONFIG_BLK
+static unsigned long host_block_write(struct udevice *dev,
+ unsigned long start, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct host_block_dev *host_dev = dev_get_priv(dev);
+ struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#else
static unsigned long host_block_write(struct blk_desc *block_dev,
unsigned long start, lbaint_t blkcnt,
const void *buffer)
{
int dev = block_dev->devnum;
struct host_block_dev *host_dev = find_host_device(dev);
+#endif
if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) ==
-1) {
@@ -61,6 +87,70 @@ static unsigned long host_block_write(struct blk_desc *block_dev,
return -1;
}
+#ifdef CONFIG_BLK
+int host_dev_bind(int devnum, char *filename)
+{
+ struct host_block_dev *host_dev;
+ struct udevice *dev;
+ char dev_name[20], *str, *fname;
+ int ret, fd;
+
+ /* Remove and unbind the old device, if any */
+ ret = blk_get_device(IF_TYPE_HOST, devnum, &dev);
+ if (ret == 0) {
+ ret = device_remove(dev);
+ if (ret)
+ return ret;
+ ret = device_unbind(dev);
+ if (ret)
+ return ret;
+ } else if (ret != -ENODEV) {
+ return ret;
+ }
+
+ if (!filename)
+ return 0;
+
+ snprintf(dev_name, sizeof(dev_name), "host%d", devnum);
+ str = strdup(dev_name);
+ if (!str)
+ return -ENOMEM;
+ fname = strdup(filename);
+ if (!fname) {
+ free(str);
+ return -ENOMEM;
+ }
+
+ fd = os_open(filename, OS_O_RDWR);
+ if (fd == -1) {
+ printf("Failed to access host backing file '%s'\n", filename);
+ ret = -ENOENT;
+ goto err;
+ }
+ ret = blk_create_device(gd->dm_root, "sandbox_host_blk", str,
+ IF_TYPE_HOST, devnum, 512,
+ os_lseek(fd, 0, OS_SEEK_END), &dev);
+ if (ret)
+ goto err_file;
+ ret = device_probe(dev);
+ if (ret) {
+ device_unbind(dev);
+ goto err_file;
+ }
+
+ host_dev = dev_get_priv(dev);
+ host_dev->fd = fd;
+ host_dev->filename = fname;
+
+ return blk_prepare_device(dev);
+err_file:
+ os_close(fd);
+err:
+ free(fname);
+ free(str);
+ return ret;
+}
+#else
int host_dev_bind(int dev, char *filename)
{
struct host_block_dev *host_dev = find_host_device(dev);
@@ -100,9 +190,19 @@ int host_dev_bind(int dev, char *filename)
return 0;
}
+#endif
int host_get_dev_err(int devnum, struct blk_desc **blk_devp)
{
+#ifdef CONFIG_BLK
+ struct udevice *dev;
+ int ret;
+
+ ret = blk_get_device(IF_TYPE_HOST, devnum, &dev);
+ if (ret)
+ return ret;
+ *blk_devp = dev_get_uclass_platdata(dev);
+#else
struct host_block_dev *host_dev = find_host_device(devnum);
if (!host_dev)
@@ -112,6 +212,8 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp)
return -ENOENT;
*blk_devp = &host_dev->blk_dev;
+#endif
+
return 0;
}
@@ -124,3 +226,17 @@ struct blk_desc *host_get_dev(int dev)
return blk_dev;
}
+
+#ifdef CONFIG_BLK
+static const struct blk_ops sandbox_host_blk_ops = {
+ .read = host_block_read,
+ .write = host_block_write,
+};
+
+U_BOOT_DRIVER(sandbox_host_blk) = {
+ .name = "sandbox_host_blk",
+ .id = UCLASS_BLK,
+ .ops = &sandbox_host_blk_ops,
+ .priv_auto_alloc_size = sizeof(struct host_block_dev),
+};
+#endif
OpenPOWER on IntegriCloud