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