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_defconfigmaster
commit
e4a94ce4ac
@ -0,0 +1,21 @@ |
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0 |
||||
*/ |
||||
|
||||
#ifndef __SANDBOX_MBOX_H |
||||
#define __SANDBOX_MBOX_H |
||||
|
||||
#include <common.h> |
||||
|
||||
#define SANDBOX_MBOX_PING_XOR 0x12345678 |
||||
|
||||
struct udevice; |
||||
|
||||
int sandbox_mbox_test_get(struct udevice *dev); |
||||
int sandbox_mbox_test_send(struct udevice *dev, uint32_t msg); |
||||
int sandbox_mbox_test_recv(struct udevice *dev, uint32_t *msg); |
||||
int sandbox_mbox_test_free(struct udevice *dev); |
||||
|
||||
#endif |
@ -0,0 +1,32 @@ |
||||
* Generic Mailbox Controller and client driver bindings |
||||
|
||||
Generic binding to provide a way for Mailbox controller drivers to |
||||
assign appropriate mailbox channel to client drivers. |
||||
|
||||
* Mailbox Controller |
||||
|
||||
Required property: |
||||
- #mbox-cells: Must be at least 1. Number of cells in a mailbox |
||||
specifier. |
||||
|
||||
Example: |
||||
mailbox: mailbox { |
||||
... |
||||
#mbox-cells = <1>; |
||||
}; |
||||
|
||||
|
||||
* Mailbox Client |
||||
|
||||
Required property: |
||||
- mboxes: List of phandle and mailbox channel specifiers. |
||||
|
||||
Optional property: |
||||
- mbox-names: List of identifier strings for each mailbox channel. |
||||
|
||||
Example: |
||||
pwr_cntrl: power { |
||||
... |
||||
mbox-names = "pwr-ctrl", "rpc"; |
||||
mboxes = <&mailbox 0 &mailbox 1>; |
||||
}; |
@ -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 |
@ -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
|
@ -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", |
||||
}; |
@ -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), |
||||
}; |
@ -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, |
||||
}; |
@ -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", |
||||
}; |
@ -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", |
||||
}; |
@ -0,0 +1,149 @@ |
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0 |
||||
*/ |
||||
|
||||
#ifndef _MAILBOX_CLIENT_H |
||||
#define _MAILBOX_CLIENT_H |
||||
|
||||
/**
|
||||
* A mailbox is a hardware mechanism for transferring small fixed-size messages |
||||
* and/or notifications between the CPU on which U-Boot runs and some other |
||||
* device such as an auxiliary CPU running firmware or a hardware module. |
||||
* |
||||
* Data transfer is optional; a mailbox may consist solely of a notification |
||||
* mechanism. When data transfer is implemented, it is via HW registers or |
||||
* FIFOs, rather than via RAM-based buffers. The mailbox API generally |
||||
* implements any communication protocol enforced solely by hardware, and |
||||
* leaves any higher-level protocols to other layers. |
||||
* |
||||
* A mailbox channel is a bi-directional mechanism that can send a message or |
||||
* notification to a single specific remote entity, and receive messages or |
||||
* notifications from that entity. The size, content, and format of such |
||||
* messages is defined by the mailbox implementation, or the remote entity with |
||||
* which it communicates; there is no general standard at this API level. |
||||
* |
||||
* A driver that implements UCLASS_MAILBOX is a mailbox provider. A provider |
||||
* will often implement multiple separate mailbox channels, since the hardware |
||||
* it manages often has this capability. mailbox_uclass.h describes the |
||||
* interface which mailbox providers must implement. |
||||
* |
||||
* Mailbox consumers/clients generate and send, or receive and process, |
||||
* messages. This header file describes the API used by clients. |
||||
*/ |
||||
|
||||
struct udevice; |
||||
|
||||
/**
|
||||
* struct mbox_chan - A handle to a single mailbox channel. |
||||
* |
||||
* Clients provide storage for channels. The content of the channel structure |
||||
* is managed solely by the mailbox API and mailbox drivers. A mailbox channel |
||||
* is initialized by "get"ing the mailbox. The channel struct is passed to all |
||||
* other mailbox APIs to identify which mailbox to operate upon. |
||||
* |
||||
* @dev: The device which implements the mailbox. |
||||
* @id: The mailbox channel ID within the provider. |
||||
* |
||||
* Currently, the mailbox API assumes that a single integer ID is enough to |
||||
* identify and configure any mailbox channel for any mailbox provider. If this |
||||
* assumption becomes invalid in the future, the struct could be expanded to |
||||
* either (a) add more fields to allow mailbox providers to store additional |
||||
* information, or (b) replace the id field with an opaque pointer, which the |
||||
* provider would dynamically allocated during its .of_xlate op, and process |
||||
* during is .request op. This may require the addition of an extra op to clean |
||||
* up the allocation. |
||||
*/ |
||||
struct mbox_chan { |
||||
struct udevice *dev; |
||||
/*
|
||||
* Written by of_xlate. We assume a single id is enough for now. In the |
||||
* future, we might add more fields here. |
||||
*/ |
||||
unsigned long id; |
||||
}; |
||||
|
||||
/**
|
||||
* mbox_get_by_index - Get/request a mailbox by integer index |
||||
* |
||||
* This looks up and requests a mailbox channel. The index is relative to the |
||||
* client device; each device is assumed to have n mailbox channels associated |
||||
* with it somehow, and this function finds and requests one of them. The |
||||
* mapping of client device channel indices to provider channels may be via |
||||
* device-tree properties, board-provided mapping tables, or some other |
||||
* mechanism. |
||||
* |
||||
* @dev: The client device. |
||||
* @index: The index of the mailbox channel to request, within the |
||||
* client's list of channels. |
||||
* @chan A pointer to a channel object to initialize. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int mbox_get_by_index(struct udevice *dev, int index, struct mbox_chan *chan); |
||||
|
||||
/**
|
||||
* mbox_get_by_name - Get/request a mailbox by name |
||||
* |
||||
* This looks up and requests a mailbox channel. The name is relative to the |
||||
* client device; each device is assumed to have n mailbox channels associated |
||||
* with it somehow, and this function finds and requests one of them. The |
||||
* mapping of client device channel names to provider channels may be via |
||||
* device-tree properties, board-provided mapping tables, or some other |
||||
* mechanism. |
||||
* |
||||
* @dev: The client device. |
||||
* @name: The name of the mailbox channel to request, within the client's |
||||
* list of channels. |
||||
* @chan A pointer to a channel object to initialize. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int mbox_get_by_name(struct udevice *dev, const char *name, |
||||
struct mbox_chan *chan); |
||||
|
||||
/**
|
||||
* mbox_free - Free a previously requested mailbox channel. |
||||
* |
||||
* @chan: A channel object that was previously successfully requested by |
||||
* calling mbox_get_by_*(). |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int mbox_free(struct mbox_chan *chan); |
||||
|
||||
/**
|
||||
* mbox_send - Send a message over a mailbox channel |
||||
* |
||||
* This function will send a message to the remote entity. It may return before |
||||
* the remote entity has received and/or processed the message. |
||||
* |
||||
* @chan: A channel object that was previously successfully requested by |
||||
* calling mbox_get_by_*(). |
||||
* @data: A pointer to the message to transfer. The format and size of |
||||
* the memory region pointed at by @data is determined by the |
||||
* mailbox provider. Providers that solely transfer notifications |
||||
* will ignore this parameter. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int mbox_send(struct mbox_chan *chan, const void *data); |
||||
|
||||
/**
|
||||
* mbox_recv - Receive any available message from a mailbox channel |
||||
* |
||||
* This function will wait (up to the specified @timeout_us) for a message to |
||||
* be sent by the remote entity, and write the content of any such message |
||||
* into a caller-provided buffer. |
||||
* |
||||
* @chan: A channel object that was previously successfully requested by |
||||
* calling mbox_get_by_*(). |
||||
* @data: A pointer to the buffer to receive the message. The format and |
||||
* size of the memory region pointed at by @data is determined by |
||||
* the mailbox provider. Providers that solely transfer |
||||
* notifications will ignore this parameter. |
||||
* @timeout_us: The maximum time to wait for a message to be available, in |
||||
* micro-seconds. A value of 0 does not wait at all. |
||||
* @return 0 if OK, -ENODATA if no message was available, or a negative error |
||||
* code. |
||||
*/ |
||||
int mbox_recv(struct mbox_chan *chan, void *data, ulong timeout_us); |
||||
|
||||
#endif |
@ -0,0 +1,83 @@ |
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0 |
||||
*/ |
||||
|
||||
#ifndef _MAILBOX_UCLASS_H |
||||
#define _MAILBOX_UCLASS_H |
||||
|
||||
/* See mailbox_client.h for background documentation. */ |
||||
|
||||
#include <mailbox_client.h> |
||||
|
||||
struct udevice; |
||||
|
||||
/**
|
||||
* struct mbox_ops - The functions that a mailbox driver must implement. |
||||
*/ |
||||
struct mbox_ops { |
||||
/**
|
||||
* of_xlate - Translate a client's device-tree (OF) mailbox specifier. |
||||
* |
||||
* The mailbox core calls this function as the first step in |
||||
* implementing a client's mbox_get_by_*() call. |
||||
* |
||||
* If this function pointer is set to NULL, the mailbox core will use |
||||
* a default implementation, which assumes #mbox-cells = <1>, and that |
||||
* the DT cell contains a simple integer channel ID. |
||||
* |
||||
* At present, the mailbox API solely supports device-tree. If this |
||||
* changes, other xxx_xlate() functions may be added to support those |
||||
* other mechanisms. |
||||
* |
||||
* @chan: The channel to hold the translation result. |
||||
* @args: The mailbox specifier values from device tree. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int (*of_xlate)(struct mbox_chan *chan, |
||||
struct fdtdec_phandle_args *args); |
||||
/**
|
||||
* request - Request a translated channel. |
||||
* |
||||
* The mailbox core calls this function as the second step in |
||||
* implementing a client's mbox_get_by_*() call, following a successful |
||||
* xxx_xlate() call. |
||||
* |
||||
* @chan: The channel to request; this has been filled in by a |
||||
* previoux xxx_xlate() function call. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int (*request)(struct mbox_chan *chan); |
||||
/**
|
||||
* free - Free a previously requested channel. |
||||
* |
||||
* This is the implementation of the client mbox_free() API. |
||||
* |
||||
* @chan: The channel to free. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int (*free)(struct mbox_chan *chan); |
||||
/**
|
||||
* send - Send a message over a mailbox channel |
||||
* |
||||
* @chan: The channel to send to the message to. |
||||
* @data: A pointer to the message to send. |
||||
* @return 0 if OK, or a negative error code. |
||||
*/ |
||||
int (*send)(struct mbox_chan *chan, const void *data); |
||||
/**
|
||||
* recv - Receive any available message from the channel. |
||||
* |
||||
* This function does not block. If not message is immediately |
||||
* available, the function should return an error. |
||||
* |
||||
* @chan: The channel to receive to the message from. |
||||
* @data: A pointer to the buffer to hold the received message. |
||||
* @return 0 if OK, -ENODATA if no message was available, or a negative |
||||
* error code. |
||||
*/ |
||||
int (*recv)(struct mbox_chan *chan, void *data); |
||||
}; |
||||
|
||||
#endif |
@ -1,71 +0,0 @@ |
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc |
||||
* Written by Simon Glass <sjg@chromium.org> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#ifndef __RESET_H |
||||
#define __RESET_H |
||||
|
||||
enum reset_t { |
||||
RESET_WARM, /* Reset CPU, keep GPIOs active */ |
||||
RESET_COLD, /* Reset CPU and GPIOs */ |
||||
RESET_POWER, /* Reset PMIC (remove and restore power) */ |
||||
|
||||
RESET_COUNT, |
||||
}; |
||||
|
||||
struct reset_ops { |
||||
/**
|
||||
* request() - request a reset of the given type |
||||
* |
||||
* Note that this function may return before the reset takes effect. |
||||
* |
||||
* @type: Reset type to request |
||||
* @return -EINPROGRESS if the reset has been started and |
||||
* will complete soon, -EPROTONOSUPPORT if not supported |
||||
* by this device, 0 if the reset has already happened |
||||
* (in which case this method will not actually return) |
||||
*/ |
||||
int (*request)(struct udevice *dev, enum reset_t type); |
||||
}; |
||||
|
||||
#define reset_get_ops(dev) ((struct reset_ops *)(dev)->driver->ops) |
||||
|
||||
/**
|
||||
* reset_request() - request a reset |
||||
* |
||||
* @type: Reset type to request |
||||
* @return 0 if OK, -EPROTONOSUPPORT if not supported by this device |
||||
*/ |
||||
int reset_request(struct udevice *dev, enum reset_t type); |
||||
|
||||
/**
|
||||
* reset_walk() - cause a reset |
||||
* |
||||
* This works through the available reset devices until it finds one that can |
||||
* perform a reset. If the provided reset type is not available, the next one |
||||
* will be tried. |
||||
* |
||||
* If this function fails to reset, it will display a message and halt |
||||
* |
||||
* @type: Reset type to request |
||||
* @return -EINPROGRESS if a reset is in progress, -ENOSYS if not available |
||||
*/ |
||||
int reset_walk(enum reset_t type); |
||||
|
||||
/**
|
||||
* reset_walk_halt() - try to reset, otherwise halt |
||||
* |
||||
* This calls reset_walk(). If it returns, indicating that reset is not |
||||
* supported, it prints a message and halts. |
||||
*/ |
||||
void reset_walk_halt(enum reset_t type); |
||||
|
||||
/**
|
||||
* reset_cpu() - calls reset_walk(RESET_WARM) |
||||
*/ |
||||
void reset_cpu(ulong addr); |
||||
|
||||
#endif |
@ -0,0 +1,71 @@ |
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc |
||||
* Written by Simon Glass <sjg@chromium.org> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#ifndef __SYSRESET_H |
||||
#define __SYSRESET_H |
||||
|
||||
enum sysreset_t { |
||||
SYSRESET_WARM, /* Reset CPU, keep GPIOs active */ |
||||
SYSRESET_COLD, /* Reset CPU and GPIOs */ |
||||
SYSRESET_POWER, /* Reset PMIC (remove and restore power) */ |
||||
|
||||
SYSRESET_COUNT, |
||||
}; |
||||
|
||||
struct sysreset_ops { |
||||
/**
|
||||
* request() - request a sysreset of the given type |
||||
* |
||||
* Note that this function may return before the reset takes effect. |
||||
* |
||||
* @type: Reset type to request |
||||
* @return -EINPROGRESS if the reset has been started and |
||||
* will complete soon, -EPROTONOSUPPORT if not supported |
||||
* by this device, 0 if the reset has already happened |
||||
* (in which case this method will not actually return) |
||||
*/ |
||||
int (*request)(struct udevice *dev, enum sysreset_t type); |
||||
}; |
||||
|
||||
#define sysreset_get_ops(dev) ((struct sysreset_ops *)(dev)->driver->ops) |
||||
|
||||
/**
|
||||
* sysreset_request() - request a sysreset |
||||
* |
||||
* @type: Reset type to request |
||||
* @return 0 if OK, -EPROTONOSUPPORT if not supported by this device |
||||
*/ |
||||
int sysreset_request(struct udevice *dev, enum sysreset_t type); |
||||
|
||||
/**
|
||||
* sysreset_walk() - cause a system reset |
||||
* |
||||
* This works through the available sysreset devices until it finds one that can |
||||
* perform a reset. If the provided sysreset type is not available, the next one |
||||
* will be tried. |
||||
* |
||||
* If this function fails to reset, it will display a message and halt |
||||
* |
||||
* @type: Reset type to request |
||||
* @return -EINPROGRESS if a reset is in progress, -ENOSYS if not available |
||||
*/ |
||||
int sysreset_walk(enum sysreset_t type); |
||||
|
||||
/**
|
||||
* sysreset_walk_halt() - try to reset, otherwise halt |
||||
* |
||||
* This calls sysreset_walk(). If it returns, indicating that reset is not |
||||
* supported, it prints a message and halts. |
||||
*/ |
||||
void sysreset_walk_halt(enum sysreset_t type); |
||||
|
||||
/**
|
||||
* reset_cpu() - calls sysreset_walk(SYSRESET_WARM) |
||||
*/ |
||||
void reset_cpu(ulong addr); |
||||
|
||||
#endif |
@ -0,0 +1,31 @@ |
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0 |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <dm/test.h> |
||||
#include <asm/mbox.h> |
||||
#include <test/ut.h> |
||||
|
||||
static int dm_test_mailbox(struct unit_test_state *uts) |
||||
{ |
||||
struct udevice *dev; |
||||
uint32_t msg; |
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "mbox-test", &dev)); |
||||
ut_assertok(sandbox_mbox_test_get(dev)); |
||||
|
||||
ut_asserteq(-ETIMEDOUT, sandbox_mbox_test_recv(dev, &msg)); |
||||
ut_assertok(sandbox_mbox_test_send(dev, 0xaaff9955UL)); |
||||
ut_assertok(sandbox_mbox_test_recv(dev, &msg)); |
||||
ut_asserteq(msg, 0xaaff9955UL ^ SANDBOX_MBOX_PING_XOR); |
||||
ut_asserteq(-ETIMEDOUT, sandbox_mbox_test_recv(dev, &msg)); |
||||
|
||||
ut_assertok(sandbox_mbox_test_free(dev)); |
||||
|
||||
return 0; |
||||
} |
||||
DM_TEST(dm_test_mailbox, DM_TESTF_SCAN_FDT); |
@ -1,74 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <reset.h> |
||||
#include <asm/state.h> |
||||
#include <asm/test.h> |
||||
#include <dm/test.h> |
||||
#include <test/ut.h> |
||||
|
||||
/* Test that we can use particular reset devices */ |
||||
static int dm_test_reset_base(struct unit_test_state *uts) |
||||
{ |
||||
struct sandbox_state *state = state_get_current(); |
||||
struct udevice *dev; |
||||
|
||||
/* Device 0 is the platform data device - it should never respond */ |
||||
ut_assertok(uclass_get_device(UCLASS_RESET, 0, &dev)); |
||||
ut_asserteq(-ENODEV, reset_request(dev, RESET_WARM)); |
||||
ut_asserteq(-ENODEV, reset_request(dev, RESET_COLD)); |
||||
ut_asserteq(-ENODEV, reset_request(dev, RESET_POWER)); |
||||
|
||||
/* Device 1 is the warm reset device */ |
||||
ut_assertok(uclass_get_device(UCLASS_RESET, 1, &dev)); |
||||
ut_asserteq(-EACCES, reset_request(dev, RESET_WARM)); |
||||
ut_asserteq(-ENOSYS, reset_request(dev, RESET_COLD)); |
||||
ut_asserteq(-ENOSYS, reset_request(dev, RESET_POWER)); |
||||
|
||||
state->reset_allowed[RESET_WARM] = true; |
||||
ut_asserteq(-EINPROGRESS, reset_request(dev, RESET_WARM)); |
||||
state->reset_allowed[RESET_WARM] = false; |
||||
|
||||
/* Device 2 is the cold reset device */ |
||||
ut_assertok(uclass_get_device(UCLASS_RESET, 2, &dev)); |
||||
ut_asserteq(-ENOSYS, reset_request(dev, RESET_WARM)); |
||||
ut_asserteq(-EACCES, reset_request(dev, RESET_COLD)); |
||||
state->reset_allowed[RESET_POWER] = false; |
||||
ut_asserteq(-EACCES, reset_request(dev, RESET_POWER)); |
||||
state->reset_allowed[RESET_POWER] = true; |
||||
|
||||
return 0; |
||||
} |
||||
DM_TEST(dm_test_reset_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |
||||
|
||||
/* Test that we can walk through the reset devices */ |
||||
static int dm_test_reset_walk(struct unit_test_state *uts) |
||||
{ |
||||
struct sandbox_state *state = state_get_current(); |
||||
|
||||
/* If we generate a power reset, we will exit sandbox! */ |
||||
state->reset_allowed[RESET_POWER] = false; |
||||
ut_asserteq(-EACCES, reset_walk(RESET_WARM)); |
||||
ut_asserteq(-EACCES, reset_walk(RESET_COLD)); |
||||
ut_asserteq(-EACCES, reset_walk(RESET_POWER)); |
||||
|
||||
/*
|
||||
* Enable cold reset - this should make cold reset work, plus a warm |
||||
* reset should be promoted to cold, since this is the next step |
||||
* along. |
||||
*/ |
||||
state->reset_allowed[RESET_COLD] = true; |
||||
ut_asserteq(-EINPROGRESS, reset_walk(RESET_WARM)); |
||||
ut_asserteq(-EINPROGRESS, reset_walk(RESET_COLD)); |
||||
ut_asserteq(-EACCES, reset_walk(RESET_POWER)); |
||||
state->reset_allowed[RESET_COLD] = false; |
||||
state->reset_allowed[RESET_POWER] = true; |
||||
|
||||
return 0; |
||||
} |
||||
DM_TEST(dm_test_reset_walk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |
@ -0,0 +1,74 @@ |
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <sysreset.h> |
||||
#include <asm/state.h> |
||||
#include <asm/test.h> |
||||
#include <dm/test.h> |
||||
#include <test/ut.h> |
||||
|
||||
/* Test that we can use particular sysreset devices */ |
||||
static int dm_test_sysreset_base(struct unit_test_state *uts) |
||||
{ |
||||
struct sandbox_state *state = state_get_current(); |
||||
struct udevice *dev; |
||||
|
||||
/* Device 0 is the platform data device - it should never respond */ |
||||
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 0, &dev)); |
||||
ut_asserteq(-ENODEV, sysreset_request(dev, SYSRESET_WARM)); |
||||
ut_asserteq(-ENODEV, sysreset_request(dev, SYSRESET_COLD)); |
||||
ut_asserteq(-ENODEV, sysreset_request(dev, SYSRESET_POWER)); |
||||
|
||||
/* Device 1 is the warm sysreset device */ |
||||
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev)); |
||||
ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_WARM)); |
||||
ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_COLD)); |
||||
ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_POWER)); |
||||
|
||||
state->sysreset_allowed[SYSRESET_WARM] = true; |
||||
ut_asserteq(-EINPROGRESS, sysreset_request(dev, SYSRESET_WARM)); |
||||
state->sysreset_allowed[SYSRESET_WARM] = false; |
||||
|
||||
/* Device 2 is the cold sysreset device */ |
||||
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); |
||||
ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_WARM)); |
||||
ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_COLD)); |
||||
state->sysreset_allowed[SYSRESET_POWER] = false; |
||||
ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_POWER)); |
||||
state->sysreset_allowed[SYSRESET_POWER] = true; |
||||
|
||||
return 0; |
||||
} |
||||
DM_TEST(dm_test_sysreset_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |
||||
|
||||
/* Test that we can walk through the sysreset devices */ |
||||
static int dm_test_sysreset_walk(struct unit_test_state *uts) |
||||
{ |
||||
struct sandbox_state *state = state_get_current(); |
||||
|
||||
/* If we generate a power sysreset, we will exit sandbox! */ |
||||
state->sysreset_allowed[SYSRESET_POWER] = false; |
||||
ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); |
||||
ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); |
||||
ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); |
||||
|
||||
/*
|
||||
* Enable cold system reset - this should make cold system reset work, |
||||
* plus a warm system reset should be promoted to cold, since this is |
||||
* the next step along. |
||||
*/ |
||||
state->sysreset_allowed[SYSRESET_COLD] = true; |
||||
ut_asserteq(-EINPROGRESS, sysreset_walk(SYSRESET_WARM)); |
||||
ut_asserteq(-EINPROGRESS, sysreset_walk(SYSRESET_COLD)); |
||||
ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); |
||||
state->sysreset_allowed[SYSRESET_COLD] = false; |
||||
state->sysreset_allowed[SYSRESET_POWER] = true; |
||||
|
||||
return 0; |
||||
} |
||||
DM_TEST(dm_test_sysreset_walk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |
Loading…
Reference in new issue