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 #include <dm/root.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn, 18 uint offset, ulong value, 19 enum pci_size_t size) 20 { 21 struct dm_pci_emul_ops *ops; 22 struct udevice *emul; 23 int ret; 24 25 ret = sandbox_pci_get_emul(bus, devfn, &emul); 26 if (ret) 27 return ret == -ENODEV ? 0 : ret; 28 ops = pci_get_emul_ops(emul); 29 if (!ops || !ops->write_config) 30 return -ENOSYS; 31 32 return ops->write_config(emul, offset, value, size); 33 } 34 35 static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn, 36 uint offset, ulong *valuep, 37 enum pci_size_t size) 38 { 39 struct dm_pci_emul_ops *ops; 40 struct udevice *emul; 41 int ret; 42 43 /* Prepare the default response */ 44 *valuep = pci_get_ff(size); 45 ret = sandbox_pci_get_emul(bus, devfn, &emul); 46 if (ret) 47 return ret == -ENODEV ? 0 : ret; 48 ops = pci_get_emul_ops(emul); 49 if (!ops || !ops->read_config) 50 return -ENOSYS; 51 52 return ops->read_config(emul, offset, valuep, size); 53 } 54 55 static int sandbox_pci_child_post_bind(struct udevice *dev) 56 { 57 /* Attach an emulator if we can */ 58 return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); 59 } 60 61 static const struct dm_pci_ops sandbox_pci_ops = { 62 .read_config = sandbox_pci_read_config, 63 .write_config = sandbox_pci_write_config, 64 }; 65 66 static const struct udevice_id sandbox_pci_ids[] = { 67 { .compatible = "sandbox,pci" }, 68 { } 69 }; 70 71 U_BOOT_DRIVER(pci_sandbox) = { 72 .name = "pci_sandbox", 73 .id = UCLASS_PCI, 74 .of_match = sandbox_pci_ids, 75 .ops = &sandbox_pci_ops, 76 .child_post_bind = sandbox_pci_child_post_bind, 77 .per_child_platdata_auto_alloc_size = 78 sizeof(struct pci_child_platdata), 79 }; 80