mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-09-19 21:01:51 +02:00
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"' I failed to notice that b4 noticed it was based on next and so took that as the base commit and merged that part of next to master. This reverts commit c8ffd1356d42223cbb8c86280a083cc3c93e6426, reversing changes made to 2ee6f3a5f7550de3599faef9704e166e5dcace35. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
137 lines
3.2 KiB
C
137 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2014 Google, Inc
|
|
* Written by Simon Glass <sjg@chromium.org>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <fdtdec.h>
|
|
#include <log.h>
|
|
#include <pci.h>
|
|
|
|
#define FDT_DEV_INFO_CELLS 4
|
|
#define FDT_DEV_INFO_SIZE (FDT_DEV_INFO_CELLS * sizeof(u32))
|
|
|
|
#define SANDBOX_PCI_DEVFN(d, f) ((d << 3) | f)
|
|
|
|
struct sandbox_pci_priv {
|
|
struct {
|
|
u16 vendor;
|
|
u16 device;
|
|
} vendev[256];
|
|
};
|
|
|
|
static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn,
|
|
uint offset, ulong value,
|
|
enum pci_size_t size)
|
|
{
|
|
struct dm_pci_emul_ops *ops;
|
|
struct udevice *container, *emul;
|
|
int ret;
|
|
|
|
ret = sandbox_pci_get_emul(bus, devfn, &container, &emul);
|
|
if (ret)
|
|
return ret == -ENODEV ? 0 : ret;
|
|
ops = pci_get_emul_ops(emul);
|
|
if (!ops || !ops->write_config)
|
|
return -ENOSYS;
|
|
|
|
return ops->write_config(emul, offset, value, size);
|
|
}
|
|
|
|
static int sandbox_pci_read_config(const struct udevice *bus, pci_dev_t devfn,
|
|
uint offset, ulong *valuep,
|
|
enum pci_size_t size)
|
|
{
|
|
struct dm_pci_emul_ops *ops;
|
|
struct udevice *container, *emul;
|
|
struct sandbox_pci_priv *priv = dev_get_priv(bus);
|
|
int ret;
|
|
|
|
/* Prepare the default response */
|
|
*valuep = pci_get_ff(size);
|
|
ret = sandbox_pci_get_emul(bus, devfn, &container, &emul);
|
|
if (ret) {
|
|
if (!container) {
|
|
u16 vendor, device;
|
|
|
|
devfn = SANDBOX_PCI_DEVFN(PCI_DEV(devfn),
|
|
PCI_FUNC(devfn));
|
|
vendor = priv->vendev[devfn].vendor;
|
|
device = priv->vendev[devfn].device;
|
|
if (offset == PCI_VENDOR_ID && vendor)
|
|
*valuep = vendor;
|
|
else if (offset == PCI_DEVICE_ID && device)
|
|
*valuep = device;
|
|
|
|
return 0;
|
|
} else {
|
|
return ret == -ENODEV ? 0 : ret;
|
|
}
|
|
}
|
|
ops = pci_get_emul_ops(emul);
|
|
if (!ops || !ops->read_config)
|
|
return -ENOSYS;
|
|
|
|
return ops->read_config(emul, offset, valuep, size);
|
|
}
|
|
|
|
static int sandbox_pci_probe(struct udevice *dev)
|
|
{
|
|
struct sandbox_pci_priv *priv = dev_get_priv(dev);
|
|
const fdt32_t *cell;
|
|
u8 pdev, pfn, devfn;
|
|
int len;
|
|
|
|
cell = ofnode_get_property(dev_ofnode(dev), "sandbox,dev-info", &len);
|
|
if (!cell)
|
|
return 0;
|
|
|
|
if ((len % FDT_DEV_INFO_SIZE) == 0) {
|
|
int num = len / FDT_DEV_INFO_SIZE;
|
|
int i;
|
|
|
|
for (i = 0; i < num; i++) {
|
|
debug("dev info #%d: %02x %02x %04x %04x\n", i,
|
|
fdt32_to_cpu(cell[0]), fdt32_to_cpu(cell[1]),
|
|
fdt32_to_cpu(cell[2]), fdt32_to_cpu(cell[3]));
|
|
|
|
pdev = fdt32_to_cpu(cell[0]);
|
|
pfn = fdt32_to_cpu(cell[1]);
|
|
if (pdev > 31 || pfn > 7)
|
|
continue;
|
|
devfn = SANDBOX_PCI_DEVFN(pdev, pfn);
|
|
priv->vendev[devfn].vendor = fdt32_to_cpu(cell[2]);
|
|
priv->vendev[devfn].device = fdt32_to_cpu(cell[3]);
|
|
|
|
cell += FDT_DEV_INFO_CELLS;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct dm_pci_ops sandbox_pci_ops = {
|
|
.read_config = sandbox_pci_read_config,
|
|
.write_config = sandbox_pci_write_config,
|
|
};
|
|
|
|
static const struct udevice_id sandbox_pci_ids[] = {
|
|
{ .compatible = "sandbox,pci" },
|
|
{ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(pci_sandbox) = {
|
|
.name = "pci_sandbox",
|
|
.id = UCLASS_PCI,
|
|
.of_match = sandbox_pci_ids,
|
|
.ops = &sandbox_pci_ops,
|
|
.probe = sandbox_pci_probe,
|
|
.priv_auto = sizeof(struct sandbox_pci_priv),
|
|
|
|
/* Attach an emulator if we can */
|
|
.child_post_bind = dm_scan_fdt_dev,
|
|
.per_child_plat_auto = sizeof(struct pci_child_plat),
|
|
};
|