1 /*
2  * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * The RPi4 has a single nonstandard PCI config region. It is broken into two
7  * pieces, the root port config registers and a window to a single device's
8  * config space which can move between devices. There isn't (yet) an
9  * authoritative public document on this since the available BCM2711 reference
10  * notes that there is a PCIe root port in the memory map but doesn't describe
11  * it. Given that it's not ECAM compliant yet reasonably simple, it makes for
12  * an excellent example of the PCI SMCCC interface.
13  *
14  * The PCI SMCCC interface is described in DEN0115 available from:
15  * https://developer.arm.com/documentation/den0115/latest
16  */
17 
18 #include <assert.h>
19 #include <stdint.h>
20 
21 #include <common/debug.h>
22 #include <common/runtime_svc.h>
23 #include <lib/pmf/pmf.h>
24 #include <lib/runtime_instr.h>
25 #include <services/pci_svc.h>
26 #include <services/sdei.h>
27 #include <services/std_svc.h>
28 #include <smccc_helpers.h>
29 
30 #include <lib/mmio.h>
31 
32 static spinlock_t pci_lock;
33 
34 #define PCIE_REG_BASE		U(RPI_IO_BASE + 0x01500000)
35 #define PCIE_MISC_PCIE_STATUS	0x4068
36 #define PCIE_EXT_CFG_INDEX	0x9000
37 /* A small window pointing at the ECAM of the device selected by CFG_INDEX */
38 #define PCIE_EXT_CFG_DATA	0x8000
39 #define INVALID_PCI_ADDR	0xFFFFFFFF
40 
41 #define	PCIE_EXT_BUS_SHIFT	20
42 #define	PCIE_EXT_DEV_SHIFT	15
43 #define	PCIE_EXT_FUN_SHIFT	12
44 
45 
pci_segment_lib_get_base(uint32_t address,uint32_t offset)46 static uint64_t pci_segment_lib_get_base(uint32_t address, uint32_t offset)
47 {
48 	uint64_t	base;
49 	uint32_t	bus, dev, fun;
50 	uint32_t	status;
51 
52 	base = PCIE_REG_BASE;
53 
54 	offset &= PCI_OFFSET_MASK;  /* Pick off the 4k register offset */
55 
56 	/* The root port is at the base of the PCIe register space */
57 	if (address != 0U) {
58 		/*
59 		 * The current device must be at CFG_DATA, a 4K window mapped,
60 		 * via CFG_INDEX, to the device we are accessing. At the same
61 		 * time we must avoid accesses to certain areas of the cfg
62 		 * space via CFG_DATA. Detect those accesses and report that
63 		 * the address is invalid.
64 		 */
65 		base += PCIE_EXT_CFG_DATA;
66 		bus = PCI_ADDR_BUS(address);
67 		dev = PCI_ADDR_DEV(address);
68 		fun = PCI_ADDR_FUN(address);
69 		address = (bus << PCIE_EXT_BUS_SHIFT) |
70 			  (dev << PCIE_EXT_DEV_SHIFT) |
71 			  (fun << PCIE_EXT_FUN_SHIFT);
72 
73 		/* Allow only dev = 0 on root port and bus 1 */
74 		if ((bus < 2U) && (dev > 0U)) {
75 			return INVALID_PCI_ADDR;
76 		}
77 
78 		/* Assure link up before reading bus 1 */
79 		status = mmio_read_32(PCIE_REG_BASE + PCIE_MISC_PCIE_STATUS);
80 		if ((status & 0x30) != 0x30) {
81 			return INVALID_PCI_ADDR;
82 		}
83 
84 		/* Adjust which device the CFG_DATA window is pointing at */
85 		mmio_write_32(PCIE_REG_BASE + PCIE_EXT_CFG_INDEX, address);
86 	}
87 	return base + offset;
88 }
89 
90 /**
91  * pci_read_config() - Performs a config space read at addr
92  * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
93  * @off:  register offset of function described by @addr to read
94  * @sz:	  size of read (8,16,32) bits.
95  * @val:  returned zero extended value read from config space
96  *
97  * sz bits of PCI config space is read at addr:offset, and the value
98  * is returned in val. Invalid segment/offset values return failure.
99  * Reads to valid functions that don't exist return INVALID_PCI_ADDR
100  * as is specified by PCI for requests that aren't completed by EPs.
101  * The boilerplate in pci_svc.c tends to do basic segment, off
102  * and sz validation. This routine should avoid duplicating those
103  * checks.
104  *
105  * This function maps directly to the PCI_READ function in DEN0115
106  * where detailed requirements may be found.
107  *
108  * Return: SMC_PCI_CALL_SUCCESS with val set
109  *	   SMC_PCI_CALL_INVAL_PARAM, on parameter error
110  */
pci_read_config(uint32_t addr,uint32_t off,uint32_t sz,uint32_t * val)111 uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val)
112 {
113 	uint32_t ret = SMC_PCI_CALL_SUCCESS;
114 	uint64_t base;
115 
116 	spin_lock(&pci_lock);
117 	base = pci_segment_lib_get_base(addr, off);
118 
119 	if (base == INVALID_PCI_ADDR) {
120 		*val = base;
121 	} else {
122 		switch (sz) {
123 		case SMC_PCI_SZ_8BIT:
124 			*val = mmio_read_8(base);
125 			break;
126 		case SMC_PCI_SZ_16BIT:
127 			*val = mmio_read_16(base);
128 			break;
129 		case SMC_PCI_SZ_32BIT:
130 			*val = mmio_read_32(base);
131 			break;
132 		default: /* should be unreachable */
133 			*val = 0;
134 			ret = SMC_PCI_CALL_INVAL_PARAM;
135 		}
136 	}
137 	spin_unlock(&pci_lock);
138 	return ret;
139 }
140 
141 /**
142  * pci_write_config() - Performs a config space write at addr
143  * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
144  * @off:  register offset of function described by @addr to write
145  * @sz:	  size of write (8,16,32) bits.
146  * @val:  value to be written
147  *
148  * sz bits of PCI config space is written at addr:offset. Invalid
149  * segment/BDF values return failure. Writes to valid functions
150  * without valid EPs are ignored, as is specified by PCI.
151  * The boilerplate in pci_svc.c tends to do basic segment, off
152  * and sz validation, so it shouldn't need to be repeated here.
153  *
154  * This function maps directly to the PCI_WRITE function in DEN0115
155  * where detailed requirements may be found.
156  *
157  * Return: SMC_PCI_CALL_SUCCESS
158  *	   SMC_PCI_CALL_INVAL_PARAM, on parameter error
159  */
pci_write_config(uint32_t addr,uint32_t off,uint32_t sz,uint32_t val)160 uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val)
161 {
162 	uint32_t ret = SMC_PCI_CALL_SUCCESS;
163 	uint64_t base;
164 
165 	spin_lock(&pci_lock);
166 	base = pci_segment_lib_get_base(addr, off);
167 
168 	if (base != INVALID_PCI_ADDR) {
169 		switch (sz) {
170 		case SMC_PCI_SZ_8BIT:
171 			mmio_write_8(base, val);
172 			break;
173 		case SMC_PCI_SZ_16BIT:
174 			mmio_write_16(base, val);
175 			break;
176 		case SMC_PCI_SZ_32BIT:
177 			mmio_write_32(base, val);
178 			break;
179 		default: /* should be unreachable */
180 			ret = SMC_PCI_CALL_INVAL_PARAM;
181 		}
182 	}
183 	spin_unlock(&pci_lock);
184 	return ret;
185 }
186 
187 /**
188  * pci_get_bus_for_seg() - returns the start->end bus range for a segment
189  * @seg:  segment being queried
190  * @bus_range:	returned bus begin + (end << 8)
191  * @nseg: returns next segment in this machine or 0 for end
192  *
193  * pci_get_bus_for_seg is called to check if a given segment is
194  * valid on this machine. If it is valid, then its bus ranges are
195  * returned along with the next valid segment on the machine. If
196  * this is the last segment, then nseg must be 0.
197  *
198  * This function maps directly to the PCI_GET_SEG_INFO function
199  * in DEN0115 where detailed requirements may be found.
200  *
201  * Return: SMC_PCI_CALL_SUCCESS, and appropriate bus_range and nseg
202  *	   SMC_PCI_CALL_NOT_IMPL, if the segment is invalid
203  */
pci_get_bus_for_seg(uint32_t seg,uint32_t * bus_range,uint32_t * nseg)204 uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg)
205 {
206 	uint32_t ret = SMC_PCI_CALL_SUCCESS;
207 	*nseg = 0U; /* only a single segment */
208 	if (seg == 0U) {
209 		*bus_range = 0xFF00; /* start 0, end 255 */
210 	} else {
211 		*bus_range = 0U;
212 		ret = SMC_PCI_CALL_NOT_IMPL;
213 	}
214 	return ret;
215 }
216