1*9a8bcabdSMario Six // SPDX-License-Identifier: GPL-2.0+
2*9a8bcabdSMario Six /*
3*9a8bcabdSMario Six * (C) Copyright 2018
4*9a8bcabdSMario Six * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5*9a8bcabdSMario Six */
6*9a8bcabdSMario Six
7*9a8bcabdSMario Six #include <common.h>
8*9a8bcabdSMario Six #include <axi.h>
9*9a8bcabdSMario Six #include <dm.h>
10*9a8bcabdSMario Six
11*9a8bcabdSMario Six /**
12*9a8bcabdSMario Six * struct sandbox_store_priv - Private data structure of a AXI store device
13*9a8bcabdSMario Six * @store: The buffer holding the device's internal memory, which is read from
14*9a8bcabdSMario Six * and written to using the driver's methods
15*9a8bcabdSMario Six */
16*9a8bcabdSMario Six struct sandbox_store_priv {
17*9a8bcabdSMario Six u8 *store;
18*9a8bcabdSMario Six };
19*9a8bcabdSMario Six
20*9a8bcabdSMario Six /**
21*9a8bcabdSMario Six * copy_axi_data() - Copy data from source to destination with a given AXI
22*9a8bcabdSMario Six * transfer width
23*9a8bcabdSMario Six * @src: Pointer to the data source from where data will be read
24*9a8bcabdSMario Six * @dst: Pointer to the data destination where data will be written to
25*9a8bcabdSMario Six * @size: Size of the data to be copied given by a axi_size_t enum value
26*9a8bcabdSMario Six *
27*9a8bcabdSMario Six * Return: 0 if OK, -ve on error
28*9a8bcabdSMario Six */
copy_axi_data(void * src,void * dst,enum axi_size_t size)29*9a8bcabdSMario Six static int copy_axi_data(void *src, void *dst, enum axi_size_t size)
30*9a8bcabdSMario Six {
31*9a8bcabdSMario Six switch (size) {
32*9a8bcabdSMario Six case AXI_SIZE_8:
33*9a8bcabdSMario Six *((u8 *)dst) = *((u8 *)src);
34*9a8bcabdSMario Six return 0;
35*9a8bcabdSMario Six case AXI_SIZE_16:
36*9a8bcabdSMario Six *((u16 *)dst) = be16_to_cpu(*((u16 *)src));
37*9a8bcabdSMario Six return 0;
38*9a8bcabdSMario Six case AXI_SIZE_32:
39*9a8bcabdSMario Six *((u32 *)dst) = be32_to_cpu(*((u32 *)src));
40*9a8bcabdSMario Six return 0;
41*9a8bcabdSMario Six default:
42*9a8bcabdSMario Six debug("%s: Unknown AXI transfer size '%d'\n", __func__, size);
43*9a8bcabdSMario Six return -EINVAL;
44*9a8bcabdSMario Six }
45*9a8bcabdSMario Six }
46*9a8bcabdSMario Six
sandbox_store_read(struct udevice * dev,ulong address,void * data,enum axi_size_t size)47*9a8bcabdSMario Six static int sandbox_store_read(struct udevice *dev, ulong address, void *data,
48*9a8bcabdSMario Six enum axi_size_t size)
49*9a8bcabdSMario Six {
50*9a8bcabdSMario Six struct sandbox_store_priv *priv = dev_get_priv(dev);
51*9a8bcabdSMario Six
52*9a8bcabdSMario Six return copy_axi_data(priv->store + address, data, size);
53*9a8bcabdSMario Six }
54*9a8bcabdSMario Six
sandbox_store_write(struct udevice * dev,ulong address,void * data,enum axi_size_t size)55*9a8bcabdSMario Six static int sandbox_store_write(struct udevice *dev, ulong address, void *data,
56*9a8bcabdSMario Six enum axi_size_t size)
57*9a8bcabdSMario Six {
58*9a8bcabdSMario Six struct sandbox_store_priv *priv = dev_get_priv(dev);
59*9a8bcabdSMario Six
60*9a8bcabdSMario Six return copy_axi_data(data, priv->store + address, size);
61*9a8bcabdSMario Six }
62*9a8bcabdSMario Six
sandbox_store_get_store(struct udevice * dev,u8 ** store)63*9a8bcabdSMario Six static int sandbox_store_get_store(struct udevice *dev, u8 **store)
64*9a8bcabdSMario Six {
65*9a8bcabdSMario Six struct sandbox_store_priv *priv = dev_get_priv(dev);
66*9a8bcabdSMario Six
67*9a8bcabdSMario Six *store = priv->store;
68*9a8bcabdSMario Six
69*9a8bcabdSMario Six return 0;
70*9a8bcabdSMario Six }
71*9a8bcabdSMario Six
72*9a8bcabdSMario Six static const struct udevice_id sandbox_store_ids[] = {
73*9a8bcabdSMario Six { .compatible = "sandbox,sandbox_store" },
74*9a8bcabdSMario Six { /* sentinel */ }
75*9a8bcabdSMario Six };
76*9a8bcabdSMario Six
77*9a8bcabdSMario Six static const struct axi_emul_ops sandbox_store_ops = {
78*9a8bcabdSMario Six .read = sandbox_store_read,
79*9a8bcabdSMario Six .write = sandbox_store_write,
80*9a8bcabdSMario Six .get_store = sandbox_store_get_store,
81*9a8bcabdSMario Six };
82*9a8bcabdSMario Six
sandbox_store_probe(struct udevice * dev)83*9a8bcabdSMario Six static int sandbox_store_probe(struct udevice *dev)
84*9a8bcabdSMario Six {
85*9a8bcabdSMario Six struct sandbox_store_priv *priv = dev_get_priv(dev);
86*9a8bcabdSMario Six u32 reg[2];
87*9a8bcabdSMario Six int ret;
88*9a8bcabdSMario Six
89*9a8bcabdSMario Six ret = dev_read_u32_array(dev, "reg", reg, ARRAY_SIZE(reg));
90*9a8bcabdSMario Six if (ret) {
91*9a8bcabdSMario Six debug("%s: Could not read 'reg' property\n", dev->name);
92*9a8bcabdSMario Six return -EINVAL;
93*9a8bcabdSMario Six }
94*9a8bcabdSMario Six
95*9a8bcabdSMario Six /*
96*9a8bcabdSMario Six * Allocate the device's internal storage that will be read
97*9a8bcabdSMario Six * from/written to
98*9a8bcabdSMario Six */
99*9a8bcabdSMario Six priv->store = calloc(reg[1], 1);
100*9a8bcabdSMario Six if (!priv->store)
101*9a8bcabdSMario Six return -ENOMEM;
102*9a8bcabdSMario Six
103*9a8bcabdSMario Six return 0;
104*9a8bcabdSMario Six }
105*9a8bcabdSMario Six
sandbox_store_remove(struct udevice * dev)106*9a8bcabdSMario Six static int sandbox_store_remove(struct udevice *dev)
107*9a8bcabdSMario Six {
108*9a8bcabdSMario Six struct sandbox_store_priv *priv = dev_get_priv(dev);
109*9a8bcabdSMario Six
110*9a8bcabdSMario Six free(priv->store);
111*9a8bcabdSMario Six
112*9a8bcabdSMario Six return 0;
113*9a8bcabdSMario Six }
114*9a8bcabdSMario Six
115*9a8bcabdSMario Six U_BOOT_DRIVER(sandbox_axi_store) = {
116*9a8bcabdSMario Six .name = "sandbox_axi_store",
117*9a8bcabdSMario Six .id = UCLASS_AXI_EMUL,
118*9a8bcabdSMario Six .of_match = sandbox_store_ids,
119*9a8bcabdSMario Six .ops = &sandbox_store_ops,
120*9a8bcabdSMario Six .priv_auto_alloc_size = sizeof(struct sandbox_store_priv),
121*9a8bcabdSMario Six .probe = sandbox_store_probe,
122*9a8bcabdSMario Six .remove = sandbox_store_remove,
123*9a8bcabdSMario Six };
124