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 }; 124