1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2018
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 */
6
7#include <common.h>
8#include <axi.h>
9#include <dm.h>
10#include <asm/axi.h>
11
12/*
13 * This driver implements a AXI bus for the sandbox architecture for testing
14 * purposes.
15 *
16 * The bus forwards every access to it to a special AXI emulation device (which
17 * it gets via the axi_emul_get_ops function) that implements a simple
18 * read/write storage.
19 *
20 * The emulator device must still be contained in the device tree in the usual
21 * way, since configuration data for the storage is read from the DT.
22 */
23
24static int axi_sandbox_read(struct udevice *bus, ulong address, void *data,
25			    enum axi_size_t size)
26{
27	struct axi_emul_ops *ops;
28	struct udevice *emul;
29	int ret;
30
31	/* Get emulator device */
32	ret = axi_sandbox_get_emul(bus, address, size, &emul);
33	if (ret)
34		return ret == -ENODEV ? 0 : ret;
35	/* Forward all reads to the AXI emulator */
36	ops = axi_emul_get_ops(emul);
37	if (!ops || !ops->read)
38		return -ENOSYS;
39
40	return ops->read(emul, address, data, size);
41}
42
43static int axi_sandbox_write(struct udevice *bus, ulong address, void *data,
44			     enum axi_size_t size)
45{
46	struct axi_emul_ops *ops;
47	struct udevice *emul;
48	int ret;
49
50	/* Get emulator device */
51	ret = axi_sandbox_get_emul(bus, address, size, &emul);
52	if (ret)
53		return ret == -ENODEV ? 0 : ret;
54	/* Forward all writes to the AXI emulator */
55	ops = axi_emul_get_ops(emul);
56	if (!ops || !ops->write)
57		return -ENOSYS;
58
59	return ops->write(emul, address, data, size);
60}
61
62static const struct udevice_id axi_sandbox_ids[] = {
63	{ .compatible = "sandbox,axi" },
64	{ /* sentinel */ }
65};
66
67static const struct axi_ops axi_sandbox_ops = {
68	.read = axi_sandbox_read,
69	.write = axi_sandbox_write,
70};
71
72U_BOOT_DRIVER(axi_sandbox_bus) = {
73	.name           = "axi_sandbox_bus",
74	.id             = UCLASS_AXI,
75	.of_match       = axi_sandbox_ids,
76	.ops		= &axi_sandbox_ops,
77};
78