Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | // SPDX-License-Identifier: GPL-2.0+ /* * Sandbox interface for QFW * * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com> * (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee> */ #define LOG_CATEGORY UCLASS_QFW #include <asm/types.h> #include <asm/io.h> #include <dm.h> #include <dm/device.h> #include <qfw.h> struct qfw_sandbox_plat { u8 file_dir_offset; }; static void qfw_sandbox_read_entry_io(struct udevice *dev, u16 entry, u32 size, void *address) { debug("%s: entry 0x%x size %u address %p\n", __func__, entry, size, address); switch (entry) { case FW_CFG_SIGNATURE: if (size == 4) *((u32 *)address) = cpu_to_be32(QEMU_FW_CFG_SIGNATURE); break; case FW_CFG_ID: /* Advertise DMA support */ if (size == 1) *((u8 *)address) = FW_CFG_DMA_ENABLED; break; default: debug("%s got unsupported entry 0x%x\n", __func__, entry); /* * Sandbox driver doesn't support other entries here, assume we use DMA * to read them -- the uclass driver will exclusively use it when * advertised. */ } } static void qfw_sandbox_read_entry_dma(struct udevice *dev, struct qfw_dma *dma) { u16 entry; u32 control = be32_to_cpu(dma->control); void *address = (void *)(uintptr_t)be64_to_cpu(dma->address); u32 length = be32_to_cpu(dma->length); struct qfw_sandbox_plat *plat = dev_get_plat(dev); struct fw_cfg_file *file; debug("%s\n", __func__); if (!(control & FW_CFG_DMA_READ)) return; if (control & FW_CFG_DMA_SELECT) { /* Start new read. */ entry = control >> 16; /* Arbitrary values to be used by tests. */ switch (entry) { case FW_CFG_NB_CPUS: if (length == 2) *((u16 *)address) = cpu_to_le16(5); break; case FW_CFG_FILE_DIR: if (length == 4) { *((u32 *)address) = cpu_to_be32(2); plat->file_dir_offset = 1; } break; default: debug("%s got unsupported entry 0x%x\n", __func__, entry); } } else if (plat->file_dir_offset && length == 64) { file = address; switch (plat->file_dir_offset) { case 1: file->size = cpu_to_be32(8); file->select = cpu_to_be16(FW_CFG_FILE_FIRST); strcpy(file->name, "test-one"); plat->file_dir_offset++; break; case 2: file->size = cpu_to_be32(8); file->select = cpu_to_be16(FW_CFG_FILE_FIRST + 1); strcpy(file->name, "test-two"); plat->file_dir_offset++; break; } } /* * Signal that we are finished. No-one checks this in sandbox -- * normally the platform-specific driver looks for it -- but let's * replicate the behaviour in case someone relies on it later. */ dma->control = 0; } static int qfw_sandbox_probe(struct udevice *dev) { return qfw_register(dev); } static struct dm_qfw_ops qfw_sandbox_ops = { .read_entry_io = qfw_sandbox_read_entry_io, .read_entry_dma = qfw_sandbox_read_entry_dma, }; U_BOOT_DRIVER(qfw_sandbox) = { .name = "qfw_sandbox", .id = UCLASS_QFW, .plat_auto = sizeof(struct qfw_sandbox_plat), .probe = qfw_sandbox_probe, .ops = &qfw_sandbox_ops, }; U_BOOT_DRVINFO(qfw_sandbox) = { .name = "qfw_sandbox", }; |