summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-01-11 13:11:06 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2016-01-11 13:11:06 +0100
commitb9a2512aaa22086dc84db3f55a0d912b206c11e3 (patch)
tree38cfaccf38003f10032808354fce63d1b369c9e2
parentb1ebbe76eb48b56ccd804636edcb5fb0b49da98a (diff)
parent0295088d53cd605aaf2a2accfd65c19c0f8a0cf0 (diff)
downloadbarebox-b9a2512aaa22086dc84db3f55a0d912b206c11e3.tar.gz
barebox-b9a2512aaa22086dc84db3f55a0d912b206c11e3.tar.xz
Merge branch 'for-next/misc'
-rw-r--r--Documentation/devicetree/bindings/barebox/barebox,environment.rst15
-rw-r--r--Documentation/devicetree/bindings/barebox/barebox,state.rst5
-rw-r--r--arch/arm/boards/at91sam9x5ek/hw_version.c2
-rw-r--r--arch/arm/boards/highbank/init.c4
-rw-r--r--arch/arm/configs/socfpga_defconfig1
-rw-r--r--arch/arm/dts/socfpga.dtsi8
-rw-r--r--arch/arm/mach-imx/ocotp.c1
-rw-r--r--arch/arm/mach-socfpga/generic.c38
-rw-r--r--commands/devinfo.c7
-rw-r--r--common/partitions.c20
-rw-r--r--common/partitions/Kconfig1
-rw-r--r--common/partitions/efi.c1
-rw-r--r--common/state.c25
-rw-r--r--drivers/input/gpio_keys.c23
-rw-r--r--drivers/of/Kconfig7
-rw-r--r--drivers/of/barebox.c47
-rw-r--r--drivers/of/of_path.c123
-rw-r--r--drivers/pci/pci-imx6.c75
-rw-r--r--drivers/usb/imx/chipidea-imx.c3
-rw-r--r--fs/devfs-core.c81
-rw-r--r--fs/devfs.c27
-rw-r--r--fs/fs.c7
-rw-r--r--include/bootstrap.h8
-rw-r--r--include/driver.h5
-rw-r--r--include/of.h19
-rw-r--r--lib/bootstrap/devfs.c2
-rw-r--r--lib/bootstrap/disk.c4
-rw-r--r--lib/readline.c5
28 files changed, 354 insertions, 210 deletions
diff --git a/Documentation/devicetree/bindings/barebox/barebox,environment.rst b/Documentation/devicetree/bindings/barebox/barebox,environment.rst
index d5e52ead04..12b103be10 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,environment.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,environment.rst
@@ -6,7 +6,10 @@ This driver provides an environment for barebox from the devicetree.
Required properties:
* ``compatible``: should be ``barebox,environment``
-* ``device-path``: path to the environment
+* ``device-path``: path to the device environment is on
+
+Optional properties:
+* ``file-path``: path to a file in the device named by device-path
The device-path is a multistring property. The first string should contain
a nodepath to the node containing the physical device of the environment or
@@ -19,9 +22,19 @@ the path to the environment. Supported values for <type>:
be the label for MTD partitions, the number for DOS
partitions (beginning with 0) or the name for GPT partitions.
+The file-path is the name of a file located in a FAT filesystem on the
+device named in device-path. This filesystem will be mounted and the
+environment loaded from the file's location in the directory tree.
+
Example::
environment@0 {
compatible = "barebox,environment";
device-path = &flash, "partname:barebox-environment";
};
+
+ environment@1 {
+ compatible = "barebox,environment";
+ device-path = &mmc, "partname:1";
+ file-path = "barebox.env";
+ };
diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
index ef66029372..d1b0627edf 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
@@ -55,8 +55,8 @@ Required properties:
``#size-cells = <1>``. Defines the ``offset`` and ``size`` of the
variable in the ``raw`` backend. ``size`` must fit the node
``type``. Variables are not allowed to overlap.
-* ``type``: Should be ``uint8``, ``uint32``, ``enum32``, ``mac`` or
- ``string`` for the type of the variable
+* ``type``: Should be ``uint8``, ``uint32``, ``int32``. ``enum32``, ``mac``
+ or ``string`` for the type of the variable
* ``names``: For ``enum32`` values only, this specifies the values
possible for ``enum32``.
@@ -93,6 +93,7 @@ Variable Types
* ``uint8``:
* ``uint32``:
+* ``int32``:
* ``enum32``: The ``default`` value is an integer representing an
offset into the names array.
* ``mac``:
diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c
index 37eb1f80c5..2f84d82d5d 100644
--- a/arch/arm/boards/at91sam9x5ek/hw_version.c
+++ b/arch/arm/boards/at91sam9x5ek/hw_version.c
@@ -235,7 +235,7 @@ static int cm_cogent_fixup(struct device_node *root, void *unused)
int ret;
struct device_node *node;
- for_each_compatible_node(node, NULL, "atmel,hsmci") {
+ for_each_compatible_node_from(node, root, NULL, "atmel,hsmci") {
struct device_node *slotnode =
of_get_child_by_name(node, "slot");
if (!slotnode)
diff --git a/arch/arm/boards/highbank/init.c b/arch/arm/boards/highbank/init.c
index a0d4b30b48..1cb02e6e48 100644
--- a/arch/arm/boards/highbank/init.c
+++ b/arch/arm/boards/highbank/init.c
@@ -35,13 +35,13 @@ static int hb_fixup(struct device_node *root, void *unused)
__be32 latency;
if (!(reg & HB_PWRDOM_STAT_SATA)) {
- for_each_compatible_node(node, NULL, "calxeda,hb-ahci")
+ for_each_compatible_node_from(node, root, NULL, "calxeda,hb-ahci")
of_set_property(node, "status", "disabled",
sizeof("disabled"), 1);
}
if (!(reg & HB_PWRDOM_STAT_EMMC)) {
- for_each_compatible_node(node, NULL, "calxeda,hb-sdhci")
+ for_each_compatible_node_from(node, root, NULL, "calxeda,hb-sdhci")
of_set_property(node, "status", "disabled",
sizeof("disabled"), 1);
}
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index 0a31de518d..7fbe045e27 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -67,6 +67,7 @@ CONFIG_NET=y
CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_OF_BAREBOX_ENV_IN_FS=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_NET_DESIGNWARE=y
CONFIG_MCI=y
diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi
index d4d498be13..d16758fdab 100644
--- a/arch/arm/dts/socfpga.dtsi
+++ b/arch/arm/dts/socfpga.dtsi
@@ -1,4 +1,12 @@
/ {
+ chosen {
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &mmc, "partname:1";
+ file-path = "barebox.env";
+ };
+ };
+
aliases {
mmc0 = &mmc;
};
diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 6ff5ee4efc..c99a003bb0 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -426,7 +426,6 @@ static int imx_ocotp_probe(struct device_d *dev)
cdev->priv = priv;
cdev->size = 192;
cdev->name = "imx-ocotp";
- cdev->device_node = dev->device_node;
ret = devfs_create(cdev);
diff --git a/arch/arm/mach-socfpga/generic.c b/arch/arm/mach-socfpga/generic.c
index 2d4afd0a7a..906bc63330 100644
--- a/arch/arm/mach-socfpga/generic.c
+++ b/arch/arm/mach-socfpga/generic.c
@@ -103,41 +103,3 @@ static int socfpga_init(void)
return 0;
}
core_initcall(socfpga_init);
-
-#if defined(CONFIG_ENV_HANDLING)
-#define ENV_PATH "/boot/barebox.env"
-static int socfpga_env_init(void)
-{
- struct stat s;
- char *diskdev, *partname;
- int ret;
-
- diskdev = "mmc0";
-
- device_detect_by_name(diskdev);
-
- partname = asprintf("/dev/%s.1", diskdev);
-
- ret = stat(partname, &s);
-
- if (ret) {
- pr_err("Failed to load environment: no device '%s'\n", diskdev);
- goto out_free;
- }
-
- mkdir("/boot", 0666);
- ret = mount(partname, "fat", "/boot", NULL);
- if (ret) {
- pr_err("Failed to load environment: mount %s failed (%d)\n", partname, ret);
- goto out_free;
- }
-
- pr_debug("Loading default env from %s on device %s\n", ENV_PATH, diskdev);
- default_environment_path_set(ENV_PATH);
-
-out_free:
- free(partname);
- return 0;
-}
-late_initcall(socfpga_env_init);
-#endif
diff --git a/commands/devinfo.c b/commands/devinfo.c
index 3c9d6a6b9d..c78efcbed4 100644
--- a/commands/devinfo.c
+++ b/commands/devinfo.c
@@ -21,7 +21,7 @@
static int do_devinfo_subtree(struct device_d *dev, int depth)
{
struct device_d *child;
- struct cdev *cdev;
+ struct cdev *cdev, *cdevl;
int i;
for (i = 0; i < depth; i++)
@@ -33,11 +33,14 @@ static int do_devinfo_subtree(struct device_d *dev, int depth)
list_for_each_entry(cdev, &dev->cdevs, devices_list) {
for (i = 0; i < depth + 1; i++)
printf(" ");
- printf("`-- 0x%08llx-0x%08llx (%10s): /dev/%s\n",
+ printf("`-- 0x%08llx-0x%08llx (%10s): /dev/%s",
cdev->offset,
cdev->offset + cdev->size - 1,
size_human_readable(cdev->size),
cdev->name);
+ list_for_each_entry(cdevl, &cdev->links, link_entry)
+ printf(", %s", cdevl->name);
+ printf("\n");
}
} else {
printf("\n");
diff --git a/common/partitions.c b/common/partitions.c
index 4f50bfeff1..82ec508e64 100644
--- a/common/partitions.c
+++ b/common/partitions.c
@@ -71,20 +71,14 @@ static int register_one_partition(struct block_device *blk,
if (!part->name[0])
return 0;
- partition_name = asprintf("%s.%s", blk->cdev.name, part->name);
- if (!partition_name)
- return -ENOMEM;
-
- dev_dbg(blk->dev, "Registering partition %s on drive %s\n",
- partition_name, blk->cdev.name);
- cdev = devfs_add_partition(blk->cdev.name,
- start, size, 0, partition_name);
-
- if (IS_ERR(cdev))
- dev_warn(blk->dev, "Registering partition %s on drive %s failed\n",
- partition_name, blk->cdev.name);
+ partition_name = xasprintf("%s.%s", blk->cdev.name, part->name);
+ ret = devfs_create_link(cdev, partition_name);
+ if (ret)
+ dev_warn(blk->dev, "Failed to create link from %s to %s\n",
+ partition_name, blk->cdev.name);
+ free(partition_name);
- ret = 0;
+ return 0;
out:
free(partition_name);
return ret;
diff --git a/common/partitions/Kconfig b/common/partitions/Kconfig
index 90238ad382..be9405a649 100644
--- a/common/partitions/Kconfig
+++ b/common/partitions/Kconfig
@@ -16,6 +16,7 @@ config PARTITION_DISK_DOS
config PARTITION_DISK_EFI
depends on PARTITION_DISK
select CRC32
+ select PRINTF_UUID
bool "EFI: GPT partition support"
help
Add support to handle partitions in GUID Partition Table style.
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 61abf00050..a9945dd9eb 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -457,6 +457,7 @@ static void efi_partition(void *buf, struct block_device *blk,
pentry->size = le64_to_cpu(ptes[i].ending_lba) - pentry->first_sec;
pentry->size++;
part_set_efi_name(&ptes[i], pentry->name);
+ snprintf(pentry->partuuid, sizeof(pentry->partuuid), "%pUl", &ptes[i].unique_partition_guid);
pd->used_entries++;
}
diff --git a/common/state.c b/common/state.c
index ec72dbd9a0..d1fa47ffa3 100644
--- a/common/state.c
+++ b/common/state.c
@@ -66,6 +66,7 @@ enum state_variable_type {
STATE_TYPE_ENUM,
STATE_TYPE_U8,
STATE_TYPE_U32,
+ STATE_TYPE_S32,
STATE_TYPE_MAC,
STATE_TYPE_STRING,
};
@@ -209,8 +210,8 @@ static struct state_variable *state_uint8_create(struct state *state,
return &su32->var;
}
-static struct state_variable *state_uint32_create(struct state *state,
- const char *name, struct device_node *node)
+static struct state_variable *state_int32_create(struct state *state,
+ const char *name, struct device_node *node, const char *format)
{
struct state_uint32 *su32;
struct param_d *param;
@@ -218,7 +219,7 @@ static struct state_variable *state_uint32_create(struct state *state,
su32 = xzalloc(sizeof(*su32));
param = dev_add_param_int(&state->dev, name, state_set_dirty,
- NULL, &su32->value, "%u", state);
+ NULL, &su32->value, format, state);
if (IS_ERR(param)) {
free(su32);
return ERR_CAST(param);
@@ -231,6 +232,18 @@ static struct state_variable *state_uint32_create(struct state *state,
return &su32->var;
}
+static struct state_variable *state_uint32_create(struct state *state,
+ const char *name, struct device_node *node)
+{
+ return state_int32_create(state, name, node, "%u");
+}
+
+static struct state_variable *state_sint32_create(struct state *state,
+ const char *name, struct device_node *node)
+{
+ return state_int32_create(state, name, node, "%d");
+}
+
/*
* enum32
*/
@@ -605,6 +618,12 @@ static struct variable_type types[] = {
.export = state_string_export,
.import = state_string_import,
.create = state_string_create,
+ }, {
+ .type = STATE_TYPE_S32,
+ .type_name = "int32",
+ .export = state_uint32_export,
+ .import = state_uint32_import,
+ .create = state_sint32_create,
},
};
diff --git a/drivers/input/gpio_keys.c b/drivers/input/gpio_keys.c
index d017594662..5b03fd76cb 100644
--- a/drivers/input/gpio_keys.c
+++ b/drivers/input/gpio_keys.c
@@ -21,6 +21,9 @@ struct gpio_key {
int active_low;
int previous_state;
+
+ int debounce_interval;
+ u64 debounce_start;
};
struct gpio_keys {
@@ -60,11 +63,17 @@ static void gpio_key_poller(struct poller_struct *poller)
gb = &gk->buttons[i];
val = gpio_get_value(gb->gpio);
- if (val != gb->previous_state && val != gb->active_low) {
- kfifo_put(gk->recv_fifo, (u_char*)&gb->code, sizeof(int));
- debug("pressed gpio(%d) as %d\n", gb->gpio, gb->code);
+ if (!is_timeout(gb->debounce_start, gb->debounce_interval * MSECOND))
+ continue;
+
+ if (val != gb->previous_state) {
+ gb->debounce_start = get_time_ns();
+ if (val != gb->active_low) {
+ kfifo_put(gk->recv_fifo, (u_char*)&gb->code, sizeof(int));
+ debug("pressed gpio(%d) as %d\n", gb->gpio, gb->code);
+ }
+ gb->previous_state = val;
}
- gb->previous_state = val;
}
}
@@ -111,6 +120,7 @@ static int gpio_keys_probe_pdata(struct gpio_keys *gk, struct device_d *dev)
gk->buttons[i].gpio = pdata->buttons[i].gpio;
gk->buttons[i].code = pdata->buttons[i].code;
gk->buttons[i].active_low = pdata->buttons[i].active_low;
+ gk->buttons[i].debounce_interval = 20;
}
return 0;
@@ -142,6 +152,11 @@ static int gpio_keys_probe_dt(struct gpio_keys *gk, struct device_d *dev)
if (ret)
return ret;
+ gk->buttons[i].debounce_interval = 20;
+
+ of_property_read_u32(npkey, "debounce-interval",
+ &gk->buttons[i].debounce_interval);
+
gk->buttons[i].code = keycode;
i++;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 90475cfbca..d0a62bda91 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -43,3 +43,10 @@ config OF_BAREBOX_DRIVERS
support for this feature. This currently allows to configure the
environment path from devicetree and to partition devices. See
Documentation/devicetree/bindings/barebox/ for more information.
+
+config OF_BAREBOX_ENV_IN_FS
+ depends on OF_BAREBOX_DRIVERS
+ bool "Allow environment to come from file"
+ help
+ Allow the devie tree configuration of the barebox environment path
+ to specify a file in filesystem, which will be mounted.
diff --git a/drivers/of/barebox.c b/drivers/of/barebox.c
index 1b3078eb47..125feef2cc 100644
--- a/drivers/of/barebox.c
+++ b/drivers/of/barebox.c
@@ -24,7 +24,46 @@
#include <malloc.h>
#include <partition.h>
#include <envfs.h>
-#include <linux/mtd/mtd.h>
+#include <fs.h>
+
+#define ENV_MNT_DIR "/boot" /* If env on filesystem, where to mount */
+
+/* If dev describes a file on a fs, mount the fs and change devpath to
+ * point to the file's path. Otherwise leave devpath alone. Does
+ * nothing in env in a file support isn't enabled. */
+static int environment_check_mount(struct device_d *dev, char **devpath)
+{
+ const char *filepath;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_OF_BAREBOX_ENV_IN_FS))
+ return 0;
+
+ ret = of_property_read_string(dev->device_node, "file-path", &filepath);
+ if (ret == -EINVAL) {
+ /* No file-path so just use device-path */
+ return 0;
+ } else if (ret) {
+ /* file-path property exists, but has error */
+ dev_err(dev, "Problem with file-path property\n");
+ return ret;
+ }
+
+ /* Get device env is on and mount it */
+ mkdir(ENV_MNT_DIR, 0777);
+ ret = mount(*devpath, "fat", ENV_MNT_DIR, NULL);
+ if (ret) {
+ dev_err(dev, "Failed to load environment: mount %s failed (%d)\n",
+ *devpath, ret);
+ return ret;
+ }
+
+ /* Set env to be in a file on the now mounted device */
+ dev_dbg(dev, "Loading default env from %s on device %s\n",
+ filepath, *devpath);
+ *devpath = asprintf("%s/%s", ENV_MNT_DIR, filepath);
+ return 0;
+}
static int environment_probe(struct device_d *dev)
{
@@ -35,8 +74,12 @@ static int environment_probe(struct device_d *dev)
if (ret)
return ret;
- dev_info(dev, "setting default environment path to %s\n", path);
+ /* Do we need to mount a fs and find env there? */
+ ret = environment_check_mount(dev, &path);
+ if (ret)
+ return ret;
+ dev_dbg(dev, "Setting default environment path to %s\n", path);
default_environment_path_set(path);
return 0;
diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c
index 9016147db8..ed620f1755 100644
--- a/drivers/of/of_path.c
+++ b/drivers/of/of_path.c
@@ -23,16 +23,6 @@
#include <linux/mtd/mtd.h>
-struct of_path {
- struct cdev *cdev;
- struct device_d *dev;
-};
-
-struct of_path_type {
- const char *name;
- int (*parse)(struct of_path *op, const char *str);
-};
-
struct device_d *of_find_device_by_node_path(const char *path)
{
struct device_d *dev;
@@ -48,65 +38,6 @@ struct device_d *of_find_device_by_node_path(const char *path)
}
/**
- * of_path_type_partname - find a partition based on physical device and
- * partition name
- * @op: of_path context
- * @name: the partition name to find
- */
-static int of_path_type_partname(struct of_path *op, const char *name)
-{
- if (!op->dev)
- return -EINVAL;
-
- op->cdev = device_find_partition(op->dev, name);
- if (op->cdev) {
- pr_debug("%s: found part '%s'\n", __func__, name);
- return 0;
- } else {
- pr_debug("%s: cannot find part '%s'\n", __func__, name);
- return -ENODEV;
- }
-}
-
-static struct of_path_type of_path_types[] = {
- {
- .name = "partname",
- .parse = of_path_type_partname,
- },
-};
-
-static int of_path_parse_one(struct of_path *op, const char *str)
-{
- int i, ret;
- char *name, *desc;
-
- pr_debug("parsing: %s\n", str);
-
- name = xstrdup(str);
- desc = strchr(name, ':');
- if (!desc) {
- free(name);
- return -EINVAL;
- }
-
- *desc = 0;
- desc++;
-
- for (i = 0; i < ARRAY_SIZE(of_path_types); i++) {
- if (!strcmp(of_path_types[i].name, name)) {
- ret = of_path_types[i].parse(op, desc);
- goto out;
- }
- }
-
- ret = -EINVAL;
-out:
- free(name);
-
- return ret;
-}
-
-/**
* __of_find_path
*
* @node: The node to find the cdev for, can be the device or a
@@ -119,36 +50,32 @@ out:
*/
static int __of_find_path(struct device_node *node, const char *part, char **outpath, unsigned flags)
{
- struct of_path op;
+ struct device_d *dev;
+ struct cdev *cdev;
bool add_bb = false;
- int ret;
- op.dev = of_find_device_by_node_path(node->full_name);
- if (!op.dev) {
- op.dev = of_find_device_by_node_path(node->parent->full_name);
- if (!op.dev)
+ dev = of_find_device_by_node_path(node->full_name);
+ if (!dev) {
+ dev = of_find_device_by_node_path(node->parent->full_name);
+ if (!dev)
return -ENODEV;
}
- device_detect(op.dev);
+ device_detect(dev);
- if (part) {
- /* Find a partition inside op.dev */
- ret = of_path_parse_one(&op, part);
- if (ret)
- return ret;
- } else {
- /* node points directly to device */
- op.cdev = cdev_by_device_node(node);
- if (!op.cdev)
- return -ENOENT;
- }
+ if (part)
+ cdev = device_find_partition(dev, part);
+ else
+ cdev = cdev_by_device_node(node);
- if ((flags & OF_FIND_PATH_FLAGS_BB) && op.cdev->mtd &&
- mtd_can_have_bb(op.cdev->mtd))
+ if (!cdev)
+ return -ENOENT;
+
+ if ((flags & OF_FIND_PATH_FLAGS_BB) && cdev->mtd &&
+ mtd_can_have_bb(cdev->mtd))
add_bb = true;
- *outpath = asprintf("/dev/%s%s", op.cdev->name, add_bb ? ".bb" : "");
+ *outpath = asprintf("/dev/%s%s", cdev->name, add_bb ? ".bb" : "");
return 0;
}
@@ -198,8 +125,8 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath,
{
struct device_node *rnode;
const char *path;
- const char *part;
- int ret;
+ const char *part = NULL;
+ const char partnamestr[] = "partname:";
path = of_get_property(node, propname, NULL);
if (!path)
@@ -209,9 +136,15 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath,
if (!rnode)
return -ENODEV;
- ret = of_property_read_string_index(node, propname, 1, &part);
- if (ret)
- part = NULL;
+ of_property_read_string_index(node, propname, 1, &part);
+ if (part) {
+ if (!strncmp(part, partnamestr, sizeof(partnamestr) - 1)) {
+ part += sizeof(partnamestr) - 1;
+ } else {
+ pr_err("Invalid device-path: %s\n", part);
+ return -EINVAL;
+ }
+ }
return __of_find_path(rnode, part, outpath, flags);
}
diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c
index eaa5f0ef58..d32bd2b4ce 100644
--- a/drivers/pci/pci-imx6.c
+++ b/drivers/pci/pci-imx6.c
@@ -13,6 +13,7 @@
#include <common.h>
#include <clock.h>
+#include <abort.h>
#include <malloc.h>
#include <io.h>
#include <init.h>
@@ -51,6 +52,8 @@ struct imx6_pcie {
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
+#define PCIE_RC_LCSR 0x80
+
/* PCIe Port Logic registers (memory-mapped) */
#define PL_OFFSET 0x700
#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
@@ -235,7 +238,10 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
val = readl(pp->dbi_base + PCIE_PL_PFLR);
val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
val |= PCIE_PL_PFLR_FORCE_LINK;
+
+ data_abort_mask();
writel(val, pp->dbi_base + PCIE_PL_PFLR);
+ data_abort_unmask();
gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2;
writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
@@ -360,13 +366,29 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp)
}
}
+static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp)
+{
+ uint32_t tmp;
+ uint64_t start = get_time_ns();
+
+ while (!is_timeout(start, SECOND)) {
+ tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+ /* Test if the speed change finished. */
+ if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
+ return 0;
+ }
+
+ dev_err(pp->dev, "Speed change timeout\n");
+ return -EINVAL;
+}
+
+
static int imx6_pcie_start_link(struct pcie_port *pp)
{
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
uint32_t tmp;
int ret;
u32 gpr12;
- u64 start;
/*
* Force Gen1 operation when starting the link. In case the link is
@@ -401,28 +423,22 @@ static int imx6_pcie_start_link(struct pcie_port *pp)
tmp |= PORT_LOGIC_SPEED_CHANGE;
writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
- start = get_time_ns();
- while (!is_timeout(start, SECOND)) {
- tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
- /* Test if the speed change finished. */
- if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
- break;
+ ret = imx6_pcie_wait_for_speed_change(pp);
+ if (ret) {
+ dev_err(pp->dev, "Failed to bring link up!\n");
+ return ret;
}
/* Make sure link training is finished as well! */
- if (tmp & PORT_LOGIC_SPEED_CHANGE)
- ret = -EINVAL;
- else
- ret = imx6_pcie_wait_for_link(pp);
-
+ ret = imx6_pcie_wait_for_link(pp);
if (ret) {
dev_err(pp->dev, "Failed to bring link up!\n");
- } else {
- tmp = readl(pp->dbi_base + 0x80);
- dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+ return ret;
}
- return ret;
+ tmp = readl(pp->dbi_base + PCIE_RC_LCSR);
+ dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+ return 0;
}
static void imx6_pcie_host_init(struct pcie_port *pp)
@@ -592,9 +608,35 @@ static int __init imx6_pcie_probe(struct device_d *dev)
if (ret < 0)
return ret;
+ dev->priv = imx6_pcie;
+
return 0;
}
+static void imx6_pcie_remove(struct device_d *dev)
+{
+ struct imx6_pcie *imx6_pcie = dev->priv;
+ u32 val;
+
+ val = readl(imx6_pcie->pp.dbi_base + PCIE_PL_PFLR);
+ val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
+ val |= PCIE_PL_PFLR_FORCE_LINK;
+ data_abort_mask();
+ writel(val, imx6_pcie->pp.dbi_base + PCIE_PL_PFLR);
+ data_abort_unmask();
+
+ val = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+ val &= ~IMX6Q_GPR12_PCIE_CTL_2;
+ writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+
+ val = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+ val |= IMX6Q_GPR1_PCIE_TEST_PD;
+ writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+
+ val &= ~IMX6Q_GPR1_PCIE_REF_CLK_EN;
+ writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+}
+
static struct of_device_id imx6_pcie_of_match[] = {
{ .compatible = "fsl,imx6q-pcie", },
{},
@@ -604,6 +646,7 @@ static struct driver_d imx6_pcie_driver = {
.name = "imx6-pcie",
.of_compatible = DRV_OF_COMPAT(imx6_pcie_of_match),
.probe = imx6_pcie_probe,
+ .remove = imx6_pcie_remove,
};
device_platform_driver(imx6_pcie_driver);
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index ae307183bc..a1c36cf644 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -242,7 +242,8 @@ static int imx_chipidea_probe(struct device_d *dev)
ci->vbus = regulator_get(dev, "vbus");
- regulator_enable(ci->vbus);
+ if (!IS_ERR(ci->vbus))
+ regulator_enable(ci->vbus);
base = dev_request_mem_region(dev, 0);
if (IS_ERR(base))
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 2541ea36e6..88a7e3a1d6 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -46,7 +46,18 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
}
#endif
-struct cdev *cdev_by_name(const char *filename)
+struct cdev *cdev_readlink(struct cdev *cdev)
+{
+ if (cdev->link)
+ cdev = cdev->link;
+
+ /* links to links are not allowed */
+ BUG_ON(cdev->link);
+
+ return cdev;
+}
+
+struct cdev *lcdev_by_name(const char *filename)
{
struct cdev *cdev;
@@ -57,6 +68,17 @@ struct cdev *cdev_by_name(const char *filename)
return NULL;
}
+struct cdev *cdev_by_name(const char *filename)
+{
+ struct cdev *cdev;
+
+ cdev = lcdev_by_name(filename);
+ if (!cdev)
+ return NULL;
+
+ return cdev_readlink(cdev);
+}
+
struct cdev *cdev_by_device_node(struct device_node *node)
{
struct cdev *cdev;
@@ -65,7 +87,7 @@ struct cdev *cdev_by_device_node(struct device_node *node)
if (!cdev->device_node)
continue;
if (cdev->device_node == node)
- return cdev;
+ return cdev_readlink(cdev);
}
return NULL;
}
@@ -111,14 +133,6 @@ int cdev_find_free_index(const char *basename)
return -EBUSY; /* all indexes are used */
}
-int cdev_do_open(struct cdev *cdev, unsigned long flags)
-{
- if (cdev->ops->open)
- return cdev->ops->open(cdev, flags);
-
- return 0;
-}
-
struct cdev *cdev_open(const char *name, unsigned long flags)
{
struct cdev *cdev;
@@ -131,9 +145,11 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
if (!cdev)
return NULL;
- ret = cdev_do_open(cdev, flags);
- if (ret)
- return NULL;
+ if (cdev->ops->open) {
+ ret = cdev->ops->open(cdev, flags);
+ if (ret)
+ return NULL;
+ }
return cdev;
}
@@ -259,22 +275,59 @@ int devfs_create(struct cdev *new)
if (cdev)
return -EEXIST;
+ INIT_LIST_HEAD(&new->links);
+
list_add_tail(&new->list, &cdev_list);
- if (new->dev)
+ if (new->dev) {
list_add_tail(&new->devices_list, &new->dev->cdevs);
+ if (!new->device_node)
+ new->device_node = new->dev->device_node;
+ }
+
+ return 0;
+}
+
+int devfs_create_link(struct cdev *cdev, const char *name)
+{
+ struct cdev *new;
+
+ if (cdev_by_name(name))
+ return -EEXIST;
+
+ /*
+ * Create a link to the real cdev instead of creating
+ * a link to a link.
+ */
+ cdev = cdev_readlink(cdev);
+
+ new = xzalloc(sizeof(*new));
+ new->name = xstrdup(name);
+ new->link = cdev;
+ INIT_LIST_HEAD(&new->links);
+ list_add_tail(&new->list, &cdev_list);
+ list_add_tail(&new->link_entry, &cdev->links);
return 0;
}
int devfs_remove(struct cdev *cdev)
{
+ struct cdev *c, *tmp;
+
if (cdev->open)
return -EBUSY;
list_del(&cdev->list);
+
if (cdev->dev)
list_del(&cdev->devices_list);
+ list_for_each_entry_safe(c, tmp, &cdev->links, link_entry)
+ devfs_remove(c);
+
+ if (cdev->link)
+ free(cdev);
+
return 0;
}
diff --git a/fs/devfs.c b/fs/devfs.c
index 5c96682f96..0b8d4fd246 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -212,12 +212,18 @@ static int devfs_stat(struct device_d *_dev, const char *filename, struct stat *
{
struct cdev *cdev;
- cdev = cdev_by_name(filename + 1);
+ cdev = lcdev_by_name(filename + 1);
if (!cdev)
return -ENOENT;
s->st_mode = S_IFCHR;
s->st_size = cdev->size;
+
+ if (cdev->link)
+ s->st_mode |= S_IFLNK;
+
+ cdev = cdev_readlink(cdev);
+
if (cdev->ops->write)
s->st_mode |= S_IWUSR;
if (cdev->ops->read)
@@ -242,6 +248,24 @@ static void devfs_delete(struct device_d *dev)
{
}
+static int devfs_readlink(struct device_d *dev, const char *pathname,
+ char *buf, size_t bufsz)
+{
+ struct cdev *cdev;
+
+ cdev = cdev_by_name(pathname + 1);
+ if (!cdev)
+ return -ENOENT;
+
+ while (cdev->link)
+ cdev = cdev->link;
+
+ bufsz = min(bufsz, strlen(cdev->name));
+ memcpy(buf, cdev->name, bufsz);
+
+ return 0;
+}
+
static struct fs_driver_d devfs_driver = {
.read = devfs_read,
.write = devfs_write,
@@ -258,6 +282,7 @@ static struct fs_driver_d devfs_driver = {
.erase = devfs_erase,
.protect = devfs_protect,
.memmap = devfs_memmap,
+ .readlink = devfs_readlink,
.flags = FS_DRIVER_NO_DEV,
.drv = {
.probe = devfs_probe,
diff --git a/fs/fs.c b/fs/fs.c
index 4983fc7ec1..ace72f7d54 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -346,6 +346,9 @@ static void automount_mount(const char *path, int instat)
in_automount++;
+ if (fs_dev_root != get_fsdevice_by_path(path))
+ goto out;
+
list_for_each_entry(am, &automount_list, list) {
int len_path = strlen(path);
int len_am_path = strlen(am->path);
@@ -377,12 +380,10 @@ static void automount_mount(const char *path, int instat)
if (ret)
printf("running automount command '%s' failed\n",
am->cmd);
- else
- automount_remove(am->path);
break;
}
-
+out:
in_automount--;
}
diff --git a/include/bootstrap.h b/include/bootstrap.h
index 9863ff425e..d3ee6be47c 100644
--- a/include/bootstrap.h
+++ b/include/bootstrap.h
@@ -15,10 +15,10 @@ typedef void (*kernel_entry_func)(int zero, int arch, void *params);
void bootstrap_boot(kernel_entry_func func, bool barebox);
#ifdef CONFIG_BOOTSTRAP_DEVFS
-void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
+void* bootstrap_read_devfs(const char *devname, bool use_bb, int offset,
int default_size, int max_size);
#else
-static inline void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
+static inline void* bootstrap_read_devfs(const char *devname, bool use_bb, int offset,
int default_size, int max_size)
{
return NULL;
@@ -26,9 +26,9 @@ static inline void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
#endif
#ifdef CONFIG_BOOTSTRAP_DISK
-void* bootstrap_read_disk(char *devname, char *fstype);
+void* bootstrap_read_disk(const char *devname, const char *fstype);
#else
-static inline void* bootstrap_read_disk(char *devname, char *fstype)
+static inline void* bootstrap_read_disk(const char *devname, const char *fstype)
{
return NULL;
}
diff --git a/include/driver.h b/include/driver.h
index 046dd9079d..31c673452f 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -450,13 +450,18 @@ struct cdev {
int open;
struct mtd_info *mtd;
u8 dos_partition_type;
+ struct cdev *link;
+ struct list_head link_entry, links;
};
int devfs_create(struct cdev *);
+int devfs_create_link(struct cdev *, const char *name);
int devfs_remove(struct cdev *);
int cdev_find_free_index(const char *);
struct cdev *device_find_partition(struct device_d *dev, const char *name);
struct cdev *cdev_by_name(const char *filename);
+struct cdev *lcdev_by_name(const char *filename);
+struct cdev *cdev_readlink(struct cdev *cdev);
struct cdev *cdev_by_device_node(struct device_node *node);
struct cdev *cdev_open(const char *name, unsigned long flags);
int cdev_do_open(struct cdev *, unsigned long flags);
diff --git a/include/of.h b/include/of.h
index e60fe89825..75cc3c11c1 100644
--- a/include/of.h
+++ b/include/of.h
@@ -641,9 +641,13 @@ static inline struct device_node *of_find_node_by_path_or_alias(
#define for_each_node_by_name_from(dn, root, name) \
for (dn = of_find_node_by_name(root, name); dn; \
dn = of_find_node_by_name(dn, name))
-#define for_each_compatible_node(dn, type, compatible) \
- for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+/* Iterate over compatible nodes starting from given root */
+#define for_each_compatible_node_from(dn, root, type, compatible) \
+ for (dn = of_find_compatible_node(root, type, compatible); dn; \
dn = of_find_compatible_node(dn, type, compatible))
+/* Iterate over compatible nodes in default device tree */
+#define for_each_compatible_node(dn, type, compatible) \
+ for_each_compatible_node_from(dn, NULL, type, compatible)
static inline struct device_node *of_find_matching_node(
struct device_node *from,
const struct of_device_id *matches)
@@ -732,6 +736,17 @@ static inline int of_property_read_u32(const struct device_node *np,
s; \
s = of_prop_next_string(prop, s))
+/*
+ * struct device_node *n;
+ *
+ * of_property_for_each_phandle(np, root, "propname", n)
+ * printk("phandle points to: %s\n", n->full_name);
+ */
+#define of_property_for_each_phandle(np, root, propname, n) \
+ for (int _i = 0; \
+ (n = of_parse_phandle_from(np, root, propname, _i));\
+ _i++)
+
static inline int of_property_write_u8(struct device_node *np,
const char *propname, u8 value)
{
diff --git a/lib/bootstrap/devfs.c b/lib/bootstrap/devfs.c
index 5a64477eed..6a3dd76cdd 100644
--- a/lib/bootstrap/devfs.c
+++ b/lib/bootstrap/devfs.c
@@ -80,7 +80,7 @@ static unsigned int get_image_size(void *head)
}
#endif
-void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
+void* bootstrap_read_devfs(const char *devname, bool use_bb, int offset,
int default_size, int max_size)
{
int ret;
diff --git a/lib/bootstrap/disk.c b/lib/bootstrap/disk.c
index ebf9ee5a98..a55d5d77f4 100644
--- a/lib/bootstrap/disk.c
+++ b/lib/bootstrap/disk.c
@@ -14,12 +14,12 @@
#include <libfile.h>
#include <bootstrap.h>
-void* bootstrap_read_disk(char *dev, char *fstype)
+void* bootstrap_read_disk(const char *dev, const char *fstype)
{
int ret;
void *buf;
int len;
- char *path = "/";
+ const char *path = "/";
ret = mount(dev, fstype, path, NULL);
if (ret) {
diff --git a/lib/readline.c b/lib/readline.c
index c007e10f50..cac967005f 100644
--- a/lib/readline.c
+++ b/lib/readline.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <readkey.h>
#include <init.h>
+#include <libbb.h>
#include <xfuncs.h>
#include <complete.h>
#include <linux/ctype.h>
@@ -150,7 +151,7 @@ static void cread_add_char(char ichar, int insert, unsigned long *num,
/* room ??? */
if (insert || *num == *eol_num) {
- if (*eol_num > len - 1) {
+ if (*eol_num > len - 2) {
getcmd_cbeep();
return;
}
@@ -321,7 +322,7 @@ int readline(const char *prompt, char *buf, int len)
ERASE_TO_EOL();
/* copy new line into place and display */
- strcpy(buf, hline);
+ safe_strncpy(buf, hline, len);
eol_num = strlen(buf);
REFRESH_TO_EOL();
continue;