9
0
Fork 0

Merge branch 'for-next/misc'

This commit is contained in:
Sascha Hauer 2016-01-11 13:11:06 +01:00
commit b9a2512aaa
28 changed files with 354 additions and 210 deletions

View File

@ -6,7 +6,10 @@ This driver provides an environment for barebox from the devicetree.
Required properties: Required properties:
* ``compatible``: should be ``barebox,environment`` * ``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 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 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 be the label for MTD partitions, the number for DOS
partitions (beginning with 0) or the name for GPT partitions. 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:: Example::
environment@0 { environment@0 {
compatible = "barebox,environment"; compatible = "barebox,environment";
device-path = &flash, "partname:barebox-environment"; device-path = &flash, "partname:barebox-environment";
}; };
environment@1 {
compatible = "barebox,environment";
device-path = &mmc, "partname:1";
file-path = "barebox.env";
};

View File

@ -55,8 +55,8 @@ Required properties:
``#size-cells = <1>``. Defines the ``offset`` and ``size`` of the ``#size-cells = <1>``. Defines the ``offset`` and ``size`` of the
variable in the ``raw`` backend. ``size`` must fit the node variable in the ``raw`` backend. ``size`` must fit the node
``type``. Variables are not allowed to overlap. ``type``. Variables are not allowed to overlap.
* ``type``: Should be ``uint8``, ``uint32``, ``enum32``, ``mac`` or * ``type``: Should be ``uint8``, ``uint32``, ``int32``. ``enum32``, ``mac``
``string`` for the type of the variable or ``string`` for the type of the variable
* ``names``: For ``enum32`` values only, this specifies the values * ``names``: For ``enum32`` values only, this specifies the values
possible for ``enum32``. possible for ``enum32``.
@ -93,6 +93,7 @@ Variable Types
* ``uint8``: * ``uint8``:
* ``uint32``: * ``uint32``:
* ``int32``:
* ``enum32``: The ``default`` value is an integer representing an * ``enum32``: The ``default`` value is an integer representing an
offset into the names array. offset into the names array.
* ``mac``: * ``mac``:

View File

@ -235,7 +235,7 @@ static int cm_cogent_fixup(struct device_node *root, void *unused)
int ret; int ret;
struct device_node *node; 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 = struct device_node *slotnode =
of_get_child_by_name(node, "slot"); of_get_child_by_name(node, "slot");
if (!slotnode) if (!slotnode)

View File

@ -35,13 +35,13 @@ static int hb_fixup(struct device_node *root, void *unused)
__be32 latency; __be32 latency;
if (!(reg & HB_PWRDOM_STAT_SATA)) { 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", of_set_property(node, "status", "disabled",
sizeof("disabled"), 1); sizeof("disabled"), 1);
} }
if (!(reg & HB_PWRDOM_STAT_EMMC)) { 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", of_set_property(node, "status", "disabled",
sizeof("disabled"), 1); sizeof("disabled"), 1);
} }

View File

@ -67,6 +67,7 @@ CONFIG_NET=y
CONFIG_NET_NETCONSOLE=y CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y CONFIG_NET_RESOLV=y
CONFIG_OF_BAREBOX_DRIVERS=y CONFIG_OF_BAREBOX_DRIVERS=y
CONFIG_OF_BAREBOX_ENV_IN_FS=y
CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_NET_DESIGNWARE=y CONFIG_DRIVER_NET_DESIGNWARE=y
CONFIG_MCI=y CONFIG_MCI=y

View File

@ -1,4 +1,12 @@
/ { / {
chosen {
environment@0 {
compatible = "barebox,environment";
device-path = &mmc, "partname:1";
file-path = "barebox.env";
};
};
aliases { aliases {
mmc0 = &mmc; mmc0 = &mmc;
}; };

View File

@ -426,7 +426,6 @@ static int imx_ocotp_probe(struct device_d *dev)
cdev->priv = priv; cdev->priv = priv;
cdev->size = 192; cdev->size = 192;
cdev->name = "imx-ocotp"; cdev->name = "imx-ocotp";
cdev->device_node = dev->device_node;
ret = devfs_create(cdev); ret = devfs_create(cdev);

View File

@ -103,41 +103,3 @@ static int socfpga_init(void)
return 0; return 0;
} }
core_initcall(socfpga_init); 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

