Merge branch 'for-next/of'
Conflicts: arch/arm/boards/freescale-mx53-loco/board.c drivers/of/Makefile
This commit is contained in:
commit
fbf082b565
|
@ -0,0 +1,10 @@
|
|||
barebox specific devicetree bindings
|
||||
====================================
|
||||
|
||||
barebox uses some barebox specific devicetree bindings. All of these
|
||||
are under the /chosen/ hierarchy in the devicetree.
|
||||
|
||||
The bindings have the form of a device with regular 'compatible' properties.
|
||||
drivers matching these devices do not handle physical devices but instead
|
||||
influence / configure certain behaviours of barebox like the place where to
|
||||
find the persistent environment.
|
|
@ -0,0 +1,25 @@
|
|||
barebox environment
|
||||
===================
|
||||
|
||||
This driver provides an environment for barebox from the devicetree.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "barebox,environment"
|
||||
- device-path: path to the environment
|
||||
|
||||
The device-path is a multistring property. The first string should be a
|
||||
nodepath to the node containing the physical device of the environment.
|
||||
The subsequent strings are of the form <type>:<options> to further describe
|
||||
the path to the environment. Supported values for <type>:
|
||||
|
||||
partname:<partname> This describes a partition on a device. <partname> can
|
||||
be the label for mtd partitions, the number for DOS
|
||||
partitions (beginning with 0) or the name for GPT
|
||||
partitions
|
||||
|
||||
Example:
|
||||
|
||||
environment@0 {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &flash, "partname:barebox-environment";
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
Common leds properties.
|
||||
|
||||
- linux,default-trigger barebox,default-trigger: This parameter, if present, is a
|
||||
string defining the trigger assigned to the LED. Current triggers are:
|
||||
"heartbeat" - LED flashes at a constant rate
|
||||
"panic" - LED turns on when barebox panics
|
||||
"net" - LED indicates network activity
|
||||
|
|
@ -114,22 +114,6 @@ static int realq7_env_init(void)
|
|||
BBU_HANDLER_FLAG_DEFAULT, NULL, 0, 0x00907000);
|
||||
imx6_bbu_internal_mmc_register_handler("mmc", "/dev/mmc3.barebox",
|
||||
0, NULL, 0, 0x00907000);
|
||||
|
||||
switch (bootsource_get()) {
|
||||
case BOOTSOURCE_MMC:
|
||||
device_detect_by_name("mmc3");
|
||||
devfs_add_partition("mmc3", 0, SZ_1M, DEVFS_PARTITION_FIXED, "mmc3.barebox");
|
||||
devfs_add_partition("mmc3", SZ_1M, SZ_1M, DEVFS_PARTITION_FIXED, "mmc3.bareboxenv");
|
||||
default_environment_path = "/dev/mmc3.bareboxenv";
|
||||
break;
|
||||
default:
|
||||
case BOOTSOURCE_SPI:
|
||||
devfs_add_partition("m25p0", 0, SZ_256K, DEVFS_PARTITION_FIXED, "m25p0.barebox");
|
||||
devfs_add_partition("m25p0", SZ_256K, SZ_256K, DEVFS_PARTITION_FIXED, "m25p0.bareboxenv");
|
||||
default_environment_path = "/dev/m25p0.bareboxenv";
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(realq7_env_init);
|
||||
|
@ -141,6 +125,16 @@ static int realq7_console_init(void)
|
|||
|
||||
imx6_init_lowlevel();
|
||||
|
||||
switch (bootsource_get()) {
|
||||
case BOOTSOURCE_MMC:
|
||||
of_device_enable_path("/chosen/environment-emmc");
|
||||
break;
|
||||
default:
|
||||
case BOOTSOURCE_SPI:
|
||||
of_device_enable_path("/chosen/environment-spi");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(realq7_console_init);
|
||||
|
|
|
@ -210,6 +210,16 @@ static int efikamx_usb_init(void)
|
|||
mxc_iomux_v3_setup_pad(MX51_PAD_EIM_A26__USBH2_STP);
|
||||
}
|
||||
|
||||
switch (bootsource_get()) {
|
||||
case BOOTSOURCE_MMC:
|
||||
of_device_enable_path("/chosen/environment-sd");
|
||||
break;
|
||||
case BOOTSOURCE_SPI:
|
||||
default:
|
||||
of_device_enable_path("/chosen/environment-spi");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
console_initcall(efikamx_usb_init);
|
||||
|
@ -230,7 +240,6 @@ extern char flash_header_imx51_genesi_efikasb_end[];
|
|||
|
||||
static int efikamx_late_init(void)
|
||||
{
|
||||
enum bootsource bootsource;
|
||||
int i;
|
||||
|
||||
if (!of_machine_is_compatible("genesi,imx51-sb"))
|
||||
|
@ -255,24 +264,6 @@ static int efikamx_late_init(void)
|
|||
armlinux_set_architecture(2370);
|
||||
armlinux_set_revision(0x5100 | imx_silicon_revision());
|
||||
|
||||
bootsource = bootsource_get();
|
||||
|
||||
switch (bootsource) {
|
||||
case BOOTSOURCE_MMC:
|
||||
device_detect_by_name("mmc1");
|
||||
|
||||
devfs_add_partition("mmc1", 0x00000, 0x80000,
|
||||
DEVFS_PARTITION_FIXED, "self0");
|
||||
devfs_add_partition("mmc1", 0x80000, 0x80000,
|
||||
DEVFS_PARTITION_FIXED, "env0");
|
||||
break;
|
||||
case BOOTSOURCE_SPI:
|
||||
default:
|
||||
devfs_add_partition("m25p0", 0x80000, 0x20000,
|
||||
DEVFS_PARTITION_FIXED, "env0");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(efikamx_late_init);
|
||||
|
|
|
@ -178,11 +178,6 @@ static int imx51_babbage_late_init(void)
|
|||
BBU_HANDLER_FLAG_DEFAULT, (void *)flash_header_imx51_babbage_start,
|
||||
flash_header_imx51_babbage_end - flash_header_imx51_babbage_start, 0);
|
||||
|
||||
device_detect_by_name("mmc0");
|
||||
|
||||
devfs_add_partition("mmc0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self0");
|
||||
devfs_add_partition("mmc0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(imx51_babbage_late_init);
|
||||
|
|
|
@ -71,6 +71,7 @@ CONFIG_NET_NFS=y
|
|||
CONFIG_NET_PING=y
|
||||
CONFIG_NET_RESOLV=y
|
||||
CONFIG_OFDEVICE=y
|
||||
CONFIG_OF_BAREBOX_DRIVERS=y
|
||||
CONFIG_DRIVER_NET_FEC_IMX=y
|
||||
CONFIG_DRIVER_SPI_IMX=y
|
||||
CONFIG_I2C=y
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
chosen {
|
||||
linux,stdout-path = "/soc/aips@70000000/serial@73fbc000";
|
||||
|
||||
environment@0 {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &esdhc1, "partname:barebox-environment";
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
|
@ -73,6 +78,13 @@
|
|||
fsl,cd-controller;
|
||||
fsl,wp-controller;
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "barebox-environment";
|
||||
reg = <0x80000 0x20000>;
|
||||
};
|
||||
};
|
||||
|
||||
&esdhc2 {
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
|
||||
chosen {
|
||||
linux,stdout-path = "/soc/aips@70000000/serial@73fbc000";
|
||||
|
||||
environment-sd {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &esdhc2, "partname:barebox-environment";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
environment-spi {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &flash, "partname:barebox-environment";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
|
@ -178,6 +190,13 @@
|
|||
cd-gpios = <&gpio1 8 0>;
|
||||
wp-gpios = <&gpio1 7 0>;
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "barebox-environment";
|
||||
reg = <0x80000 0x80000>;
|
||||
};
|
||||
};
|
||||
|
||||
&ecspi1 {
|
||||
|
@ -290,6 +309,13 @@
|
|||
compatible = "sst,sst25vf032b", "m25p80";
|
||||
spi-max-frequency = <15000000>;
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "barebox-environment";
|
||||
reg = <0x80000 0x80000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
chosen {
|
||||
linux,stdout-path = "/soc/aips@50000000/serial@53fbc000";
|
||||
|
||||
environment@0 {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &esdhc1, "partname:barebox-environment";
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
|
@ -119,6 +124,13 @@
|
|||
pinctrl-0 = <&pinctrl_esdhc1_1>;
|
||||
cd-gpios = <&gpio3 13 0>;
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "barebox-environment";
|
||||
reg = <0x80000 0x20000>;
|
||||
};
|
||||
};
|
||||
|
||||
&ssi2 {
|
||||
|
|
|
@ -19,6 +19,18 @@
|
|||
|
||||
chosen {
|
||||
linux,stdout-path = "/soc/aips-bus@02100000/serial@021e8000";
|
||||
|
||||
environment-emmc {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &usdhc4, "partname:barebox-environment";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
environment-spi {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &flash, "partname:barebox-environment";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
aliases {
|
||||
|
@ -87,6 +99,18 @@
|
|||
compatible = "m25p80";
|
||||
spi-max-frequency = <40000000>;
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "barebox";
|
||||
reg = <0x0 0x80000>;
|
||||
};
|
||||
|
||||
partition@1 {
|
||||
label = "barebox-environment";
|
||||
reg = <0x80000 0x20000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -351,4 +375,11 @@
|
|||
non-removable;
|
||||
bus-width = <8>;
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "barebox-environment";
|
||||
reg = <0x0 0x80000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <init.h>
|
||||
#include <asm/syslib.h>
|
||||
#include <ns16550.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* These datas are from the MBR, created by the linker and filled by the
|
||||
|
@ -43,6 +44,7 @@ extern uint8_t pers_env_drive;
|
|||
static int devices_init(void)
|
||||
{
|
||||
int rc;
|
||||
struct cdev *cdev;
|
||||
|
||||
/* extended memory only */
|
||||
add_mem_device("ram0", 0x0, bios_get_memsize() << 10,
|
||||
|
@ -51,11 +53,11 @@ static int devices_init(void)
|
|||
NULL);
|
||||
|
||||
if (pers_env_size != PATCH_AREA_PERS_SIZE_UNUSED) {
|
||||
rc = devfs_add_partition("biosdisk0",
|
||||
cdev = devfs_add_partition("biosdisk0",
|
||||
pers_env_storage * 512,
|
||||
(unsigned)pers_env_size * 512,
|
||||
DEVFS_PARTITION_FIXED, "env0");
|
||||
printf("Partition: %d\n", rc);
|
||||
printf("Partition: %d\n", IS_ERR(cdev) ? PTR_ERR(cdev) : 0);
|
||||
} else
|
||||
printf("No persistent storage defined\n");
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define SIZE_REMAINING ((ulong)-1)
|
||||
|
||||
|
@ -48,7 +49,8 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
|
|||
char *end;
|
||||
char buf[PATH_MAX] = {};
|
||||
unsigned long flags = 0;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct cdev *cdev;
|
||||
|
||||
memset(buf, 0, PATH_MAX);
|
||||
|
||||
|
@ -99,9 +101,12 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
|
|||
|
||||
*retsize = size;
|
||||
|
||||
ret = devfs_add_partition(devname, *offset, size, flags, buf);
|
||||
if (ret)
|
||||
cdev = devfs_add_partition(devname, *offset, size, flags, buf);
|
||||
if (IS_ERR(cdev)) {
|
||||
ret = PTR_ERR(cdev);
|
||||
printf("cannot create %s: %s\n", buf, strerror(-ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ out:
|
|||
|
||||
int envfs_register_partition(const char *devname, unsigned int partnr)
|
||||
{
|
||||
struct cdev *cdev;
|
||||
struct cdev *cdev, *part;
|
||||
char *partname;
|
||||
|
||||
if (!devname)
|
||||
|
@ -398,8 +398,14 @@ int envfs_register_partition(const char *devname, unsigned int partnr)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
return devfs_add_partition(partname, 0, cdev->size,
|
||||
part = devfs_add_partition(partname, 0, cdev->size,
|
||||
DEVFS_PARTITION_FIXED, "env0");
|
||||
if (part)
|
||||
return 0;
|
||||
|
||||
free(partname);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(envfs_register_partition);
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <disks.h>
|
||||
#include <filetype.h>
|
||||
#include <dma.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "partitions/parser.h"
|
||||
|
||||
|
@ -48,16 +49,19 @@ static int register_one_partition(struct block_device *blk,
|
|||
int ret;
|
||||
uint64_t start = part->first_sec * SECTOR_SIZE;
|
||||
uint64_t size = part->size * SECTOR_SIZE;
|
||||
struct cdev *cdev;
|
||||
|
||||
partition_name = asprintf("%s.%d", blk->cdev.name, no);
|
||||
if (!partition_name)
|
||||
return -ENOMEM;
|
||||
dev_dbg(blk->dev, "Registering partition %s on drive %s\n",
|
||||
partition_name, blk->cdev.name);
|
||||
ret = devfs_add_partition(blk->cdev.name,
|
||||
cdev = devfs_add_partition(blk->cdev.name,
|
||||
start, size, 0, partition_name);
|
||||
if (ret)
|
||||
if (IS_ERR(cdev)) {
|
||||
ret = PTR_ERR(cdev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free(partition_name);
|
||||
|
||||
|
@ -70,10 +74,10 @@ static int register_one_partition(struct block_device *blk,
|
|||
|
||||
dev_dbg(blk->dev, "Registering partition %s on drive %s\n",
|
||||
partition_name, blk->cdev.name);
|
||||
ret = devfs_add_partition(blk->cdev.name,
|
||||
cdev = devfs_add_partition(blk->cdev.name,
|
||||
start, size, 0, partition_name);
|
||||
|
||||
if (ret)
|
||||
if (IS_ERR(cdev))
|
||||
dev_warn(blk->dev, "Registering partition %s on drive %s failed\n",
|
||||
partition_name, blk->cdev.name);
|
||||
|
||||
|
|
|
@ -24,5 +24,6 @@ source "drivers/dma/Kconfig"
|
|||
source "drivers/gpio/Kconfig"
|
||||
source "drivers/w1/Kconfig"
|
||||
source "drivers/pinctrl/Kconfig"
|
||||
source "drivers/bus/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -23,3 +23,4 @@ obj-y += gpio/
|
|||
obj-$(CONFIG_OFTREE) += of/
|
||||
obj-$(CONFIG_W1) += w1/
|
||||
obj-y += pinctrl/
|
||||
obj-y += bus/
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
menu "Bus devices"
|
||||
|
||||
config IMX_WEIM
|
||||
depends on ARCH_IMX
|
||||
bool "i.MX WEIM driver"
|
||||
|
||||
endmenu
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_IMX_WEIM) += imx-weim.o
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* EIM driver for Freescale's i.MX chips
|
||||
*
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <driver.h>
|
||||
#include <init.h>
|
||||
#include <io.h>
|
||||
#include <of.h>
|
||||
|
||||
struct imx_weim_devtype {
|
||||
unsigned int cs_count;
|
||||
unsigned int cs_regs_count;
|
||||
unsigned int cs_stride;
|
||||
};
|
||||
|
||||
static const struct imx_weim_devtype imx1_weim_devtype = {
|
||||
.cs_count = 6,
|
||||
.cs_regs_count = 2,
|
||||
.cs_stride = 0x08,
|
||||
};
|
||||
|
||||
static const struct imx_weim_devtype imx27_weim_devtype = {
|
||||
.cs_count = 6,
|
||||
.cs_regs_count = 3,
|
||||
.cs_stride = 0x10,
|
||||
};
|
||||
|
||||
static const struct imx_weim_devtype imx50_weim_devtype = {
|
||||
.cs_count = 4,
|
||||
.cs_regs_count = 6,
|
||||
.cs_stride = 0x18,
|
||||
};
|
||||
|
||||
static const struct imx_weim_devtype imx51_weim_devtype = {
|
||||
.cs_count = 6,
|
||||
.cs_regs_count = 6,
|
||||
.cs_stride = 0x18,
|
||||
};
|
||||
|
||||
static struct of_device_id weim_id_table[] = {
|
||||
{
|
||||
/* i.MX1/21 */
|
||||
.compatible = "fsl,imx1-weim",
|
||||
.data = (unsigned long)&imx1_weim_devtype,
|
||||
}, {
|
||||
/* i.MX25/27/31/35 */
|
||||
.compatible = "fsl,imx27-weim",
|
||||
.data = (unsigned long)&imx27_weim_devtype,
|
||||
}, {
|
||||
/* i.MX50/53/6Q */
|
||||
.compatible = "fsl,imx50-weim",
|
||||
.data = (unsigned long)&imx50_weim_devtype,
|
||||
}, {
|
||||
/* i.MX51 */
|
||||
.compatible = "fsl,imx51-weim",
|
||||
.data = (unsigned long)&imx51_weim_devtype,
|
||||
}, {
|
||||
.compatible = "fsl,imx6q-weim",
|
||||
.data = (unsigned long)&imx50_weim_devtype,
|
||||
}, {
|
||||
}
|
||||
};
|
||||
|
||||
struct imx_weim {
|
||||
struct device_d *dev;
|
||||
void __iomem *base;
|
||||
struct imx_weim_devtype *devtype;
|
||||
};
|
||||
|
||||
/* Parse and set the timing for this device. */
|
||||
static int
|
||||
weim_timing_setup(struct imx_weim *weim, struct device_node *np)
|
||||
{
|
||||
struct imx_weim_devtype *devtype = weim->devtype;
|
||||
u32 cs_idx, value[devtype->cs_regs_count];
|
||||
int i, ret;
|
||||
|
||||
/* get the CS index from this child node's "reg" property. */
|
||||
ret = of_property_read_u32(np, "reg", &cs_idx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cs_idx >= devtype->cs_count)
|
||||
return -EINVAL;
|
||||
|
||||
ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
|
||||
value, devtype->cs_regs_count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(weim->dev, "setting up cs for %s\n", np->name);
|
||||
|
||||
/* set the timing for WEIM */
|
||||
for (i = 0; i < devtype->cs_regs_count; i++)
|
||||
writel(value[i], weim->base + cs_idx * devtype->cs_stride + i * 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int weim_parse_dt(struct imx_weim *weim)
|
||||
{
|
||||
struct device_node *child;
|
||||
int ret;
|
||||
|
||||
for_each_child_of_node(weim->dev->device_node, child) {
|
||||
if (!child->name)
|
||||
continue;
|
||||
|
||||
ret = weim_timing_setup(weim, child);
|
||||
if (ret) {
|
||||
dev_err(weim->dev, "%s set timing failed.\n",
|
||||
child->full_name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_platform_populate(weim->dev->device_node, NULL, weim->dev);
|
||||
if (ret)
|
||||
dev_err(weim->dev, "%s fail to create devices.\n",
|
||||
weim->dev->device_node->full_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int weim_probe(struct device_d *dev)
|
||||
{
|
||||
struct imx_weim_devtype *devtype;
|
||||
struct imx_weim *weim;
|
||||
int ret;
|
||||
|
||||
ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
weim = xzalloc(sizeof(*weim));
|
||||
|
||||
weim->dev = dev;
|
||||
weim->devtype = devtype;
|
||||
|
||||
/* get the resource */
|
||||
weim->base = dev_request_mem_region(dev, 0);
|
||||
if (!weim->base) {
|
||||
ret = -EBUSY;
|
||||
goto weim_err;
|
||||
}
|
||||
|
||||
/* parse the device node */
|
||||
ret = weim_parse_dt(weim);
|
||||
if (ret) {
|
||||
goto weim_err;
|
||||
}
|
||||
|
||||
dev_info(dev, "WEIM driver registered.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
weim_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct driver_d weim_driver = {
|
||||
.name = "imx-weim",
|
||||
.of_compatible = DRV_OF_COMPAT(weim_id_table),
|
||||
.probe = weim_probe,
|
||||
};
|
||||
device_platform_driver(weim_driver);
|
|
@ -7,6 +7,10 @@ config LED_GPIO
|
|||
bool "gpio LED support"
|
||||
depends on GENERIC_GPIO
|
||||
|
||||
config LED_GPIO_OF
|
||||
bool "support parsing gpio LEDs from device tree"
|
||||
depends on LED_GPIO && OFTREE
|
||||
|
||||
config LED_GPIO_RGB
|
||||
bool "gpio rgb LED support"
|
||||
depends on LED_GPIO
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
*
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <led.h>
|
||||
#include <gpio.h>
|
||||
#include <of_gpio.h>
|
||||
|
||||
static void led_gpio_set(struct led *led, unsigned int value)
|
||||
{
|
||||
|
@ -194,3 +196,79 @@ void led_gpio_rgb_unregister(struct gpio_led *led)
|
|||
led_unregister(&led->led);
|
||||
}
|
||||
#endif /* CONFIG_LED_GPIO_RGB */
|
||||
|
||||
#ifdef CONFIG_LED_GPIO_OF
|
||||
|
||||
struct led_trg {
|
||||
const char *str;
|
||||
enum led_trigger trg;
|
||||
};
|
||||
|
||||
static struct led_trg triggers[] = {
|
||||
{ .str = "heartbeat", LED_TRIGGER_HEARTBEAT, },
|
||||
{ .str = "panic", LED_TRIGGER_PANIC, },
|
||||
{ .str = "net", LED_TRIGGER_NET_TXRX, },
|
||||
};
|
||||
|
||||
static void led_of_parse_trigger(struct led *led, struct device_node *np)
|
||||
{
|
||||
const char *trigger;
|
||||
int i;
|
||||
|
||||
trigger = of_get_property(np, "linux,default-trigger", NULL);
|
||||
if (!trigger)
|
||||
trigger = of_get_property(np, "barebox,default-trigger", NULL);
|
||||
|
||||
if (!trigger)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(triggers); i++) {
|
||||
struct led_trg *trg = &triggers[i];
|
||||
if (!strcmp(trg->str, trigger)) {
|
||||
led_set_trigger(trg->trg, led);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int led_gpio_of_probe(struct device_d *dev)
|
||||
{
|
||||
struct device_node *child;
|
||||
|
||||
for_each_child_of_node(dev->device_node, child) {
|
||||
struct gpio_led *gled;
|
||||
enum of_gpio_flags flags;
|
||||
int gpio;
|
||||
|
||||
gpio = of_get_named_gpio_flags(child, "gpios", 0, &flags);
|
||||
if (gpio < 0)
|
||||
continue;
|
||||
|
||||
gled = xzalloc(sizeof(*gled));
|
||||
gled->led.name = xstrdup(child->name);
|
||||
gled->gpio = gpio;
|
||||
gled->active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
|
||||
|
||||
dev_dbg(dev, "register led %s on gpio%d, active_low = %d\n",
|
||||
gled->led.name, gled->gpio, gled->active_low);
|
||||
|
||||
led_of_parse_trigger(&gled->led, child);
|
||||
led_gpio_register(gled);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id led_gpio_of_ids[] = {
|
||||
{ .compatible = "gpio-leds", },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct driver_d led_gpio_of_driver = {
|
||||
.name = "gpio-leds",
|
||||
.probe = led_gpio_of_probe,
|
||||
.of_compatible = DRV_OF_COMPAT(led_gpio_of_ids),
|
||||
};
|
||||
device_platform_driver(led_gpio_of_driver);
|
||||
|
||||
#endif /* CONFIG LED_GPIO_OF */
|
||||
|
|
|
@ -406,7 +406,7 @@ static int mci_calc_blk_cnt(uint64_t cap, unsigned shift)
|
|||
}
|
||||
|
||||
static void mci_part_add(struct mci *mci, uint64_t size,
|
||||
unsigned int part_cfg, char *name, int idx, bool ro,
|
||||
unsigned int part_cfg, char *name, char *partname, int idx, bool ro,
|
||||
int area_type)
|
||||
{
|
||||
struct mci_part *part = &mci->part[mci->nr_parts];
|
||||
|
@ -414,6 +414,7 @@ static void mci_part_add(struct mci *mci, uint64_t size,
|
|||
part->mci = mci;
|
||||
part->size = size;
|
||||
part->blk.cdev.name = name;
|
||||
part->blk.cdev.partname = partname;
|
||||
part->blk.blockbits = SECTOR_SHIFT;
|
||||
part->blk.num_blocks = mci_calc_blk_cnt(size, part->blk.blockbits);
|
||||
part->area_type = area_type;
|
||||
|
@ -482,13 +483,14 @@ static int mmc_change_freq(struct mci *mci)
|
|||
unsigned int part_size;
|
||||
|
||||
for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) {
|
||||
char *name;
|
||||
char *name, *partname;
|
||||
part_size = mci->ext_csd[EXT_CSD_BOOT_MULT] << 17;
|
||||
|
||||
name = asprintf("%s.boot%d", mci->cdevname, idx);
|
||||
partname = asprintf("boot%d", idx);
|
||||
name = asprintf("%s.%s", mci->cdevname, partname);
|
||||
mci_part_add(mci, part_size,
|
||||
EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
|
||||
name, idx, true,
|
||||
name, partname, idx, true,
|
||||
MMC_BLK_DATA_AREA_BOOT);
|
||||
}
|
||||
|
||||
|
@ -1104,7 +1106,7 @@ static int mci_startup(struct mci *mci)
|
|||
err = mci_set_blocklen(mci, mci->read_bl_len);
|
||||
|
||||
mci_part_add(mci, mci->capacity, 0,
|
||||
mci->cdevname, 0, true,
|
||||
mci->cdevname, NULL, 0, true,
|
||||
MMC_BLK_DATA_AREA_MAIN);
|
||||
|
||||
return err;
|
||||
|
@ -1556,6 +1558,7 @@ static int mci_card_probe(struct mci *mci)
|
|||
dev_warn(&mci->dev, "No partition table found\n");
|
||||
rc = 0; /* it's not a failure */
|
||||
}
|
||||
of_parse_partitions(&part->blk.cdev, host->hw_dev->device_node);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) &&
|
||||
|
|
|
@ -386,6 +386,7 @@ int add_mtd_device(struct mtd_info *mtd, char *devname)
|
|||
}
|
||||
|
||||
devfs_create(&mtd->cdev);
|
||||
of_parse_partitions(&mtd->cdev, mtd->parent->device_node);
|
||||
|
||||
list_for_each_entry(hook, &mtd_register_hooks, hook)
|
||||
if (hook->add_mtd_device)
|
||||
|
|
|
@ -18,3 +18,12 @@ config OFDEVICE
|
|||
config OF_NET
|
||||
depends on NET
|
||||
def_bool y
|
||||
|
||||
config OF_BAREBOX_DRIVERS
|
||||
depends on OFDEVICE
|
||||
bool "Enable barebox specific devicetree configuration drivers"
|
||||
help
|
||||
barebox supports being configured from devicetree. This enables
|
||||
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.
|
||||
|
|
|
@ -4,3 +4,4 @@ obj-$(CONFIG_GPIOLIB) += of_gpio.o
|
|||
obj-y += partition.o
|
||||
obj-y += of_net.o
|
||||
obj-$(CONFIG_MTD) += of_mtd.o
|
||||
obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o of_path.o
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* barebox.c
|
||||
*
|
||||
* Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <io.h>
|
||||
#include <of.h>
|
||||
#include <malloc.h>
|
||||
#include <partition.h>
|
||||
#include <envfs.h>
|
||||
|
||||
struct of_partition {
|
||||
struct list_head list;
|
||||
char *nodepath;
|
||||
struct device_d *dev;
|
||||
struct device_node *of_partitions;
|
||||
};
|
||||
|
||||
static LIST_HEAD(of_partition_list);
|
||||
|
||||
struct device_d *of_find_device_by_node_path(const char *path)
|
||||
{
|
||||
struct device_d *dev;
|
||||
|
||||
for_each_device(dev) {
|
||||
if (!dev->device_node)
|
||||
continue;
|
||||
if (!strcmp(path, dev->device_node->full_name))
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int environment_probe(struct device_d *dev)
|
||||
{
|
||||
char *path;
|
||||
int ret;
|
||||
|
||||
ret = of_find_path(dev->device_node, "device-path", &path);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(dev, "setting default environment path to %s\n", path);
|
||||
|
||||
default_environment_path = path;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id environment_dt_ids[] = {
|
||||
{
|
||||
.compatible = "barebox,environment",
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct driver_d environment_driver = {
|
||||
.name = "barebox-environment",
|
||||
.probe = environment_probe,
|
||||
.of_compatible = environment_dt_ids,
|
||||
};
|
||||
|
||||
static int barebox_of_driver_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
node = of_get_root_node();
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
node = of_find_node_by_path("/chosen");
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
of_platform_populate(node, of_default_bus_match_table, NULL);
|
||||
|
||||
platform_driver_register(&environment_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(barebox_of_driver_init);
|
|
@ -1755,3 +1755,68 @@ int of_add_initrd(struct device_node *root, resource_size_t start,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_device_enable - enable a devicenode device
|
||||
* @node - the node to enable
|
||||
*
|
||||
* This deletes the status property of a devicenode effectively
|
||||
* enabling the device.
|
||||
*/
|
||||
int of_device_enable(struct device_node *node)
|
||||
{
|
||||
struct property *pp;
|
||||
|
||||
pp = of_find_property(node, "status", NULL);
|
||||
if (!pp)
|
||||
return 0;
|
||||
|
||||
of_delete_property(pp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_device_enable_path - enable a devicenode
|
||||
* @path - the nodepath to enable
|
||||
*
|
||||
* wrapper around of_device_enable taking the nodepath as argument
|
||||
*/
|
||||
int of_device_enable_path(const char *path)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
node = of_find_node_by_path(path);
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
|
||||
return of_device_enable(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_device_enable - disable a devicenode device
|
||||
* @node - the node to disable
|
||||
*
|
||||
* This sets the status of a devicenode to "disabled"
|
||||
*/
|
||||
int of_device_disable(struct device_node *node)
|
||||
{
|
||||
return of_set_property(node, "status", "disabled", sizeof("disabled"), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_device_disable_path - disable a devicenode
|
||||
* @path - the nodepath to disable
|
||||
*
|
||||
* wrapper around of_device_disable taking the nodepath as argument
|
||||
*/
|
||||
int of_device_disable_path(const char *path)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
node = of_find_node_by_path(path);
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
|
||||
return of_device_disable(node);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* of_path.c
|
||||
*
|
||||
* Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <of.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);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 - translate a path description in the devicetree to a barebox
|
||||
* path
|
||||
*
|
||||
* @node: the node containing the property with the path description
|
||||
* @propname: the property name of the path description
|
||||
* @outpath: if this function returns 0 outpath will contain the path belonging
|
||||
* to the input path description. Must be freed with free().
|
||||
*
|
||||
* pathes in the devicetree have the form of a multistring property. The first
|
||||
* string contains the full path to the physical device containing the path.
|
||||
* The remaining strings have the form "<type>:<options>". Currently supported
|
||||
* for <type> are:
|
||||
*
|
||||
* partname:<partname> - find a partition by its partition name. For mtd
|
||||
* partitions this is the label. For DOS partitions
|
||||
* this is the number beginning with 0.
|
||||
*
|
||||
* examples:
|
||||
*
|
||||
* device-path = &mmc0, "partname:0";
|
||||
* device-path = &norflash, "partname:barebox-environment";
|
||||
*/
|
||||
int of_find_path(struct device_node *node, const char *propname, char **outpath)
|
||||
{
|
||||
struct of_path op = {};
|
||||
struct device_node *rnode;
|
||||
const char *path, *str;
|
||||
int i, len, ret;
|
||||
|
||||
path = of_get_property(node, propname, &len);
|
||||
if (!path)
|
||||
return -EINVAL;
|
||||
|
||||
rnode = of_find_node_by_path(path);
|
||||
if (!rnode)
|
||||
return -ENODEV;
|
||||
|
||||
op.dev = of_find_device_by_node_path(rnode->full_name);
|
||||
if (!op.dev)
|
||||
return -ENODEV;
|
||||
|
||||
device_detect(op.dev);
|
||||
|
||||
i = 1;
|
||||
|
||||
while (1) {
|
||||
ret = of_property_read_string_index(node, propname, i++, &str);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = of_path_parse_one(&op, str);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!op.cdev)
|
||||
return -ENOENT;
|
||||
|
||||
*outpath = asprintf("/dev/%s", op.cdev->name);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -23,44 +23,58 @@
|
|||
#include <linux/mtd/mtd.h>
|
||||
#include <nand.h>
|
||||
|
||||
struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
|
||||
{
|
||||
const char *partname;
|
||||
char *filename;
|
||||
struct cdev *new;
|
||||
const __be32 *reg;
|
||||
unsigned long offset, size;
|
||||
const char *name;
|
||||
int len;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
reg = of_get_property(node, "reg", &len);
|
||||
if (!reg)
|
||||
return NULL;
|
||||
|
||||
offset = be32_to_cpu(reg[0]);
|
||||
size = be32_to_cpu(reg[1]);
|
||||
|
||||
partname = of_get_property(node, "label", &len);
|
||||
if (!partname)
|
||||
partname = of_get_property(node, "name", &len);
|
||||
name = (char *)partname;
|
||||
|
||||
debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdev->name, partname, offset, size);
|
||||
|
||||
if (of_get_property(node, "read-only", &len))
|
||||
flags = DEVFS_PARTITION_READONLY;
|
||||
|
||||
filename = asprintf("%s.%s", cdev->name, partname);
|
||||
|
||||
new = devfs_add_partition(cdev->name, offset, size, flags, filename);
|
||||
|
||||
if (cdev->mtd && cdev->mtd->type == MTD_NANDFLASH)
|
||||
dev_add_bb_dev(filename, NULL);
|
||||
|
||||
free(filename);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
int of_parse_partitions(struct cdev *cdev, struct device_node *node)
|
||||
{
|
||||
struct device_node *n;
|
||||
const char *partname;
|
||||
char *filename;
|
||||
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_child_of_node(node, n) {
|
||||
const __be32 *reg;
|
||||
unsigned long offset, size;
|
||||
const char *name;
|
||||
int len;
|
||||
unsigned long flags = 0;
|
||||
|
||||
reg = of_get_property(n, "reg", &len);
|
||||
if (!reg)
|
||||
continue;
|
||||
|
||||
offset = be32_to_cpu(reg[0]);
|
||||
size = be32_to_cpu(reg[1]);
|
||||
|
||||
partname = of_get_property(n, "label", &len);
|
||||
if (!partname)
|
||||
partname = of_get_property(n, "name", &len);
|
||||
name = (char *)partname;
|
||||
|
||||
debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdev->name, partname, offset, size);
|
||||
|
||||
if (of_get_property(n, "read-only", &len))
|
||||
flags = DEVFS_PARTITION_READONLY;
|
||||
|
||||
filename = asprintf("%s.%s", cdev->name, partname);
|
||||
|
||||
devfs_add_partition(cdev->name, offset, size, flags, filename);
|
||||
|
||||
if (cdev->mtd && cdev->mtd->type == MTD_NANDFLASH)
|
||||
dev_add_bb_dev(filename, NULL);
|
||||
|
||||
free(filename);
|
||||
of_parse_partition(cdev, n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -56,6 +56,33 @@ struct cdev *cdev_by_name(const char *filename)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_find_partition - find a partition belonging to a physical device
|
||||
*
|
||||
* @dev: the device which should be searched for partitions
|
||||
* @name: the partition name
|
||||
*/
|
||||
struct cdev *device_find_partition(struct device_d *dev, const char *name)
|
||||
{
|
||||
struct cdev *cdev;
|
||||
struct device_d *child;
|
||||
|
||||
list_for_each_entry(cdev, &dev->cdevs, devices_list) {
|
||||
if (!cdev->partname)
|
||||
continue;
|
||||
if (!strcmp(cdev->partname, name))
|
||||
return cdev;
|
||||
}
|
||||
|
||||
device_for_each_child(dev, child) {
|
||||
cdev = device_find_partition(child, name);
|
||||
if (cdev)
|
||||
return cdev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cdev_find_free_index(const char *basename)
|
||||
{
|
||||
int i;
|
||||
|
@ -70,6 +97,14 @@ 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 = cdev_by_name(name);
|
||||
|
@ -78,11 +113,9 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
|
|||
if (!cdev)
|
||||
return NULL;
|
||||
|
||||
if (cdev->ops->open) {
|
||||
ret = cdev->ops->open(cdev, flags);
|
||||
if (ret)
|
||||
return NULL;
|
||||
}
|
||||
ret = cdev_do_open(cdev, flags);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
return cdev;
|
||||
}
|
||||
|
@ -226,24 +259,26 @@ int devfs_remove(struct cdev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int devfs_add_partition(const char *devname, loff_t offset, loff_t size,
|
||||
struct cdev *devfs_add_partition(const char *devname, loff_t offset, loff_t size,
|
||||
int flags, const char *name)
|
||||
{
|
||||
struct cdev *cdev, *new;
|
||||
|
||||
cdev = cdev_by_name(name);
|
||||
if (cdev)
|
||||
return -EEXIST;
|
||||
return ERR_PTR(-EEXIST);
|
||||
|
||||
cdev = cdev_by_name(devname);
|
||||
if (!cdev)
|
||||
return -ENOENT;
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (offset + size > cdev->size)
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
new = xzalloc(sizeof (*new));
|
||||
new->name = strdup(name);
|
||||
if (!strncmp(devname, name, strlen(devname)))
|
||||
new->partname = xstrdup(name + strlen(devname) + 1);
|
||||
new->ops = cdev->ops;
|
||||
new->priv = cdev->priv;
|
||||
new->size = size;
|
||||
|
@ -257,14 +292,14 @@ int devfs_add_partition(const char *devname, loff_t offset, loff_t size,
|
|||
if (IS_ERR(new->mtd)) {
|
||||
int ret = PTR_ERR(new->mtd);
|
||||
free(new);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
devfs_create(new);
|
||||
|
||||
return 0;
|
||||
return new;
|
||||
}
|
||||
|
||||
int devfs_del_partition(const char *name)
|
||||
|
@ -291,6 +326,7 @@ int devfs_del_partition(const char *name)
|
|||
return ret;
|
||||
|
||||
free(cdev->name);
|
||||
free(cdev->partname);
|
||||
free(cdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -447,7 +447,10 @@ struct cdev {
|
|||
struct device_d *dev;
|
||||
struct list_head list;
|
||||
struct list_head devices_list;
|
||||
char *name;
|
||||
char *name; /* filename under /dev/ */
|
||||
char *partname; /* the partition name, usually the above without the
|
||||
* device part, i.e. name = "nand0.barebox" -> partname = "barebox"
|
||||
*/
|
||||
loff_t offset;
|
||||
loff_t size;
|
||||
unsigned int flags;
|
||||
|
@ -458,8 +461,10 @@ struct cdev {
|
|||
int devfs_create(struct cdev *);
|
||||
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 *cdev_open(const char *name, unsigned long flags);
|
||||
int cdev_do_open(struct cdev *, unsigned long flags);
|
||||
void cdev_close(struct cdev *cdev);
|
||||
int cdev_flush(struct cdev *cdev);
|
||||
ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags);
|
||||
|
@ -472,7 +477,7 @@ int cdev_erase(struct cdev *cdev, size_t count, loff_t offset);
|
|||
#define DEVFS_IS_PARTITION (1 << 2)
|
||||
#define DEVFS_IS_CHARACTER_DEV (1 << 3)
|
||||
|
||||
int devfs_add_partition(const char *devname, loff_t offset, loff_t size,
|
||||
struct cdev *devfs_add_partition(const char *devname, loff_t offset, loff_t size,
|
||||
int flags, const char *name);
|
||||
int devfs_del_partition(const char *name);
|
||||
|
||||
|
|
10
include/of.h
10
include/of.h
|
@ -221,6 +221,7 @@ extern int of_platform_populate(struct device_node *root,
|
|||
struct device_d *parent);
|
||||
extern struct device_d *of_find_device_by_node(struct device_node *np);
|
||||
|
||||
struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node);
|
||||
int of_parse_partitions(struct cdev *cdev, struct device_node *node);
|
||||
int of_device_is_stdout_path(struct device_d *dev);
|
||||
const char *of_get_model(void);
|
||||
|
@ -228,6 +229,8 @@ void *of_flatten_dtb(struct device_node *node);
|
|||
int of_add_memory(struct device_node *node, bool dump);
|
||||
void of_add_memory_bank(struct device_node *node, bool dump, int r,
|
||||
u64 base, u64 size);
|
||||
struct device_d *of_find_device_by_node_path(const char *path);
|
||||
int of_find_path(struct device_node *node, const char *propname, char **outpath);
|
||||
#else
|
||||
static inline int of_parse_partitions(struct cdev *cdev,
|
||||
struct device_node *node)
|
||||
|
@ -679,4 +682,11 @@ static inline int of_property_write_u64(struct device_node *np,
|
|||
return of_property_write_u64_array(np, propname, &value, 1);
|
||||
}
|
||||
|
||||
extern const struct of_device_id of_default_bus_match_table[];
|
||||
|
||||
int of_device_enable(struct device_node *node);
|
||||
int of_device_enable_path(const char *path);
|
||||
int of_device_disable(struct device_node *node);
|
||||
int of_device_disable_path(const char *path);
|
||||
|
||||
#endif /* __OF_H */
|
||||
|
|
Loading…
Reference in New Issue