xref: /rk3399_rockchip-uboot/drivers/pci/pcie_xilinx.c (revision 90aa625c9a9e1fb7a2f001fd8e50099bacaf92b8)
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, &reg_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(&reg_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