View File

@ -21,7 +21,7 @@
static int do_devinfo_subtree(struct device_d *dev, int depth) static int do_devinfo_subtree(struct device_d *dev, int depth)
{ {
struct device_d *child; struct device_d *child;
struct cdev *cdev; struct cdev *cdev, *cdevl;
int i; int i;
for (i = 0; i < depth; 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) { list_for_each_entry(cdev, &dev->cdevs, devices_list) {
for (i = 0; i < depth + 1; i++) for (i = 0; i < depth + 1; i++)
printf(" "); printf(" ");
printf("`-- 0x%08llx-0x%08llx (%10s): /dev/%s\n", printf("`-- 0x%08llx-0x%08llx (%10s): /dev/%s",
cdev->offset, cdev->offset,
cdev->offset + cdev->size - 1, cdev->offset + cdev->size - 1,
size_human_readable(cdev->size), size_human_readable(cdev->size),
cdev->name); cdev->name);
list_for_each_entry(cdevl, &cdev->links, link_entry)
printf(", %s", cdevl->name);
printf("\n");
} }
} else { } else {
printf("\n"); printf("\n");

View File

@ -71,20 +71,14 @@ static int register_one_partition(struct block_device *blk,
if (!part->name[0]) if (!part->name[0])
return 0; return 0;
partition_name = asprintf("%s.%s", blk->cdev.name, part->name); partition_name = xasprintf("%s.%s", blk->cdev.name, part->name);
if (!partition_name) ret = devfs_create_link(cdev, partition_name);
return -ENOMEM; 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", return 0;
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;
out: out:
free(partition_name); free(partition_name);
return ret; return ret;

View File

@ -16,6 +16,7 @@ config PARTITION_DISK_DOS
config PARTITION_DISK_EFI config PARTITION_DISK_EFI
depends on PARTITION_DISK depends on PARTITION_DISK
select CRC32 select CRC32
select PRINTF_UUID
bool "EFI: GPT partition support" bool "EFI: GPT partition support"
help help
Add support to handle partitions in GUID Partition Table style. Add support to handle partitions in GUID Partition Table style.

View File

@ -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 = le64_to_cpu(ptes[i].ending_lba) - pentry->first_sec;
pentry->size++; pentry->size++;
part_set_efi_name(&ptes[i], pentry->name); part_set_efi_name(&ptes[i], pentry->name);
snprintf(pentry->partuuid, sizeof(pentry->partuuid), "%pUl", &ptes[i].unique_partition_guid);
pd->used_entries++; pd->used_entries++;
} }

View File

@ -66,6 +66,7 @@ enum state_variable_type {
STATE_TYPE_ENUM, STATE_TYPE_ENUM,
STATE_TYPE_U8, STATE_TYPE_U8,
STATE_TYPE_U32, STATE_TYPE_U32,
STATE_TYPE_S32,
STATE_TYPE_MAC, STATE_TYPE_MAC,
STATE_TYPE_STRING, STATE_TYPE_STRING,
}; };
@ -209,8 +210,8 @@ static struct state_variable *state_uint8_create(struct state *state,
return &su32->var; return &su32->var;
} }
static struct state_variable *state_uint32_create(struct state *state, static struct state_variable *state_int32_create(struct state *state,
const char *name, struct device_node *node) const char *name, struct device_node *node, const char *format)
{ {
struct state_uint32 *su32; struct state_uint32 *su32;
struct param_d *param; struct param_d *param;
@ -218,7 +219,7 @@ static struct state_variable *state_uint32_create(struct state *state,
su32 = xzalloc(sizeof(*su32)); su32 = xzalloc(sizeof(*su32));
param = dev_add_param_int(&state->dev, name, state_set_dirty, 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)) { if (IS_ERR(param)) {
free(su32); free(su32);
return ERR_CAST(param); return ERR_CAST(param);
@ -231,6 +232,18 @@ static struct state_variable *state_uint32_create(struct state *state,
return &su32->var; 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 * enum32
*/ */
@ -605,6 +618,12 @@ static struct variable_type types[] = {
.export = state_string_export, .export = state_string_export,
.import = state_string_import, .import = state_string_import,
.create = state_string_create, .create = state_string_create,
}, {
.type = STATE_TYPE_S32,
.type_name = "int32",
.export = state_uint32_export,
.import = state_uint32_import,
.create = state_sint32_create,
}, },
}; };

View File

@ -21,6 +21,9 @@ struct gpio_key {
int active_low; int active_low;
int previous_state; int previous_state;
int debounce_interval;
u64 debounce_start;
}; };
struct gpio_keys { struct gpio_keys {
@ -60,11 +63,17 @@ static void gpio_key_poller(struct poller_struct *poller)
gb = &gk->buttons[i]; gb = &gk->buttons[i];
val = gpio_get_value(gb->gpio); val = gpio_get_value(gb->gpio);
if (val != gb->previous_state && val != gb->active_low) { if (!is_timeout(gb->debounce_start, gb->debounce_interval * MSECOND))
kfifo_put(gk->recv_fifo, (u_char*)&gb->code, sizeof(int)); continue;
debug("pressed gpio(%d) as %d\n", gb->gpio, gb->code);
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].gpio = pdata->buttons[i].gpio;
gk->buttons[i].code = pdata->buttons[i].code; gk->buttons[i].code = pdata->buttons[i].code;
gk->buttons[i].active_low = pdata->buttons[i].active_low; gk->buttons[i].active_low = pdata->buttons[i].active_low;
gk->buttons[i].debounce_interval = 20;
} }
return 0; return 0;
@ -142,6 +152,11 @@ static int gpio_keys_probe_dt(struct gpio_keys *gk, struct device_d *dev)
if (ret) if (ret)
return 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; gk->buttons[i].code = keycode;
i++; i++;

View File

@ -43,3 +43,10 @@ config OF_BAREBOX_DRIVERS
support for this feature. This currently allows to configure the support for this feature. This currently allows to configure the
environment path from devicetree and to partition devices. See environment path from devicetree and to partition devices. See
Documentation/devicetree/bindings/barebox/ for more information. 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.

View File

@ -24,7 +24,46 @@
#include <malloc.h> #include <malloc.h>
#include <partition.h> #include <partition.h>
#include <envfs.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) static int environment_probe(struct device_d *dev)
{ {
@ -35,8 +74,12 @@ static int environment_probe(struct device_d *dev)
if (ret) if (ret)
return 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); default_environment_path_set(path);
return 0; return 0;

View File

@ -23,16 +23,6 @@
#include <linux/mtd/mtd.h> #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 *of_find_device_by_node_path(const char *path)
{ {
struct device_d *dev; struct device_d *dev;
@ -47,65 +37,6 @@ struct device_d *of_find_device_by_node_path(const char *path)
return NULL; 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 * __of_find_path
* *
@ -119,36 +50,32 @@ out:
*/ */
static int __of_find_path(struct device_node *node, const char *part, char **outpath, unsigned flags) 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; bool add_bb = false;
int ret;
op.dev = of_find_device_by_node_path(node->full_name); dev = of_find_device_by_node_path(node->full_name);
if (!op.dev) { if (!dev) {
op.dev = of_find_device_by_node_path(node->parent->full_name); dev = of_find_device_by_node_path(node->parent->full_name);
if (!op.dev) if (!dev)
return -ENODEV; return -ENODEV;
} }
device_detect(op.dev); device_detect(dev);
if (part) { if (part)
/* Find a partition inside op.dev */ cdev = device_find_partition(dev, part);
ret = of_path_parse_one(&op, part); else
if (ret) cdev = cdev_by_device_node(node);
return ret;
} else {
/* node points directly to device */
op.cdev = cdev_by_device_node(node);
if (!op.cdev)
return -ENOENT;
}
if ((flags & OF_FIND_PATH_FLAGS_BB) && op.cdev->mtd && if (!cdev)
mtd_can_have_bb(op.cdev->mtd)) return -ENOENT;
if ((flags & OF_FIND_PATH_FLAGS_BB) && cdev->mtd &&
mtd_can_have_bb(cdev->mtd))
add_bb = true; 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; return 0;
} }
@ -198,8 +125,8 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath,
{ {
struct device_node *rnode; struct device_node *rnode;
const char *path; const char *path;
const char *part; const char *part = NULL;
int ret; const char partnamestr[] = "partname:";
path = of_get_property(node, propname, NULL); path = of_get_property(node, propname, NULL);
if (!path) if (!path)
@ -209,9 +136,15 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath,
if (!rnode) if (!rnode)
return -ENODEV; return -ENODEV;
ret = of_property_read_string_index(node, propname, 1, &part); of_property_read_string_index(node, propname, 1, &part);
if (ret) if (part) {
part = NULL; 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); return __of_find_path(rnode, part, outpath, flags);
} }

View File

@ -13,6 +13,7 @@
#include <common.h> #include <common.h>
#include <clock.h> #include <clock.h>
#include <abort.h>
#include <malloc.h> #include <malloc.h>
#include <io.h> #include <io.h>
#include <init.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_GEN2 0x2
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf #define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
#define PCIE_RC_LCSR 0x80
/* PCIe Port Logic registers (memory-mapped) */ /* PCIe Port Logic registers (memory-mapped) */
#define PL_OFFSET 0x700 #define PL_OFFSET 0x700
#define PCIE_PL_PFLR (PL_OFFSET + 0x08) #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 = readl(pp->dbi_base + PCIE_PL_PFLR);
val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
val |= PCIE_PL_PFLR_FORCE_LINK; val |= PCIE_PL_PFLR_FORCE_LINK;
data_abort_mask();
writel(val, pp->dbi_base + PCIE_PL_PFLR); writel(val, pp->dbi_base + PCIE_PL_PFLR);
data_abort_unmask();
gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2; gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2;
writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); 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) static int imx6_pcie_start_link(struct pcie_port *pp)
{ {
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
uint32_t tmp; uint32_t tmp;
int ret; int ret;
u32 gpr12; u32 gpr12;
u64 start;
/* /*
* Force Gen1 operation when starting the link. In case the link is * 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; tmp |= PORT_LOGIC_SPEED_CHANGE;
writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
start = get_time_ns(); ret = imx6_pcie_wait_for_speed_change(pp);
while (!is_timeout(start, SECOND)) { if (ret) {
tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); dev_err(pp->dev, "Failed to bring link up!\n");
/* Test if the speed change finished. */ return ret;
if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
break;
} }
/* Make sure link training is finished as well! */ /* Make sure link training is finished as well! */
if (tmp & PORT_LOGIC_SPEED_CHANGE) ret = imx6_pcie_wait_for_link(pp);
ret = -EINVAL;
else
ret = imx6_pcie_wait_for_link(pp);
if (ret) { if (ret) {
dev_err(pp->dev, "Failed to bring link up!\n"); dev_err(pp->dev, "Failed to bring link up!\n");
} else { return ret;
tmp = readl(pp->dbi_base + 0x80);
dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
} }
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) 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) if (ret < 0)
return ret; return ret;
dev->priv = imx6_pcie;
return 0; 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[] = { static struct of_device_id imx6_pcie_of_match[] = {
{ .compatible = "fsl,imx6q-pcie", }, { .compatible = "fsl,imx6q-pcie", },
{}, {},
@ -604,6 +646,7 @@ static struct driver_d imx6_pcie_driver = {
.name = "imx6-pcie", .name = "imx6-pcie",
.of_compatible = DRV_OF_COMPAT(imx6_pcie_of_match), .of_compatible = DRV_OF_COMPAT(imx6_pcie_of_match),
.probe = imx6_pcie_probe, .probe = imx6_pcie_probe,
.remove = imx6_pcie_remove,
}; };
device_platform_driver(imx6_pcie_driver); device_platform_driver(imx6_pcie_driver);

View File

@ -242,7 +242,8 @@ static int imx_chipidea_probe(struct device_d *dev)
ci->vbus = regulator_get(dev, "vbus"); 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); base = dev_request_mem_region(dev, 0);
if (IS_ERR(base)) if (IS_ERR(base))

