1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2014 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7/*
8 * IO space access commands.
9 */
10
11#include <command.h>
12#include <dm.h>
13#include <log.h>
14#include <asm/io.h>
15
16int pci_map_physmem(phys_addr_t paddr, unsigned long *lenp,
17		    struct udevice **devp, void **ptrp)
18{
19	struct udevice *dev;
20	int ret;
21
22	*ptrp = 0;
23	for (uclass_first_device(UCLASS_PCI_EMUL, &dev);
24	     dev;
25	     uclass_next_device(&dev)) {
26		struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
27
28		if (!ops || !ops->map_physmem)
29			continue;
30		ret = (ops->map_physmem)(dev, paddr, lenp, ptrp);
31		if (ret)
32			continue;
33		*devp = dev;
34		return 0;
35	}
36
37	debug("%s: failed: addr=%pap\n", __func__, &paddr);
38	return -ENOSYS;
39}
40
41int pci_unmap_physmem(const void *vaddr, unsigned long len,
42		      struct udevice *dev)
43{
44	struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
45
46	if (!ops || !ops->unmap_physmem)
47		return -ENOSYS;
48	return (ops->unmap_physmem)(dev, vaddr, len);
49}
50
51static int pci_io_read(unsigned int addr, ulong *valuep, pci_size_t size)
52{
53	struct udevice *dev;
54	int ret;
55
56	*valuep = pci_get_ff(size);
57	for (uclass_first_device(UCLASS_PCI_EMUL, &dev);
58	     dev;
59	     uclass_next_device(&dev)) {
60		struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
61
62		if (ops && ops->read_io) {
63			ret = (ops->read_io)(dev, addr, valuep, size);
64			if (!ret)
65				return 0;
66		}
67	}
68
69	debug("%s: failed: addr=%x\n", __func__, addr);
70	return -ENOSYS;
71}
72
73static int pci_io_write(unsigned int addr, ulong value, pci_size_t size)
74{
75	struct udevice *dev;
76	int ret;
77
78	for (uclass_first_device(UCLASS_PCI_EMUL, &dev);
79	     dev;
80	     uclass_next_device(&dev)) {
81		struct dm_pci_emul_ops *ops = pci_get_emul_ops(dev);
82
83		if (ops && ops->write_io) {
84			ret = (ops->write_io)(dev, addr, value, size);
85			if (!ret)
86				return 0;
87		}
88	}
89
90	debug("%s: failed: addr=%x, value=%lx\n", __func__, addr, value);
91	return -ENOSYS;
92}
93
94int _inl(unsigned int addr)
95{
96	unsigned long value;
97	int ret;
98
99	ret = pci_io_read(addr, &value, PCI_SIZE_32);
100
101	return ret ? 0 : value;
102}
103
104int _inw(unsigned int addr)
105{
106	unsigned long value;
107	int ret;
108
109	ret = pci_io_read(addr, &value, PCI_SIZE_16);
110
111	return ret ? 0 : value;
112}
113
114int _inb(unsigned int addr)
115{
116	unsigned long value;
117	int ret;
118
119	ret = pci_io_read(addr, &value, PCI_SIZE_8);
120
121	return ret ? 0 : value;
122}
123
124void _outl(unsigned int value, unsigned int addr)
125{
126	pci_io_write(addr, value, PCI_SIZE_32);
127}
128
129void _outw(unsigned int value, unsigned int addr)
130{
131	pci_io_write(addr, value, PCI_SIZE_16);
132}
133
134void _outb(unsigned int value, unsigned int addr)
135{
136	pci_io_write(addr, value, PCI_SIZE_8);
137}
138