1a29e45a9SPaul Burton /*
2a29e45a9SPaul Burton * Xilinx AXI Bridge for PCI Express Driver
3a29e45a9SPaul Burton *
4a29e45a9SPaul Burton * Copyright (C) 2016 Imagination Technologies
5a29e45a9SPaul Burton *
6a29e45a9SPaul Burton * SPDX-License-Identifier: GPL-2.0
7a29e45a9SPaul Burton */
8a29e45a9SPaul Burton
9a29e45a9SPaul Burton #include <common.h>
10a29e45a9SPaul Burton #include <dm.h>
11a29e45a9SPaul Burton #include <pci.h>
12a29e45a9SPaul Burton
13a29e45a9SPaul Burton #include <asm/io.h>
14a29e45a9SPaul Burton
15a29e45a9SPaul Burton /**
16a29e45a9SPaul Burton * struct xilinx_pcie - Xilinx PCIe controller state
17a29e45a9SPaul Burton * @hose: The parent classes PCI controller state
18a29e45a9SPaul Burton * @cfg_base: The base address of memory mapped configuration space
19a29e45a9SPaul Burton */
20a29e45a9SPaul Burton struct xilinx_pcie {
21a29e45a9SPaul Burton struct pci_controller hose;
22a29e45a9SPaul Burton void *cfg_base;
23a29e45a9SPaul Burton };
24a29e45a9SPaul Burton
25a29e45a9SPaul Burton /* Register definitions */
26a29e45a9SPaul Burton #define XILINX_PCIE_REG_PSCR 0x144
27a29e45a9SPaul Burton #define XILINX_PCIE_REG_PSCR_LNKUP BIT(11)
28a29e45a9SPaul Burton
29a29e45a9SPaul Burton /**
30a29e45a9SPaul Burton * pcie_xilinx_link_up() - Check whether the PCIe link is up
31a29e45a9SPaul Burton * @pcie: Pointer to the PCI controller state
32a29e45a9SPaul Burton *
33a29e45a9SPaul Burton * Checks whether the PCIe link for the given device is up or down.
34a29e45a9SPaul Burton *
35a29e45a9SPaul Burton * Return: true if the link is up, else false
36a29e45a9SPaul Burton */
pcie_xilinx_link_up(struct xilinx_pcie * pcie)37a29e45a9SPaul Burton static bool pcie_xilinx_link_up(struct xilinx_pcie *pcie)
38a29e45a9SPaul Burton {
39a29e45a9SPaul Burton uint32_t pscr = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_PSCR);
40a29e45a9SPaul Burton
41a29e45a9SPaul Burton return pscr & XILINX_PCIE_REG_PSCR_LNKUP;
42a29e45a9SPaul Burton }
43a29e45a9SPaul Burton
44a29e45a9SPaul Burton /**
45a29e45a9SPaul Burton * pcie_xilinx_config_address() - Calculate the address of a config access
46a29e45a9SPaul Burton * @pcie: Pointer to the PCI controller state
47a29e45a9SPaul Burton * @bdf: Identifies the PCIe device to access
48a29e45a9SPaul Burton * @offset: The offset into the device's configuration space
49a29e45a9SPaul Burton * @paddress: Pointer to the pointer to write the calculates address to
50a29e45a9SPaul Burton *
51a29e45a9SPaul Burton * Calculates the address that should be accessed to perform a PCIe
52a29e45a9SPaul Burton * configuration space access for a given device identified by the PCIe
53a29e45a9SPaul Burton * controller device @pcie and the bus, device & function numbers in @bdf. If
54a29e45a9SPaul Burton * access to the device is not valid then the function will return an error
55a29e45a9SPaul Burton * code. Otherwise the address to access will be written to the pointer pointed
56a29e45a9SPaul Burton * to by @paddress.
57a29e45a9SPaul Burton *
58a29e45a9SPaul Burton * Return: 0 on success, else -ENODEV
59a29e45a9SPaul Burton */
pcie_xilinx_config_address(struct xilinx_pcie * pcie,pci_dev_t bdf,uint offset,void ** paddress)60a29e45a9SPaul Burton static int pcie_xilinx_config_address(struct xilinx_pcie *pcie, pci_dev_t bdf,
61a29e45a9SPaul Burton uint offset, void **paddress)
62a29e45a9SPaul Burton {
63a29e45a9SPaul Burton unsigned int bus = PCI_BUS(bdf);
64a29e45a9SPaul Burton unsigned int dev = PCI_DEV(bdf);
65a29e45a9SPaul Burton unsigned int func = PCI_FUNC(bdf);
66a29e45a9SPaul Burton void *addr;
67a29e45a9SPaul Burton
68a29e45a9SPaul Burton if ((bus > 0) && !pcie_xilinx_link_up(pcie))
69a29e45a9SPaul Burton return -ENODEV;
70a29e45a9SPaul Burton
71a29e45a9SPaul Burton /*
72a29e45a9SPaul Burton * Busses 0 (host-PCIe bridge) & 1 (its immediate child) are
73a29e45a9SPaul Burton * limited to a single device each.
74a29e45a9SPaul Burton */
75a29e45a9SPaul Burton if ((bus < 2) && (dev > 0))
76a29e45a9SPaul Burton return -ENODEV;
77a29e45a9SPaul Burton
78a29e45a9SPaul Burton addr = pcie->cfg_base;
79a29e45a9SPaul Burton addr += bus << 20;
80a29e45a9SPaul Burton addr += dev << 15;
81a29e45a9SPaul Burton addr += func << 12;
82a29e45a9SPaul Burton addr += offset;
83a29e45a9SPaul Burton *paddress = addr;
84a29e45a9SPaul Burton
85a29e45a9SPaul Burton return 0;
86a29e45a9SPaul Burton }
87a29e45a9SPaul Burton
88a29e45a9SPaul Burton /**
89a29e45a9SPaul Burton * pcie_xilinx_read_config() - Read from configuration space
90a29e45a9SPaul Burton * @pcie: Pointer to the PCI controller state
91a29e45a9SPaul Burton * @bdf: Identifies the PCIe device to access
92a29e45a9SPaul Burton * @offset: The offset into the device's configuration space
93a29e45a9SPaul Burton * @valuep: A pointer at which to store the read value
94a29e45a9SPaul Burton * @size: Indicates the size of access to perform
95a29e45a9SPaul Burton *
96a29e45a9SPaul Burton * Read a value of size @size from offset @offset within the configuration
97a29e45a9SPaul Burton * space of the device identified by the bus, device & function numbers in @bdf
98a29e45a9SPaul Burton * on the PCI bus @bus.
99a29e45a9SPaul Burton *
100a29e45a9SPaul Burton * Return: 0 on success, else -ENODEV or -EINVAL
101a29e45a9SPaul Burton */
pcie_xilinx_read_config(struct udevice * bus,pci_dev_t bdf,uint offset,ulong * valuep,enum pci_size_t size)102a29e45a9SPaul Burton static int pcie_xilinx_read_config(struct udevice *bus, pci_dev_t bdf,
103a29e45a9SPaul Burton uint offset, ulong *valuep,
104a29e45a9SPaul Burton enum pci_size_t size)
105a29e45a9SPaul Burton {
106a29e45a9SPaul Burton struct xilinx_pcie *pcie = dev_get_priv(bus);
107a29e45a9SPaul Burton void *address;
108a29e45a9SPaul Burton int err;
109a29e45a9SPaul Burton
110a29e45a9SPaul Burton err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
111a29e45a9SPaul Burton if (err < 0) {
112a29e45a9SPaul Burton *valuep = pci_get_ff(size);
113a29e45a9SPaul Burton return 0;
114a29e45a9SPaul Burton }
115a29e45a9SPaul Burton
116a29e45a9SPaul Burton switch (size) {
117a29e45a9SPaul Burton case PCI_SIZE_8:
118a29e45a9SPaul Burton *valuep = __raw_readb(address);
119a29e45a9SPaul Burton return 0;
120a29e45a9SPaul Burton case PCI_SIZE_16:
121a29e45a9SPaul Burton *valuep = __raw_readw(address);
122a29e45a9SPaul Burton return 0;
123a29e45a9SPaul Burton case PCI_SIZE_32:
124a29e45a9SPaul Burton *valuep = __raw_readl(address);
125a29e45a9SPaul Burton return 0;
126a29e45a9SPaul Burton default:
127a29e45a9SPaul Burton return -EINVAL;
128a29e45a9SPaul Burton }
129a29e45a9SPaul Burton }
130a29e45a9SPaul Burton
131a29e45a9SPaul Burton /**
132a29e45a9SPaul Burton * pcie_xilinx_write_config() - Write to configuration space
133a29e45a9SPaul Burton * @pcie: Pointer to the PCI controller state
134a29e45a9SPaul Burton * @bdf: Identifies the PCIe device to access
135a29e45a9SPaul Burton * @offset: The offset into the device's configuration space
136a29e45a9SPaul Burton * @value: The value to write
137a29e45a9SPaul Burton * @size: Indicates the size of access to perform
138a29e45a9SPaul Burton *
139a29e45a9SPaul Burton * Write the value @value of size @size from offset @offset within the
140a29e45a9SPaul Burton * configuration space of the device identified by the bus, device & function
141a29e45a9SPaul Burton * numbers in @bdf on the PCI bus @bus.
142a29e45a9SPaul Burton *
143a29e45a9SPaul Burton * Return: 0 on success, else -ENODEV or -EINVAL
144a29e45a9SPaul Burton */
pcie_xilinx_write_config(struct udevice * bus,pci_dev_t bdf,uint offset,ulong value,enum pci_size_t size)145a29e45a9SPaul Burton static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf,
146a29e45a9SPaul Burton uint offset, ulong value,
147a29e45a9SPaul Burton enum pci_size_t size)
148a29e45a9SPaul Burton {
149a29e45a9SPaul Burton struct xilinx_pcie *pcie = dev_get_priv(bus);
150a29e45a9SPaul Burton void *address;
151a29e45a9SPaul Burton int err;
152a29e45a9SPaul Burton
153a29e45a9SPaul Burton err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
154a29e45a9SPaul Burton if (err < 0)
155a29e45a9SPaul Burton return 0;
156a29e45a9SPaul Burton
157a29e45a9SPaul Burton switch (size) {
158a29e45a9SPaul Burton case PCI_SIZE_8:
159a29e45a9SPaul Burton __raw_writeb(value, address);
160a29e45a9SPaul Burton return 0;
161a29e45a9SPaul Burton case PCI_SIZE_16:
162a29e45a9SPaul Burton __raw_writew(value, address);
163a29e45a9SPaul Burton return 0;
164a29e45a9SPaul Burton case PCI_SIZE_32:
165a29e45a9SPaul Burton __raw_writel(value, address);
166a29e45a9SPaul Burton return 0;
167a29e45a9SPaul Burton default:
168a29e45a9SPaul Burton return -EINVAL;
169a29e45a9SPaul Burton }
170a29e45a9SPaul Burton }
171a29e45a9SPaul Burton
172a29e45a9SPaul Burton /**
173a29e45a9SPaul Burton * pcie_xilinx_ofdata_to_platdata() - Translate from DT to device state
174a29e45a9SPaul Burton * @dev: A pointer to the device being operated on
175a29e45a9SPaul Burton *
176a29e45a9SPaul Burton * Translate relevant data from the device tree pertaining to device @dev into
177a29e45a9SPaul Burton * state that the driver will later make use of. This state is stored in the
178a29e45a9SPaul Burton * device's private data structure.
179a29e45a9SPaul Burton *
180a29e45a9SPaul Burton * Return: 0 on success, else -EINVAL
181a29e45a9SPaul Burton */
pcie_xilinx_ofdata_to_platdata(struct udevice * dev)182a29e45a9SPaul Burton static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev)
183a29e45a9SPaul Burton {
184a29e45a9SPaul Burton struct xilinx_pcie *pcie = dev_get_priv(dev);
185a29e45a9SPaul Burton struct fdt_resource reg_res;
186a29e45a9SPaul Burton DECLARE_GLOBAL_DATA_PTR;
187a29e45a9SPaul Burton int err;
188a29e45a9SPaul Burton
189e160f7d4SSimon Glass err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
190a29e45a9SPaul Burton 0, ®_res);
191a29e45a9SPaul Burton if (err < 0) {
192*90aa625cSMasahiro Yamada pr_err("\"reg\" resource not found\n");
193a29e45a9SPaul Burton return err;
194a29e45a9SPaul Burton }
195a29e45a9SPaul Burton
196a29e45a9SPaul Burton pcie->cfg_base = map_physmem(reg_res.start,
197a29e45a9SPaul Burton fdt_resource_size(®_res),
198a29e45a9SPaul Burton MAP_NOCACHE);
199a29e45a9SPaul Burton
200a29e45a9SPaul Burton return 0;
201a29e45a9SPaul Burton }
202a29e45a9SPaul Burton
203a29e45a9SPaul Burton static const struct dm_pci_ops pcie_xilinx_ops = {
204a29e45a9SPaul Burton .read_config = pcie_xilinx_read_config,
205a29e45a9SPaul Burton .write_config = pcie_xilinx_write_config,
206a29e45a9SPaul Burton };
207a29e45a9SPaul Burton
208a29e45a9SPaul Burton static const struct udevice_id pcie_xilinx_ids[] = {
209a29e45a9SPaul Burton { .compatible = "xlnx,axi-pcie-host-1.00.a" },
210a29e45a9SPaul Burton { }
211a29e45a9SPaul Burton };
212a29e45a9SPaul Burton
213a29e45a9SPaul Burton U_BOOT_DRIVER(pcie_xilinx) = {
214a29e45a9SPaul Burton .name = "pcie_xilinx",
215a29e45a9SPaul Burton .id = UCLASS_PCI,
216a29e45a9SPaul Burton .of_match = pcie_xilinx_ids,
217a29e45a9SPaul Burton .ops = &pcie_xilinx_ops,
218a29e45a9SPaul Burton .ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata,
219a29e45a9SPaul Burton .priv_auto_alloc_size = sizeof(struct xilinx_pcie),
220a29e45a9SPaul Burton };
221