View File

@ -46,7 +46,18 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
} }
#endif #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; struct cdev *cdev;
@ -57,6 +68,17 @@ struct cdev *cdev_by_name(const char *filename)
return NULL; 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_by_device_node(struct device_node *node)
{ {
struct cdev *cdev; struct cdev *cdev;
@ -65,7 +87,7 @@ struct cdev *cdev_by_device_node(struct device_node *node)
if (!cdev->device_node) if (!cdev->device_node)
continue; continue;
if (cdev->device_node == node) if (cdev->device_node == node)
return cdev; return cdev_readlink(cdev);
} }
return NULL; return NULL;
} }
@ -111,14 +133,6 @@ int cdev_find_free_index(const char *basename)
return -EBUSY; /* all indexes are used */ 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_open(const char *name, unsigned long flags)
{ {
struct cdev *cdev; struct cdev *cdev;
@ -131,9 +145,11 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
if (!cdev) if (!cdev)
return NULL; return NULL;
ret = cdev_do_open(cdev, flags); if (cdev->ops->open) {
if (ret) ret = cdev->ops->open(cdev, flags);
return NULL; if (ret)
return NULL;
}
return cdev; return cdev;
} }
@ -259,22 +275,59 @@ int devfs_create(struct cdev *new)
if (cdev) if (cdev)
return -EEXIST; return -EEXIST;
INIT_LIST_HEAD(&new->links);
list_add_tail(&new->list, &cdev_list); list_add_tail(&new->list, &cdev_list);
if (new->dev) if (new->dev) {
list_add_tail(&new->devices_list, &new->dev->cdevs); 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; return 0;
} }
int devfs_remove(struct cdev *cdev) int devfs_remove(struct cdev *cdev)
{ {
struct cdev *c, *tmp;
if (cdev->open) if (cdev->open)
return -EBUSY; return -EBUSY;
list_del(&cdev->list); list_del(&cdev->list);
if (cdev->dev) if (cdev->dev)
list_del(&cdev->devices_list); 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; return 0;
} }

