Merge branch 'for-next/misc'
This commit is contained in:
commit
b9a2512aaa
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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``:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
/ {
|
||||
chosen {
|
||||
environment@0 {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &mmc, "partname:1";
|
||||
file-path = "barebox.env";
|
||||
};
|
||||
};
|
||||
|
||||
aliases {
|
||||
mmc0 = &mmc;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
ret = 0;
|
||||
return 0;
|
||||
out:
|
||||
free(partition_name);
|
||||
return ret;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -47,65 +37,6 @@ struct device_d *of_find_device_by_node_path(const char *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
27
fs/devfs.c
27
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,
|
||||
|
|
7
fs/fs.c
7
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--;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
19
include/of.h
19
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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue