blob: 0de124f315f3486967dacebab2e94198123c161d [file] [log] [blame]
/*
* Copyright (c) 2014 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* IO space access commands.
*/
#include <common.h>
#include <command.h>
#include <dm.h>
#include <asm/io.h>
int pci_map_physmem(phys_addr_t paddr, unsigned long *lenp,
struct udevice **devp, void **ptrp)
{
struct udevice *dev;
int ret;
*ptrp = 0;
for (uclass_first_device(UCLASS_PCI_EMUL, &dev);
dev;
uclass_next_device(&dev)) {
struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
if (!ops || !ops->map_physmem)
continue;
ret = (ops->map_physmem)(dev, paddr, lenp, ptrp);
if (ret)
continue;
*devp = dev;
return 0;
}
debug("%s: failed: addr=%x\n", __func__, paddr);
return -ENOSYS;
}
int pci_unmap_physmem(const void *vaddr, unsigned long len,
struct udevice *dev)
{
struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
if (!ops || !ops->unmap_physmem)
return -ENOSYS;
return (ops->unmap_physmem)(dev, vaddr, len);
}
static int pci_io_read(unsigned int addr, ulong *valuep, pci_size_t size)
{
struct udevice *dev;
int ret;
*valuep = pci_get_ff(size);
for (uclass_first_device(UCLASS_PCI_EMUL, &dev);
dev;
uclass_next_device(&dev)) {
struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
if (ops && ops->read_io) {
ret = (ops->read_io)(dev, addr, valuep, size);
if (!ret)
return 0;
}
}
debug("%s: failed: addr=%x\n", __func__, addr);
return -ENOSYS;
}
static int pci_io_write(unsigned int addr, ulong value, pci_size_t size)
{
struct udevice *dev;
int ret;
for (uclass_first_device(UCLASS_PCI_EMUL, &dev);
dev;
uclass_next_device(&dev)) {
struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
if (ops && ops->write_io) {
ret = (ops->write_io)(dev, addr, value, size);
if (!ret)
return 0;
}
}
debug("%s: failed: addr=%x, value=%lx\n", __func__, addr, value);
return -ENOSYS;
}
int inl(unsigned int addr)
{
unsigned long value;
int ret;
ret = pci_io_read(addr, &value, PCI_SIZE_32);
return ret ? 0 : value;
}
int inw(unsigned int addr)
{
unsigned long value;
int ret;
ret = pci_io_read(addr, &value, PCI_SIZE_16);
return ret ? 0 : value;
}
int inb(unsigned int addr)
{
unsigned long value;
int ret;
ret = pci_io_read(addr, &value, PCI_SIZE_8);
return ret ? 0 : value;
}
void outl(unsigned int value, unsigned int addr)
{
pci_io_write(addr, value, PCI_SIZE_32);
}
void outw(unsigned int value, unsigned int addr)
{
pci_io_write(addr, value, PCI_SIZE_16);
}
void outb(unsigned int value, unsigned int addr)
{
pci_io_write(addr, value, PCI_SIZE_8);
}