Merge git://git.denx.de/u-boot-dm
For odroid-c2 (arch-meson) for now disable designware eth as meson now needs to do some harder GPIO work. Signed-off-by: Tom Rini <trini@konsulko.com> Conflicts: lib/efi_loader/efi_disk.c Modified: configs/odroid-c2_defconfig
This commit is contained in:
@@ -30,6 +30,8 @@ source "drivers/input/Kconfig"
|
||||
|
||||
source "drivers/led/Kconfig"
|
||||
|
||||
source "drivers/mailbox/Kconfig"
|
||||
|
||||
source "drivers/memory/Kconfig"
|
||||
|
||||
source "drivers/misc/Kconfig"
|
||||
|
||||
@@ -64,6 +64,7 @@ obj-y += video/
|
||||
obj-y += watchdog/
|
||||
obj-$(CONFIG_QE) += qe/
|
||||
obj-$(CONFIG_U_QE) += qe/
|
||||
obj-y += mailbox/
|
||||
obj-y += memory/
|
||||
obj-y += pwm/
|
||||
obj-y += input/
|
||||
|
||||
@@ -407,7 +407,7 @@ static int rk3036_clk_bind(struct udevice *dev)
|
||||
}
|
||||
|
||||
/* The reset driver does not have a device node, so bind it here */
|
||||
ret = device_bind_driver(gd->dm_root, "rk3036_reset", "reset", &dev);
|
||||
ret = device_bind_driver(gd->dm_root, "rk3036_sysreset", "reset", &dev);
|
||||
if (ret)
|
||||
debug("Warning: No RK3036 reset driver: ret=%d\n", ret);
|
||||
|
||||
|
||||
@@ -891,7 +891,7 @@ static int rk3288_clk_bind(struct udevice *dev)
|
||||
}
|
||||
|
||||
/* The reset driver does not have a device node, so bind it here */
|
||||
ret = device_bind_driver(gd->dm_root, "rk3288_reset", "reset", &dev);
|
||||
ret = device_bind_driver(gd->dm_root, "rk3288_sysreset", "reset", &dev);
|
||||
if (ret)
|
||||
debug("Warning: No RK3288 reset driver: ret=%d\n", ret);
|
||||
|
||||
|
||||
@@ -26,9 +26,10 @@
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int device_bind(struct udevice *parent, const struct driver *drv,
|
||||
const char *name, void *platdata, int of_offset,
|
||||
struct udevice **devp)
|
||||
static int device_bind_common(struct udevice *parent, const struct driver *drv,
|
||||
const char *name, void *platdata,
|
||||
ulong driver_data, int of_offset,
|
||||
struct udevice **devp)
|
||||
{
|
||||
struct udevice *dev;
|
||||
struct uclass *uc;
|
||||
@@ -56,6 +57,7 @@ int device_bind(struct udevice *parent, const struct driver *drv,
|
||||
INIT_LIST_HEAD(&dev->devres_head);
|
||||
#endif
|
||||
dev->platdata = platdata;
|
||||
dev->driver_data = driver_data;
|
||||
dev->name = name;
|
||||
dev->of_offset = of_offset;
|
||||
dev->parent = parent;
|
||||
@@ -193,6 +195,23 @@ fail_alloc1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int device_bind_with_driver_data(struct udevice *parent,
|
||||
const struct driver *drv, const char *name,
|
||||
ulong driver_data, int of_offset,
|
||||
struct udevice **devp)
|
||||
{
|
||||
return device_bind_common(parent, drv, name, NULL, driver_data,
|
||||
of_offset, devp);
|
||||
}
|
||||
|
||||
int device_bind(struct udevice *parent, const struct driver *drv,
|
||||
const char *name, void *platdata, int of_offset,
|
||||
struct udevice **devp)
|
||||
{
|
||||
return device_bind_common(parent, drv, name, platdata, 0, of_offset,
|
||||
devp);
|
||||
}
|
||||
|
||||
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
|
||||
const struct driver_info *info, struct udevice **devp)
|
||||
{
|
||||
|
||||
@@ -170,7 +170,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
|
||||
}
|
||||
|
||||
dm_dbg(" - found match at '%s'\n", entry->name);
|
||||
ret = device_bind(parent, entry, name, NULL, offset, &dev);
|
||||
ret = device_bind_with_driver_data(parent, entry, name,
|
||||
id->data, offset, &dev);
|
||||
if (ret == -ENODEV) {
|
||||
dm_dbg("Driver '%s' refuses to bind\n", entry->name);
|
||||
continue;
|
||||
@@ -180,7 +181,6 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
|
||||
ret);
|
||||
return ret;
|
||||
} else {
|
||||
dev->driver_data = id->data;
|
||||
found = true;
|
||||
if (devp)
|
||||
*devp = dev;
|
||||
|
||||
@@ -258,43 +258,30 @@ static int gpio_sunxi_probe(struct udevice *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sunxi_gpio_soc_data {
|
||||
int start;
|
||||
int no_banks;
|
||||
};
|
||||
|
||||
/**
|
||||
* We have a top-level GPIO device with no actual GPIOs. It has a child
|
||||
* device for each Sunxi bank.
|
||||
*/
|
||||
static int gpio_sunxi_bind(struct udevice *parent)
|
||||
{
|
||||
struct sunxi_gpio_soc_data *soc_data =
|
||||
(struct sunxi_gpio_soc_data *)dev_get_driver_data(parent);
|
||||
struct sunxi_gpio_platdata *plat = parent->platdata;
|
||||
struct sunxi_gpio_reg *ctlr;
|
||||
int bank, no_banks, ret, start;
|
||||
int bank, ret;
|
||||
|
||||
/* If this is a child device, there is nothing to do here */
|
||||
if (plat)
|
||||
return 0;
|
||||
|
||||
if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
|
||||
"allwinner,sun6i-a31-r-pinctrl") == 0) {
|
||||
start = 'L' - 'A';
|
||||
no_banks = 2; /* L & M */
|
||||
} else if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
|
||||
"allwinner,sun8i-a23-r-pinctrl") == 0 ||
|
||||
fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
|
||||
"allwinner,sun8i-a83t-r-pinctrl") == 0 ||
|
||||
fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
|
||||
"allwinner,sun8i-h3-r-pinctrl") == 0) {
|
||||
start = 'L' - 'A';
|
||||
no_banks = 1; /* L only */
|
||||
} else if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
|
||||
"allwinner,sun9i-a80-r-pinctrl") == 0) {
|
||||
start = 'L' - 'A';
|
||||
no_banks = 3; /* L, M & N */
|
||||
} else {
|
||||
start = 0;
|
||||
no_banks = SUNXI_GPIO_BANKS;
|
||||
}
|
||||
|
||||
ctlr = (struct sunxi_gpio_reg *)dev_get_addr(parent);
|
||||
for (bank = 0; bank < no_banks; bank++) {
|
||||
for (bank = 0; bank < soc_data->no_banks; bank++) {
|
||||
struct sunxi_gpio_platdata *plat;
|
||||
struct udevice *dev;
|
||||
|
||||
@@ -302,7 +289,7 @@ static int gpio_sunxi_bind(struct udevice *parent)
|
||||
if (!plat)
|
||||
return -ENOMEM;
|
||||
plat->regs = &ctlr->gpio_bank[bank];
|
||||
plat->bank_name = gpio_bank_name(start + bank);
|
||||
plat->bank_name = gpio_bank_name(soc_data->start + bank);
|
||||
plat->gpio_count = SUNXI_GPIOS_PER_BANK;
|
||||
|
||||
ret = device_bind(parent, parent->driver,
|
||||
@@ -315,23 +302,46 @@ static int gpio_sunxi_bind(struct udevice *parent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sunxi_gpio_soc_data soc_data_a_all = {
|
||||
.start = 0,
|
||||
.no_banks = SUNXI_GPIO_BANKS,
|
||||
};
|
||||
|
||||
static const struct sunxi_gpio_soc_data soc_data_l_1 = {
|
||||
.start = 'L' - 'A',
|
||||
.no_banks = 1,
|
||||
};
|
||||
|
||||
static const struct sunxi_gpio_soc_data soc_data_l_2 = {
|
||||
.start = 'L' - 'A',
|
||||
.no_banks = 2,
|
||||
};
|
||||
|
||||
static const struct sunxi_gpio_soc_data soc_data_l_3 = {
|
||||
.start = 'L' - 'A',
|
||||
.no_banks = 3,
|
||||
};
|
||||
|
||||
#define ID(_compat_, _soc_data_) \
|
||||
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
|
||||
|
||||
static const struct udevice_id sunxi_gpio_ids[] = {
|
||||
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
|
||||
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
|
||||
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
|
||||
{ .compatible = "allwinner,sun6i-a31-pinctrl" },
|
||||
{ .compatible = "allwinner,sun6i-a31s-pinctrl" },
|
||||
{ .compatible = "allwinner,sun7i-a20-pinctrl" },
|
||||
{ .compatible = "allwinner,sun8i-a23-pinctrl" },
|
||||
{ .compatible = "allwinner,sun8i-a33-pinctrl" },
|
||||
{ .compatible = "allwinner,sun8i-a83t-pinctrl", },
|
||||
{ .compatible = "allwinner,sun8i-h3-pinctrl" },
|
||||
{ .compatible = "allwinner,sun9i-a80-pinctrl" },
|
||||
{ .compatible = "allwinner,sun6i-a31-r-pinctrl" },
|
||||
{ .compatible = "allwinner,sun8i-a23-r-pinctrl" },
|
||||
{ .compatible = "allwinner,sun8i-a83t-r-pinctrl" },
|
||||
{ .compatible = "allwinner,sun8i-h3-r-pinctrl", },
|
||||
{ .compatible = "allwinner,sun9i-a80-r-pinctrl", },
|
||||
ID("allwinner,sun4i-a10-pinctrl", a_all),
|
||||
ID("allwinner,sun5i-a10s-pinctrl", a_all),
|
||||
ID("allwinner,sun5i-a13-pinctrl", a_all),
|
||||
ID("allwinner,sun6i-a31-pinctrl", a_all),
|
||||
ID("allwinner,sun6i-a31s-pinctrl", a_all),
|
||||
ID("allwinner,sun7i-a20-pinctrl", a_all),
|
||||
ID("allwinner,sun8i-a23-pinctrl", a_all),
|
||||
ID("allwinner,sun8i-a33-pinctrl", a_all),
|
||||
ID("allwinner,sun8i-a83t-pinctrl", a_all),
|
||||
ID("allwinner,sun8i-h3-pinctrl", a_all),
|
||||
ID("allwinner,sun9i-a80-pinctrl", a_all),
|
||||
ID("allwinner,sun6i-a31-r-pinctrl", l_2),
|
||||
ID("allwinner,sun8i-a23-r-pinctrl", l_1),
|
||||
ID("allwinner,sun8i-a83t-r-pinctrl", l_1),
|
||||
ID("allwinner,sun8i-h3-r-pinctrl", l_1),
|
||||
ID("allwinner,sun9i-a80-r-pinctrl", l_3),
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
20
drivers/mailbox/Kconfig
Normal file
20
drivers/mailbox/Kconfig
Normal file
@@ -0,0 +1,20 @@
|
||||
menu "Mailbox Controller Support"
|
||||
|
||||
config DM_MAILBOX
|
||||
bool "Enable mailbox controllers using Driver Model"
|
||||
depends on DM && OF_CONTROL
|
||||
help
|
||||
Enable support for the mailbox driver class. Mailboxes provide the
|
||||
ability to transfer small messages and/or notifications from one
|
||||
CPU to another CPU, or sometimes to dedicated HW modules. They form
|
||||
the basis of a variety of inter-process/inter-CPU communication
|
||||
protocols.
|
||||
|
||||
config SANDBOX_MBOX
|
||||
bool "Enable the sandbox mailbox test driver"
|
||||
depends on DM_MAILBOX && SANDBOX
|
||||
help
|
||||
Enable support for a test mailbox implementation, which simply echos
|
||||
back a modified version of any message that is sent.
|
||||
|
||||
endmenu
|
||||
7
drivers/mailbox/Makefile
Normal file
7
drivers/mailbox/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_DM_MAILBOX) += mailbox-uclass.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
|
||||
145
drivers/mailbox/mailbox-uclass.c
Normal file
145
drivers/mailbox/mailbox-uclass.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <mailbox_client.h>
|
||||
#include <mailbox_uclass.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static inline struct mbox_ops *mbox_dev_ops(struct udevice *dev)
|
||||
{
|
||||
return (struct mbox_ops *)dev->driver->ops;
|
||||
}
|
||||
|
||||
static int mbox_of_xlate_default(struct mbox_chan *chan,
|
||||
struct fdtdec_phandle_args *args)
|
||||
{
|
||||
debug("%s(chan=%p)\n", __func__, chan);
|
||||
|
||||
if (args->args_count != 1) {
|
||||
debug("Invaild args_count: %d\n", args->args_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chan->id = args->args[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbox_get_by_index(struct udevice *dev, int index, struct mbox_chan *chan)
|
||||
{
|
||||
struct fdtdec_phandle_args args;
|
||||
int ret;
|
||||
struct udevice *dev_mbox;
|
||||
struct mbox_ops *ops;
|
||||
|
||||
debug("%s(dev=%p, index=%d, chan=%p)\n", __func__, dev, index, chan);
|
||||
|
||||
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
|
||||
"mboxes", "#mbox-cells", 0,
|
||||
index, &args);
|
||||
if (ret) {
|
||||
debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_MAILBOX, args.node,
|
||||
&dev_mbox);
|
||||
if (ret) {
|
||||
debug("%s: uclass_get_device_by_of_offset failed: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
ops = mbox_dev_ops(dev_mbox);
|
||||
|
||||
chan->dev = dev_mbox;
|
||||
if (ops->of_xlate)
|
||||
ret = ops->of_xlate(chan, &args);
|
||||
else
|
||||
ret = mbox_of_xlate_default(chan, &args);
|
||||
if (ret) {
|
||||
debug("of_xlate() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ops->request(chan);
|
||||
if (ret) {
|
||||
debug("ops->request() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbox_get_by_name(struct udevice *dev, const char *name,
|
||||
struct mbox_chan *chan)
|
||||
{
|
||||
int index;
|
||||
|
||||
debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
|
||||
|
||||
index = fdt_find_string(gd->fdt_blob, dev->of_offset, "mbox-names",
|
||||
name);
|
||||
if (index < 0) {
|
||||
debug("fdt_find_string() failed: %d\n", index);
|
||||
return index;
|
||||
}
|
||||
|
||||
return mbox_get_by_index(dev, index, chan);
|
||||
}
|
||||
|
||||
int mbox_free(struct mbox_chan *chan)
|
||||
{
|
||||
struct mbox_ops *ops = mbox_dev_ops(chan->dev);
|
||||
|
||||
debug("%s(chan=%p)\n", __func__, chan);
|
||||
|
||||
return ops->free(chan);
|
||||
}
|
||||
|
||||
int mbox_send(struct mbox_chan *chan, const void *data)
|
||||
{
|
||||
struct mbox_ops *ops = mbox_dev_ops(chan->dev);
|
||||
|
||||
debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
|
||||
|
||||
return ops->send(chan, data);
|
||||
}
|
||||
|
||||
int mbox_recv(struct mbox_chan *chan, void *data, ulong timeout_us)
|
||||
{
|
||||
struct mbox_ops *ops = mbox_dev_ops(chan->dev);
|
||||
ulong start_time;
|
||||
int ret;
|
||||
|
||||
debug("%s(chan=%p, data=%p, timeout_us=%ld)\n", __func__, chan, data,
|
||||
timeout_us);
|
||||
|
||||
start_time = timer_get_us();
|
||||
/*
|
||||
* Account for partial us ticks, but if timeout_us is 0, ensure we
|
||||
* still don't wait at all.
|
||||
*/
|
||||
if (timeout_us)
|
||||
timeout_us++;
|
||||
|
||||
for (;;) {
|
||||
ret = ops->recv(chan, data);
|
||||
if (ret != -ENODATA)
|
||||
return ret;
|
||||
if ((timer_get_us() - start_time) >= timeout_us)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(mailbox) = {
|
||||
.id = UCLASS_MAILBOX,
|
||||
.name = "mailbox",
|
||||
};
|
||||
54
drivers/mailbox/sandbox-mbox-test.c
Normal file
54
drivers/mailbox/sandbox-mbox-test.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <mailbox_client.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct sandbox_mbox_test {
|
||||
struct mbox_chan chan;
|
||||
};
|
||||
|
||||
int sandbox_mbox_test_get(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_mbox_test *sbmt = dev_get_priv(dev);
|
||||
|
||||
return mbox_get_by_name(dev, "test", &sbmt->chan);
|
||||
}
|
||||
|
||||
int sandbox_mbox_test_send(struct udevice *dev, uint32_t msg)
|
||||
{
|
||||
struct sandbox_mbox_test *sbmt = dev_get_priv(dev);
|
||||
|
||||
return mbox_send(&sbmt->chan, &msg);
|
||||
}
|
||||
|
||||
int sandbox_mbox_test_recv(struct udevice *dev, uint32_t *msg)
|
||||
{
|
||||
struct sandbox_mbox_test *sbmt = dev_get_priv(dev);
|
||||
|
||||
return mbox_recv(&sbmt->chan, msg, 100);
|
||||
}
|
||||
|
||||
int sandbox_mbox_test_free(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_mbox_test *sbmt = dev_get_priv(dev);
|
||||
|
||||
return mbox_free(&sbmt->chan);
|
||||
}
|
||||
|
||||
static const struct udevice_id sandbox_mbox_test_ids[] = {
|
||||
{ .compatible = "sandbox,mbox-test" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_mbox_test) = {
|
||||
.name = "sandbox_mbox_test",
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = sandbox_mbox_test_ids,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_mbox_test),
|
||||
};
|
||||
104
drivers/mailbox/sandbox-mbox.c
Normal file
104
drivers/mailbox/sandbox-mbox.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <mailbox_uclass.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mbox.h>
|
||||
|
||||
#define SANDBOX_MBOX_CHANNELS 2
|
||||
|
||||
struct sandbox_mbox_chan {
|
||||
bool rx_msg_valid;
|
||||
uint32_t rx_msg;
|
||||
};
|
||||
|
||||
struct sandbox_mbox {
|
||||
struct sandbox_mbox_chan chans[SANDBOX_MBOX_CHANNELS];
|
||||
};
|
||||
|
||||
static int sandbox_mbox_request(struct mbox_chan *chan)
|
||||
{
|
||||
debug("%s(chan=%p)\n", __func__, chan);
|
||||
|
||||
if (chan->id >= SANDBOX_MBOX_CHANNELS)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_mbox_free(struct mbox_chan *chan)
|
||||
{
|
||||
debug("%s(chan=%p)\n", __func__, chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_mbox_send(struct mbox_chan *chan, const void *data)
|
||||
{
|
||||
struct sandbox_mbox *sbm = dev_get_priv(chan->dev);
|
||||
const uint32_t *pmsg = data;
|
||||
|
||||
debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
|
||||
|
||||
sbm->chans[chan->id].rx_msg = *pmsg ^ SANDBOX_MBOX_PING_XOR;
|
||||
sbm->chans[chan->id].rx_msg_valid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_mbox_recv(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct sandbox_mbox *sbm = dev_get_priv(chan->dev);
|
||||
uint32_t *pmsg = data;
|
||||
|
||||
debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
|
||||
|
||||
if (!sbm->chans[chan->id].rx_msg_valid)
|
||||
return -ENODATA;
|
||||
|
||||
*pmsg = sbm->chans[chan->id].rx_msg;
|
||||
sbm->chans[chan->id].rx_msg_valid = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_mbox_bind(struct udevice *dev)
|
||||
{
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_mbox_probe(struct udevice *dev)
|
||||
{
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sandbox_mbox_ids[] = {
|
||||
{ .compatible = "sandbox,mbox" },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct mbox_ops sandbox_mbox_mbox_ops = {
|
||||
.request = sandbox_mbox_request,
|
||||
.free = sandbox_mbox_free,
|
||||
.send = sandbox_mbox_send,
|
||||
.recv = sandbox_mbox_recv,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_mbox) = {
|
||||
.name = "sandbox_mbox",
|
||||
.id = UCLASS_MAILBOX,
|
||||
.of_match = sandbox_mbox_ids,
|
||||
.bind = sandbox_mbox_bind,
|
||||
.probe = sandbox_mbox_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_mbox),
|
||||
.ops = &sandbox_mbox_mbox_ops,
|
||||
};
|
||||
@@ -121,13 +121,13 @@ config PCA9551_I2C_ADDR
|
||||
help
|
||||
The I2C address of the PCA9551 LED controller.
|
||||
|
||||
config RESET
|
||||
bool "Enable support for reset drivers"
|
||||
config SYSRESET
|
||||
bool "Enable support for system reset drivers"
|
||||
depends on DM
|
||||
help
|
||||
Enable reset drivers which can be used to reset the CPU or board.
|
||||
Each driver can provide a reset method which will be called to
|
||||
effect a reset. The uclass will try all available drivers when
|
||||
Enable system reset drivers which can be used to reset the CPU or
|
||||
board. Each driver can provide a reset method which will be called
|
||||
to effect a reset. The uclass will try all available drivers when
|
||||
reset_walk() is called.
|
||||
|
||||
config WINBOND_W83627
|
||||
|
||||
@@ -27,7 +27,7 @@ obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
|
||||
obj-$(CONFIG_NS87308) += ns87308.o
|
||||
obj-$(CONFIG_PDSP188x) += pdsp188x.o
|
||||
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
|
||||
obj-$(CONFIG_SANDBOX) += reset_sandbox.o
|
||||
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
|
||||
ifdef CONFIG_DM_I2C
|
||||
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
|
||||
endif
|
||||
@@ -40,7 +40,7 @@ obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
|
||||
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
|
||||
obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
|
||||
obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
|
||||
obj-$(CONFIG_RESET) += reset-uclass.o
|
||||
obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
|
||||
obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o
|
||||
obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
|
||||
obj-$(CONFIG_QFW) += qfw.o
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <reset.h>
|
||||
#include <asm/state.h>
|
||||
#include <asm/test.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int sandbox_warm_reset_request(struct udevice *dev, enum reset_t type)
|
||||
{
|
||||
struct sandbox_state *state = state_get_current();
|
||||
|
||||
switch (type) {
|
||||
case RESET_WARM:
|
||||
state->last_reset = type;
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (!state->reset_allowed[type])
|
||||
return -EACCES;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static int sandbox_reset_request(struct udevice *dev, enum reset_t type)
|
||||
{
|
||||
struct sandbox_state *state = state_get_current();
|
||||
|
||||
/*
|
||||
* If we have a device tree, the device we created from platform data
|
||||
* (see the U_BOOT_DEVICE() declaration below) should not do anything.
|
||||
* If we are that device, return an error.
|
||||
*/
|
||||
if (state->fdt_fname && dev->of_offset == -1)
|
||||
return -ENODEV;
|
||||
|
||||
switch (type) {
|
||||
case RESET_COLD:
|
||||
state->last_reset = type;
|
||||
break;
|
||||
case RESET_POWER:
|
||||
state->last_reset = type;
|
||||
if (!state->reset_allowed[type])
|
||||
return -EACCES;
|
||||
sandbox_exit();
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (!state->reset_allowed[type])
|
||||
return -EACCES;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static struct reset_ops sandbox_reset_ops = {
|
||||
.request = sandbox_reset_request,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_reset_ids[] = {
|
||||
{ .compatible = "sandbox,reset" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(reset_sandbox) = {
|
||||
.name = "reset_sandbox",
|
||||
.id = UCLASS_RESET,
|
||||
.of_match = sandbox_reset_ids,
|
||||
.ops = &sandbox_reset_ops,
|
||||
};
|
||||
|
||||
static struct reset_ops sandbox_warm_reset_ops = {
|
||||
.request = sandbox_warm_reset_request,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_warm_reset_ids[] = {
|
||||
{ .compatible = "sandbox,warm-reset" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(warm_reset_sandbox) = {
|
||||
.name = "warm_reset_sandbox",
|
||||
.id = UCLASS_RESET,
|
||||
.of_match = sandbox_warm_reset_ids,
|
||||
.ops = &sandbox_warm_reset_ops,
|
||||
};
|
||||
|
||||
/* This is here in case we don't have a device tree */
|
||||
U_BOOT_DEVICE(reset_sandbox_non_fdt) = {
|
||||
.name = "reset_sandbox",
|
||||
};
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <reset.h>
|
||||
#include <sysreset.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <regmap.h>
|
||||
@@ -15,9 +15,9 @@
|
||||
#include <dm/root.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
int reset_request(struct udevice *dev, enum reset_t type)
|
||||
int sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct reset_ops *ops = reset_get_ops(dev);
|
||||
struct sysreset_ops *ops = sysreset_get_ops(dev);
|
||||
|
||||
if (!ops->request)
|
||||
return -ENOSYS;
|
||||
@@ -25,16 +25,16 @@ int reset_request(struct udevice *dev, enum reset_t type)
|
||||
return ops->request(dev, type);
|
||||
}
|
||||
|
||||
int reset_walk(enum reset_t type)
|
||||
int sysreset_walk(enum sysreset_t type)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
while (ret != -EINPROGRESS && type < RESET_COUNT) {
|
||||
for (uclass_first_device(UCLASS_RESET, &dev);
|
||||
while (ret != -EINPROGRESS && type < SYSRESET_COUNT) {
|
||||
for (uclass_first_device(UCLASS_SYSRESET, &dev);
|
||||
dev;
|
||||
uclass_next_device(&dev)) {
|
||||
ret = reset_request(dev, type);
|
||||
ret = sysreset_request(dev, type);
|
||||
if (ret == -EINPROGRESS)
|
||||
break;
|
||||
}
|
||||
@@ -44,38 +44,38 @@ int reset_walk(enum reset_t type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset_walk_halt(enum reset_t type)
|
||||
void sysreset_walk_halt(enum sysreset_t type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = reset_walk(type);
|
||||
ret = sysreset_walk(type);
|
||||
|
||||
/* Wait for the reset to take effect */
|
||||
if (ret == -EINPROGRESS)
|
||||
mdelay(100);
|
||||
|
||||
/* Still no reset? Give up */
|
||||
printf("Reset not supported on this platform\n");
|
||||
debug("System reset not supported on this platform\n");
|
||||
hang();
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_cpu() - calls reset_walk(RESET_WARM)
|
||||
* reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
|
||||
*/
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
reset_walk_halt(RESET_WARM);
|
||||
sysreset_walk_halt(SYSRESET_WARM);
|
||||
}
|
||||
|
||||
|
||||
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
reset_walk_halt(RESET_WARM);
|
||||
sysreset_walk_halt(SYSRESET_WARM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(reset) = {
|
||||
.id = UCLASS_RESET,
|
||||
.name = "reset",
|
||||
UCLASS_DRIVER(sysreset) = {
|
||||
.id = UCLASS_SYSRESET,
|
||||
.name = "sysreset",
|
||||
};
|
||||
101
drivers/misc/sysreset_sandbox.c
Normal file
101
drivers/misc/sysreset_sandbox.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <sysreset.h>
|
||||
#include <asm/state.h>
|
||||
#include <asm/test.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int sandbox_warm_sysreset_request(struct udevice *dev,
|
||||
enum sysreset_t type)
|
||||
{
|
||||
struct sandbox_state *state = state_get_current();
|
||||
|
||||
switch (type) {
|
||||
case SYSRESET_WARM:
|
||||
state->last_sysreset = type;
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (!state->sysreset_allowed[type])
|
||||
return -EACCES;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct sandbox_state *state = state_get_current();
|
||||
|
||||
/*
|
||||
* If we have a device tree, the device we created from platform data
|
||||
* (see the U_BOOT_DEVICE() declaration below) should not do anything.
|
||||
* If we are that device, return an error.
|
||||
*/
|
||||
if (state->fdt_fname && dev->of_offset == -1)
|
||||
return -ENODEV;
|
||||
|
||||
switch (type) {
|
||||
case SYSRESET_COLD:
|
||||
state->last_sysreset = type;
|
||||
break;
|
||||
case SYSRESET_POWER:
|
||||
state->last_sysreset = type;
|
||||
if (!state->sysreset_allowed[type])
|
||||
return -EACCES;
|
||||
sandbox_exit();
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (!state->sysreset_allowed[type])
|
||||
return -EACCES;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static struct sysreset_ops sandbox_sysreset_ops = {
|
||||
.request = sandbox_sysreset_request,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_sysreset_ids[] = {
|
||||
{ .compatible = "sandbox,reset" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysreset_sandbox) = {
|
||||
.name = "sysreset_sandbox",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.of_match = sandbox_sysreset_ids,
|
||||
.ops = &sandbox_sysreset_ops,
|
||||
};
|
||||
|
||||
static struct sysreset_ops sandbox_warm_sysreset_ops = {
|
||||
.request = sandbox_warm_sysreset_request,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_warm_sysreset_ids[] = {
|
||||
{ .compatible = "sandbox,warm-reset" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(warm_sysreset_sandbox) = {
|
||||
.name = "warm_sysreset_sandbox",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.of_match = sandbox_warm_sysreset_ids,
|
||||
.ops = &sandbox_warm_sysreset_ops,
|
||||
};
|
||||
|
||||
/* This is here in case we don't have a device tree */
|
||||
U_BOOT_DEVICE(sysreset_sandbox_non_fdt) = {
|
||||
.name = "sysreset_sandbox",
|
||||
};
|
||||
@@ -454,27 +454,40 @@ static const struct mmc_ops dwmci_ops = {
|
||||
.init = dwmci_init,
|
||||
};
|
||||
|
||||
void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
|
||||
uint caps, u32 max_clk, u32 min_clk)
|
||||
{
|
||||
cfg->name = name;
|
||||
cfg->ops = &dwmci_ops;
|
||||
cfg->f_min = min_clk;
|
||||
cfg->f_max = max_clk;
|
||||
|
||||
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
||||
|
||||
cfg->host_caps = caps;
|
||||
|
||||
if (buswidth == 8) {
|
||||
cfg->host_caps |= MMC_MODE_8BIT;
|
||||
cfg->host_caps &= ~MMC_MODE_4BIT;
|
||||
} else {
|
||||
cfg->host_caps |= MMC_MODE_4BIT;
|
||||
cfg->host_caps &= ~MMC_MODE_8BIT;
|
||||
}
|
||||
cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz;
|
||||
|
||||
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
|
||||
{
|
||||
return mmc_bind(dev, mmc, cfg);
|
||||
}
|
||||
#else
|
||||
int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
|
||||
{
|
||||
host->cfg.name = host->name;
|
||||
host->cfg.ops = &dwmci_ops;
|
||||
host->cfg.f_min = min_clk;
|
||||
host->cfg.f_max = max_clk;
|
||||
|
||||
host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
||||
|
||||
host->cfg.host_caps = host->caps;
|
||||
|
||||
if (host->buswidth == 8) {
|
||||
host->cfg.host_caps |= MMC_MODE_8BIT;
|
||||
host->cfg.host_caps &= ~MMC_MODE_4BIT;
|
||||
} else {
|
||||
host->cfg.host_caps |= MMC_MODE_4BIT;
|
||||
host->cfg.host_caps &= ~MMC_MODE_8BIT;
|
||||
}
|
||||
host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz;
|
||||
|
||||
host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||
dwmci_setup_cfg(&host->cfg, host->name, host->buswidth, host->caps,
|
||||
max_clk, min_clk);
|
||||
|
||||
host->mmc = mmc_create(&host->cfg, host);
|
||||
if (host->mmc == NULL)
|
||||
@@ -482,3 +495,4 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -984,7 +984,7 @@ static const int fbase[] = {
|
||||
/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
|
||||
* to platforms without floating point.
|
||||
*/
|
||||
static const int multipliers[] = {
|
||||
static const u8 multipliers[] = {
|
||||
0, /* reserved */
|
||||
10,
|
||||
12,
|
||||
@@ -1531,15 +1531,6 @@ static int mmc_send_if_cond(struct mmc *mmc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not used any more */
|
||||
int __deprecated mmc_register(struct mmc *mmc)
|
||||
{
|
||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
|
||||
printf("%s is deprecated! use mmc_create() instead.\n", __func__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
|
||||
{
|
||||
@@ -1566,7 +1557,7 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
|
||||
bdesc->removable = 1;
|
||||
|
||||
/* setup initial part type */
|
||||
bdesc->part_type = mmc->cfg->part_type;
|
||||
bdesc->part_type = cfg->part_type;
|
||||
mmc->dev = dev;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -37,6 +37,19 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
|
||||
|
||||
/* SPL will never write or erase, declare dummies to reduce code size. */
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
static inline unsigned long mmc_berase(struct udevice *dev,
|
||||
lbaint_t start, lbaint_t blkcnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline ulong mmc_bwrite(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *src)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline unsigned long mmc_berase(struct blk_desc *block_dev,
|
||||
lbaint_t start, lbaint_t blkcnt)
|
||||
{
|
||||
@@ -48,6 +61,7 @@ static inline ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct rockchip_mmc_plat {
|
||||
struct mmc_config cfg;
|
||||
struct mmc mmc;
|
||||
};
|
||||
|
||||
struct rockchip_dwmmc_priv {
|
||||
struct udevice *clk;
|
||||
int periph;
|
||||
@@ -62,6 +67,9 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
|
||||
|
||||
static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||
{
|
||||
#ifdef CONFIG_BLK
|
||||
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
|
||||
#endif
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
||||
struct dwmci_host *host = &priv->host;
|
||||
@@ -100,16 +108,37 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_BLK
|
||||
dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
|
||||
minmax[1], minmax[0]);
|
||||
host->mmc = &plat->mmc;
|
||||
#else
|
||||
ret = add_dwmci(host, minmax[1], minmax[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#endif
|
||||
host->mmc->priv = &priv->host;
|
||||
host->mmc->dev = dev;
|
||||
upriv->mmc = host->mmc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dwmmc_bind(struct udevice *dev)
|
||||
{
|
||||
#ifdef CONFIG_BLK
|
||||
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id rockchip_dwmmc_ids[] = {
|
||||
{ .compatible = "rockchip,rk3288-dw-mshc" },
|
||||
{ }
|
||||
@@ -120,8 +149,10 @@ U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
|
||||
.id = UCLASS_MMC,
|
||||
.of_match = rockchip_dwmmc_ids,
|
||||
.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
|
||||
.bind = rockchip_dwmmc_bind,
|
||||
.probe = rockchip_dwmmc_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
|
||||
.platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PWRSEQ
|
||||
|
||||
@@ -137,7 +137,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||
int trans_bytes = 0, is_aligned = 1;
|
||||
u32 mask, flags, mode;
|
||||
unsigned int time = 0, start_addr = 0;
|
||||
int mmc_dev = mmc->block_dev.devnum;
|
||||
int mmc_dev = mmc_get_blk_desc(mmc)->devnum;
|
||||
unsigned start = get_timer(0);
|
||||
|
||||
/* Timeout unit - ms */
|
||||
|
||||
@@ -326,6 +326,7 @@ static int rk_vop_probe(struct udevice *dev)
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
video_set_flush_dcache(dev, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user