]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/pci/pcie_ecam_generic.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[thirdparty/u-boot.git] / drivers / pci / pcie_ecam_generic.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0
3675cb04
TT
2/*
3 * Generic PCIE host provided by e.g. QEMU
4 *
5 * Heavily based on drivers/pci/pcie_xilinx.c
6 *
7 * Copyright (C) 2016 Imagination Technologies
3675cb04
TT
8 */
9
d678a59d 10#include <common.h>
3675cb04
TT
11#include <dm.h>
12#include <pci.h>
67c7f14a 13#include <linux/ioport.h>
1e94b46f 14#include <linux/printk.h>
3675cb04
TT
15
16#include <asm/io.h>
17
4f2e2280
AD
18#define TYPE_PCI 0x1
19
3675cb04
TT
20/**
21 * struct generic_ecam_pcie - generic_ecam PCIe controller state
22 * @cfg_base: The base address of memory mapped configuration space
23 */
24struct generic_ecam_pcie {
25 void *cfg_base;
f83567e0
VO
26 pci_size_t size;
27 int first_busno;
3675cb04
TT
28};
29
30/**
31 * pci_generic_ecam_conf_address() - Calculate the address of a config access
32 * @bus: Pointer to the PCI bus
33 * @bdf: Identifies the PCIe device to access
34 * @offset: The offset into the device's configuration space
35 * @paddress: Pointer to the pointer to write the calculates address to
36 *
37 * Calculates the address that should be accessed to perform a PCIe
38 * configuration space access for a given device identified by the PCIe
39 * controller device @pcie and the bus, device & function numbers in @bdf. If
40 * access to the device is not valid then the function will return an error
41 * code. Otherwise the address to access will be written to the pointer pointed
42 * to by @paddress.
43 */
c4e72c4a
SG
44static int pci_generic_ecam_conf_address(const struct udevice *bus,
45 pci_dev_t bdf, uint offset,
46 void **paddress)
3675cb04
TT
47{
48 struct generic_ecam_pcie *pcie = dev_get_priv(bus);
49 void *addr;
50
51 addr = pcie->cfg_base;
4f2e2280
AD
52
53 if (dev_get_driver_data(bus) == TYPE_PCI) {
54 addr += ((PCI_BUS(bdf) - pcie->first_busno) << 16) |
55 (PCI_DEV(bdf) << 11) | (PCI_FUNC(bdf) << 8) | offset;
56 } else {
57 addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - pcie->first_busno,
58 PCI_DEV(bdf), PCI_FUNC(bdf), offset);
59 }
3675cb04
TT
60 *paddress = addr;
61
62 return 0;
63}
64
f83567e0
VO
65static bool pci_generic_ecam_addr_valid(const struct udevice *bus,
66 pci_dev_t bdf)
67{
68 struct generic_ecam_pcie *pcie = dev_get_priv(bus);
69 int num_buses = DIV_ROUND_UP(pcie->size, 1 << 16);
70
71 return (PCI_BUS(bdf) >= pcie->first_busno &&
72 PCI_BUS(bdf) < pcie->first_busno + num_buses);
73}
74
3675cb04
TT
75/**
76 * pci_generic_ecam_read_config() - Read from configuration space
77 * @bus: Pointer to the PCI bus
78 * @bdf: Identifies the PCIe device to access
79 * @offset: The offset into the device's configuration space
80 * @valuep: A pointer at which to store the read value
81 * @size: Indicates the size of access to perform
82 *
83 * Read a value of size @size from offset @offset within the configuration
84 * space of the device identified by the bus, device & function numbers in @bdf
85 * on the PCI bus @bus.
86 */
c4e72c4a
SG
87static int pci_generic_ecam_read_config(const struct udevice *bus,
88 pci_dev_t bdf, uint offset,
89 ulong *valuep, enum pci_size_t size)
3675cb04 90{
f83567e0
VO
91 if (!pci_generic_ecam_addr_valid(bus, bdf)) {
92 *valuep = pci_get_ff(size);
93 return 0;
94 }
95
3675cb04
TT
96 return pci_generic_mmap_read_config(bus, pci_generic_ecam_conf_address,
97 bdf, offset, valuep, size);
98}
99
100/**
101 * pci_generic_ecam_write_config() - Write to configuration space
102 * @bus: Pointer to the PCI bus
103 * @bdf: Identifies the PCIe device to access
104 * @offset: The offset into the device's configuration space
105 * @value: The value to write
106 * @size: Indicates the size of access to perform
107 *
108 * Write the value @value of size @size from offset @offset within the
109 * configuration space of the device identified by the bus, device & function
110 * numbers in @bdf on the PCI bus @bus.
111 */
112static int pci_generic_ecam_write_config(struct udevice *bus, pci_dev_t bdf,
113 uint offset, ulong value,
114 enum pci_size_t size)
115{
f83567e0
VO
116 if (!pci_generic_ecam_addr_valid(bus, bdf))
117 return 0;
118
3675cb04
TT
119 return pci_generic_mmap_write_config(bus, pci_generic_ecam_conf_address,
120 bdf, offset, value, size);
121}
122
123/**
d1998a9f 124 * pci_generic_ecam_of_to_plat() - Translate from DT to device state
3675cb04
TT
125 * @dev: A pointer to the device being operated on
126 *
127 * Translate relevant data from the device tree pertaining to device @dev into
128 * state that the driver will later make use of. This state is stored in the
129 * device's private data structure.
130 *
131 * Return: 0 on success, else -EINVAL
132 */
d1998a9f 133static int pci_generic_ecam_of_to_plat(struct udevice *dev)
3675cb04
TT
134{
135 struct generic_ecam_pcie *pcie = dev_get_priv(dev);
67c7f14a
MK
136 ofnode node = dev_ofnode(dev);
137 struct resource reg_res;
3675cb04
TT
138 int err;
139
67c7f14a 140 err = ofnode_read_resource(node, 0, &reg_res);
3675cb04
TT
141 if (err < 0) {
142 pr_err("\"reg\" resource not found\n");
143 return err;
144 }
145
67c7f14a 146 pcie->size = resource_size(&reg_res);
f83567e0
VO
147 pcie->cfg_base = map_physmem(reg_res.start, pcie->size, MAP_NOCACHE);
148
149 return 0;
150}
151
152static int pci_generic_ecam_probe(struct udevice *dev)
153{
154 struct generic_ecam_pcie *pcie = dev_get_priv(dev);
155
8b85dfc6 156 pcie->first_busno = dev_seq(dev);
3675cb04
TT
157
158 return 0;
159}
160
161static const struct dm_pci_ops pci_generic_ecam_ops = {
162 .read_config = pci_generic_ecam_read_config,
163 .write_config = pci_generic_ecam_write_config,
164};
165
166static const struct udevice_id pci_generic_ecam_ids[] = {
4f2e2280
AD
167 { .compatible = "pci-host-ecam-generic" /* PCI-E */ },
168 { .compatible = "pci-host-cam-generic", .data = TYPE_PCI },
3675cb04
TT
169 { }
170};
171
172U_BOOT_DRIVER(pci_generic_ecam) = {
173 .name = "pci_generic_ecam",
174 .id = UCLASS_PCI,
175 .of_match = pci_generic_ecam_ids,
176 .ops = &pci_generic_ecam_ops,
f83567e0 177 .probe = pci_generic_ecam_probe,
d1998a9f 178 .of_to_plat = pci_generic_ecam_of_to_plat,
41575d8e 179 .priv_auto = sizeof(struct generic_ecam_pcie),
3675cb04 180};