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