View File

@ -212,12 +212,18 @@ static int devfs_stat(struct device_d *_dev, const char *filename, struct stat *
{ {
struct cdev *cdev; struct cdev *cdev;
cdev = cdev_by_name(filename + 1); cdev = lcdev_by_name(filename + 1);
if (!cdev) if (!cdev)
return -ENOENT; return -ENOENT;
s->st_mode = S_IFCHR; s->st_mode = S_IFCHR;
s->st_size = cdev->size; s->st_size = cdev->size;
if (cdev->link)
s->st_mode |= S_IFLNK;
cdev = cdev_readlink(cdev);
if (cdev->ops->write) if (cdev->ops->write)
s->st_mode |= S_IWUSR; s->st_mode |= S_IWUSR;
if (cdev->ops->read) 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 = { static struct fs_driver_d devfs_driver = {
.read = devfs_read, .read = devfs_read,
.write = devfs_write, .write = devfs_write,
@ -258,6 +282,7 @@ static struct fs_driver_d devfs_driver = {
.erase = devfs_erase, .erase = devfs_erase,
.protect = devfs_protect, .protect = devfs_protect,
.memmap = devfs_memmap, .memmap = devfs_memmap,
.readlink = devfs_readlink,
.flags = FS_DRIVER_NO_DEV, .flags = FS_DRIVER_NO_DEV,
.drv = { .drv = {
.probe = devfs_probe, .probe = devfs_probe,

View File

@ -346,6 +346,9 @@ static void automount_mount(const char *path, int instat)
in_automount++; in_automount++;
if (fs_dev_root != get_fsdevice_by_path(path))
goto out;
list_for_each_entry(am, &automount_list, list) { list_for_each_entry(am, &automount_list, list) {
int len_path = strlen(path); int len_path = strlen(path);
int len_am_path = strlen(am->path); int len_am_path = strlen(am->path);
@ -377,12 +380,10 @@ static void automount_mount(const char *path, int instat)
if (ret) if (ret)
printf("running automount command '%s' failed\n", printf("running automount command '%s' failed\n",
am->cmd); am->cmd);
else
automount_remove(am->path);
break; break;
} }
out:
in_automount--; in_automount--;
} }

View File

@ -15,10 +15,10 @@ typedef void (*kernel_entry_func)(int zero, int arch, void *params);
void bootstrap_boot(kernel_entry_func func, bool barebox); void bootstrap_boot(kernel_entry_func func, bool barebox);
#ifdef CONFIG_BOOTSTRAP_DEVFS #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); int default_size, int max_size);
#else #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) int default_size, int max_size)
{ {
return NULL; return NULL;
@ -26,9 +26,9 @@ static inline void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
#endif #endif
#ifdef CONFIG_BOOTSTRAP_DISK #ifdef CONFIG_BOOTSTRAP_DISK
void* bootstrap_read_disk(char *devname, char *fstype); void* bootstrap_read_disk(const char *devname, const char *fstype);
#else #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; return NULL;
} }

View File

@ -450,13 +450,18 @@ struct cdev {
int open; int open;
struct mtd_info *mtd; struct mtd_info *mtd;
u8 dos_partition_type; u8 dos_partition_type;
struct cdev *link;
struct list_head link_entry, links;
}; };
int devfs_create(struct cdev *); int devfs_create(struct cdev *);
int devfs_create_link(struct cdev *, const char *name);
int devfs_remove(struct cdev *); int devfs_remove(struct cdev *);
int cdev_find_free_index(const char *); int cdev_find_free_index(const char *);
struct cdev *device_find_partition(struct device_d *dev, const char *name); struct cdev *device_find_partition(struct device_d *dev, const char *name);
struct cdev *cdev_by_name(const char *filename); 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_by_device_node(struct device_node *node);
struct cdev *cdev_open(const char *name, unsigned long flags); struct cdev *cdev_open(const char *name, unsigned long flags);
int cdev_do_open(struct cdev *, unsigned long flags); int cdev_do_open(struct cdev *, unsigned long flags);

View File

@ -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) \ #define for_each_node_by_name_from(dn, root, name) \
for (dn = of_find_node_by_name(root, name); dn; \ for (dn = of_find_node_by_name(root, name); dn; \
dn = of_find_node_by_name(dn, name)) dn = of_find_node_by_name(dn, name))
#define for_each_compatible_node(dn, type, compatible) \ /* Iterate over compatible nodes starting from given root */
for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ #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)) 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( static inline struct device_node *of_find_matching_node(
struct device_node *from, struct device_node *from,
const struct of_device_id *matches) const struct of_device_id *matches)
@ -732,6 +736,17 @@ static inline int of_property_read_u32(const struct device_node *np,
s; \ s; \
s = of_prop_next_string(prop, 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, static inline int of_property_write_u8(struct device_node *np,
const char *propname, u8 value) const char *propname, u8 value)
{ {

View File

@ -80,7 +80,7 @@ static unsigned int get_image_size(void *head)
} }
#endif #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 default_size, int max_size)
{ {
int ret; int ret;

View File

@ -14,12 +14,12 @@
#include <libfile.h> #include <libfile.h>
#include <bootstrap.h> #include <bootstrap.h>
void* bootstrap_read_disk(char *dev, char *fstype) void* bootstrap_read_disk(const char *dev, const char *fstype)
{ {
int ret; int ret;
void *buf; void *buf;
int len; int len;
char *path = "/"; const char *path = "/";
ret = mount(dev, fstype, path, NULL); ret = mount(dev, fstype, path, NULL);
if (ret) { if (ret) {

View File

@ -1,6 +1,7 @@
#include <common.h> #include <common.h>
#include <readkey.h> #include <readkey.h>
#include <init.h> #include <init.h>
#include <libbb.h>
#include <xfuncs.h> #include <xfuncs.h>
#include <complete.h> #include <complete.h>
#include <linux/ctype.h> #include <linux/ctype.h>
@ -150,7 +151,7 @@ static void cread_add_char(char ichar, int insert, unsigned long *num,
/* room ??? */ /* room ??? */
if (insert || *num == *eol_num) { if (insert || *num == *eol_num) {
if (*eol_num > len - 1) { if (*eol_num > len - 2) {
getcmd_cbeep(); getcmd_cbeep();
return; return;
} }
@ -321,7 +322,7 @@ int readline(const char *prompt, char *buf, int len)
ERASE_TO_EOL(); ERASE_TO_EOL();
/* copy new line into place and display */ /* copy new line into place and display */
strcpy(buf, hline); safe_strncpy(buf, hline, len);
eol_num = strlen(buf); eol_num = strlen(buf);
REFRESH_TO_EOL(); REFRESH_TO_EOL();
continue; continue;