1 /* 2 * Copyright (c) 2014 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <fdtdec.h> 11 #include <inttypes.h> 12 #include <pci.h> 13 14 static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn, 15 uint offset, ulong value, 16 enum pci_size_t size) 17 { 18 struct dm_pci_emul_ops *ops; 19 struct udevice *emul; 20 int ret; 21 22 ret = sandbox_pci_get_emul(bus, devfn, &emul); 23 if (ret) 24 return ret == -ENODEV ? 0 : ret; 25 ops = pci_get_emul_ops(emul); 26 if (!ops || !ops->write_config) 27 return -ENOSYS; 28 29 return ops->write_config(emul, offset, value, size); 30 } 31 32 static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn, 33 uint offset, ulong *valuep, 34 enum pci_size_t size) 35 { 36 struct dm_pci_emul_ops *ops; 37 struct udevice *emul; 38 int ret; 39 40 /* Prepare the default response */ 41 *valuep = pci_get_ff(size); 42 ret = sandbox_pci_get_emul(bus, devfn, &emul); 43 if (ret) 44 return ret == -ENODEV ? 0 : ret; 45 ops = pci_get_emul_ops(emul); 46 if (!ops || !ops->read_config) 47 return -ENOSYS; 48 49 return ops->read_config(emul, offset, valuep, size); 50 } 51 52 static const struct dm_pci_ops sandbox_pci_ops = { 53 .read_config = sandbox_pci_read_config, 54 .write_config = sandbox_pci_write_config, 55 }; 56 57 static const struct udevice_id sandbox_pci_ids[] = { 58 { .compatible = "sandbox,pci" }, 59 { } 60 }; 61 62 U_BOOT_DRIVER(pci_sandbox) = { 63 .name = "pci_sandbox", 64 .id = UCLASS_PCI, 65 .of_match = sandbox_pci_ids, 66 .ops = &sandbox_pci_ops, 67 68 /* Attach an emulator if we can */ 69 .child_post_bind = dm_scan_fdt_dev, 70 .per_child_platdata_auto_alloc_size = 71 sizeof(struct pci_child_platdata), 72 }; 73