diff options
Diffstat (limited to 'arch/sandbox/board/hostfile.c')
-rw-r--r-- | arch/sandbox/board/hostfile.c | 94 |
1 files changed, 57 insertions, 37 deletions
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c index 4fdf2b317d..7afad95b6d 100644 --- a/arch/sandbox/board/hostfile.c +++ b/arch/sandbox/board/hostfile.c @@ -24,10 +24,9 @@ #include <errno.h> #include <linux/err.h> #include <mach/hostfile.h> +#include <featctrl.h> #include <xfuncs.h> -#include <linux/err.h> - struct hf_priv { union { struct block_device blk; @@ -35,6 +34,7 @@ struct hf_priv { }; const char *filename; int fd; + struct feature_controller feat; }; static ssize_t hf_read(struct hf_priv *priv, void *buf, size_t count, loff_t offset, ulong flags) @@ -91,25 +91,48 @@ static struct block_device_ops hf_blk_ops = { .write = hf_blk_write, }; -static void hf_info(struct device_d *dev) +static void hf_info(struct device *dev) { struct hf_priv *priv = dev->priv; printf("file: %s\n", priv->filename); } -static int hf_probe(struct device_d *dev) +static int hostfile_feat_check(struct feature_controller *feat, int idx) +{ + struct hf_priv *priv = container_of(feat, struct hf_priv, feat); + + return priv->fd >= 0 ? FEATCTRL_OKAY : FEATCTRL_GATED; +} + +static int hf_probe(struct device *dev) { - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; struct hf_priv *priv = xzalloc(sizeof(*priv)); struct cdev *cdev; - bool is_blockdev; + bool is_featctrl = false, is_blockdev; u64 reg[2]; int err; if (!np) return -ENODEV; + dev->priv = priv; + priv->fd = -1; + + if (IS_ENABLED(CONFIG_FEATURE_CONTROLLER) && + of_property_read_bool(np, "barebox,feature-controller")) { + priv->feat.dev = dev; + priv->feat.check = hostfile_feat_check; + + err = feature_controller_register(&priv->feat); + if (err) + return err; + + is_featctrl = true; + } + + err = of_property_read_u64_array(np, "reg", reg, ARRAY_SIZE(reg)); if (err) return err; @@ -122,16 +145,15 @@ static int hf_probe(struct device_d *dev) return err; if (priv->fd < 0) - return priv->fd; + return is_featctrl ? 0 : priv->fd; dev->info = hf_info; - dev->priv = priv; is_blockdev = of_property_read_bool(np, "barebox,blockdev"); cdev = is_blockdev ? &priv->blk.cdev : &priv->cdev; - cdev->device_node = np; + cdev_set_of_node(cdev, np); if (is_blockdev) { cdev->name = np->name; @@ -139,15 +161,12 @@ static int hf_probe(struct device_d *dev) priv->blk.ops = &hf_blk_ops; priv->blk.blockbits = SECTOR_SHIFT; priv->blk.num_blocks = reg[1] / SECTOR_SIZE; + priv->blk.type = BLK_TYPE_VIRTUAL; err = blockdevice_register(&priv->blk); if (err) return err; - err = parse_partition_table(&priv->blk); - if (err) - dev_warn(dev, "No partition table found\n"); - dev_info(dev, "registered as block device\n"); } else { cdev->name = np->name; @@ -166,7 +185,7 @@ static int hf_probe(struct device_d *dev) of_parse_partitions(cdev, np); of_partitions_register_fixup(cdev); - return 0; + return of_platform_populate(np, NULL, dev); } static __maybe_unused struct of_device_id hostfile_dt_ids[] = { @@ -176,8 +195,9 @@ static __maybe_unused struct of_device_id hostfile_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, hostfile_dt_ids); -static struct driver_d hf_drv = { +static struct driver hf_drv = { .name = "hostfile", .of_compatible = DRV_OF_COMPAT(hostfile_dt_ids), .probe = hf_probe, @@ -229,15 +249,30 @@ static int of_hostfile_map_fixup(struct device_node *root, void *ctx) struct device_node *node; int ret; - for_each_compatible_node_from(node, root, NULL, hostfile_dt_ids->compatible) { + for_each_compatible_node_from(node, root, NULL, "barebox,stickypage") { + char *filename; + + filename = linux_get_stickypage_path(); + if (!filename) { + pr_err("error allocating stickypage\n"); + continue; + } + + of_property_write_string(node, "barebox,filename", filename); + of_property_write_string(node, "compatible", "barebox,hostfile"); + } + + for_each_compatible_node_from(node, root, NULL, "barebox,hostfile") { struct hf_info hf = {}; uint64_t reg[2] = {}; - bool no_filename; hf.devname = node->name; ret = of_property_read_string(node, "barebox,filename", &hf.filename); - no_filename = ret; + if (ret) { + pr_err("skipping nameless hostfile %s\n", hf.devname); + continue; + } hf.is_blockdev = of_property_read_bool(node, "barebox,blockdev"); hf.is_cdev = of_property_read_bool(node, "barebox,cdev"); @@ -250,29 +285,14 @@ static int of_hostfile_map_fixup(struct device_node *root, void *ctx) ret = linux_open_hostfile(&hf); if (ret) - goto out; + continue; reg[0] = hf.base; reg[1] = hf.size; - ret = of_property_write_u64_array(node, "reg", reg, ARRAY_SIZE(reg)); - if (ret) - goto out; - - ret = of_property_write_bool(node, "barebox,blockdev", hf.is_blockdev); - if (ret) - goto out; - - if (no_filename) { - ret = of_property_write_string(node, "barebox,filename", hf.filename); - if (ret) - goto out; - } - - ret = of_property_write_u32(node, "barebox,fd", hf.fd); -out: - if (ret) - pr_err("error fixing up %s: %pe\n", hf.devname, ERR_PTR(ret)); + of_property_write_u64_array(node, "reg", reg, ARRAY_SIZE(reg)); + of_property_write_bool(node, "barebox,blockdev", hf.is_blockdev); + of_property_write_u32(node, "barebox,fd", hf.fd); } return 0; |