]>
Commit | Line | Data |
---|---|---|
e51f2b14 WD |
1 | /* |
2 | * *************************************************************************** | |
3 | * Copyright (C) 2015 Marvell International Ltd. | |
4 | * *************************************************************************** | |
5 | * This program is free software: you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the Free | |
7 | * Software Foundation, either version 2 of the License, or any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | * *************************************************************************** | |
17 | */ | |
18 | /* pcie_advk.c | |
19 | * | |
20 | * Ported from Linux driver - driver/pci/host/pci-aardvark.c | |
21 | * | |
22 | * Author: Victor Gu <[email protected]> | |
23 | * Hezi Shahmoon <[email protected]> | |
22f69fc7 | 24 | * Pali Rohár <[email protected]> |
e51f2b14 WD |
25 | * |
26 | */ | |
27 | ||
e51f2b14 WD |
28 | #include <dm.h> |
29 | #include <pci.h> | |
30 | #include <asm/io.h> | |
31 | #include <asm-generic/gpio.h> | |
336d4615 | 32 | #include <dm/device_compat.h> |
cd93d625 | 33 | #include <linux/bitops.h> |
c05ed00a | 34 | #include <linux/delay.h> |
e51f2b14 WD |
35 | #include <linux/ioport.h> |
36 | ||
819a43c9 T |
37 | /* PCIe Root Port register offsets */ |
38 | #define ADVK_ROOT_PORT_PCI_CFG_OFF 0x0 | |
39 | #define ADVK_ROOT_PORT_PCI_EXP_OFF 0xc0 | |
40 | #define ADVK_ROOT_PORT_PCI_ERR_OFF 0x100 | |
e51f2b14 | 41 | |
cf2a589a T |
42 | /* PIO registers */ |
43 | #define ADVK_PIO_BASE_ADDR 0x4000 | |
44 | #define ADVK_PIO_CTRL (ADVK_PIO_BASE_ADDR + 0x0) | |
45 | #define ADVK_PIO_CTRL_TYPE_MASK GENMASK(3, 0) | |
46 | #define ADVK_PIO_CTRL_TYPE_SHIFT 0 | |
47 | #define ADVK_PIO_CTRL_TYPE_RD_TYPE0 0x8 | |
48 | #define ADVK_PIO_CTRL_TYPE_RD_TYPE1 0x9 | |
49 | #define ADVK_PIO_CTRL_TYPE_WR_TYPE0 0xa | |
50 | #define ADVK_PIO_CTRL_TYPE_WR_TYPE1 0xb | |
51 | #define ADVK_PIO_CTRL_ADDR_WIN_DISABLE BIT(24) | |
52 | #define ADVK_PIO_STAT (ADVK_PIO_BASE_ADDR + 0x4) | |
53 | #define ADVK_PIO_COMPLETION_STATUS_MASK GENMASK(9, 7) | |
54 | #define ADVK_PIO_COMPLETION_STATUS_SHIFT 7 | |
55 | #define ADVK_PIO_COMPLETION_STATUS_OK 0 | |
56 | #define ADVK_PIO_COMPLETION_STATUS_UR 1 | |
57 | #define ADVK_PIO_COMPLETION_STATUS_CRS 2 | |
58 | #define ADVK_PIO_COMPLETION_STATUS_CA 4 | |
59 | #define ADVK_PIO_NON_POSTED_REQ BIT(10) | |
60 | #define ADVK_PIO_ERR_STATUS BIT(11) | |
61 | #define ADVK_PIO_ADDR_LS (ADVK_PIO_BASE_ADDR + 0x8) | |
62 | #define ADVK_PIO_ADDR_MS (ADVK_PIO_BASE_ADDR + 0xc) | |
63 | #define ADVK_PIO_WR_DATA (ADVK_PIO_BASE_ADDR + 0x10) | |
64 | #define ADVK_PIO_WR_DATA_STRB (ADVK_PIO_BASE_ADDR + 0x14) | |
65 | #define ADVK_PIO_RD_DATA (ADVK_PIO_BASE_ADDR + 0x18) | |
66 | #define ADVK_PIO_START (ADVK_PIO_BASE_ADDR + 0x1c) | |
67 | #define ADVK_PIO_ISR (ADVK_PIO_BASE_ADDR + 0x20) | |
68 | ||
69 | /* Global Control registers */ | |
70 | #define ADVK_GLOBAL_CTRL_BASE_ADDR 0x4800 | |
71 | #define ADVK_GLOBAL_CTRL0 (ADVK_GLOBAL_CTRL_BASE_ADDR + 0x0) | |
72 | #define ADVK_GLOBAL_CTRL0_SPEED_GEN_MASK GENMASK(1, 0) | |
73 | #define ADVK_GLOBAL_CTRL0_SPEED_GEN_SHIFT 0 | |
74 | #define ADVK_GLOBAL_CTRL0_SPEED_GEN_1 0 | |
75 | #define ADVK_GLOBAL_CTRL0_SPEED_GEN_2 1 | |
76 | #define ADVK_GLOBAL_CTRL0_SPEED_GEN_3 2 | |
77 | #define ADVK_GLOBAL_CTRL0_IS_RC BIT(2) | |
78 | #define ADVK_GLOBAL_CTRL0_LANE_COUNT_MASK GENMASK(4, 3) | |
79 | #define ADVK_GLOBAL_CTRL0_LANE_COUNT_SHIFT 3 | |
80 | #define ADVK_GLOBAL_CTRL0_LANE_COUNT_1 0 | |
81 | #define ADVK_GLOBAL_CTRL0_LANE_COUNT_2 1 | |
82 | #define ADVK_GLOBAL_CTRL0_LANE_COUNT_4 2 | |
83 | #define ADVK_GLOBAL_CTRL0_LANE_COUNT_8 3 | |
84 | #define ADVK_GLOBAL_CTRL0_LINK_TRAINING_EN BIT(6) | |
85 | #define ADVK_GLOBAL_CTRL2 (ADVK_GLOBAL_CTRL_BASE_ADDR + 0x8) | |
86 | #define ADVK_GLOBAL_CTRL2_STRICT_ORDER_EN BIT(5) | |
87 | #define ADVK_GLOBAL_CTRL2_ADDRWIN_MAP_EN BIT(6) | |
88 | ||
89 | /* PCIe window configuration registers */ | |
90 | #define ADVK_OB_WIN_BASE_ADDR 0x4c00 | |
91 | #define ADVK_OB_WIN_BLOCK_SIZE 0x20 | |
92 | #define ADVK_OB_WIN_COUNT 8 | |
93 | #define ADVK_OB_WIN_REG_ADDR(win, offset) (ADVK_OB_WIN_BASE_ADDR + ADVK_OB_WIN_BLOCK_SIZE * (win) + (offset)) | |
94 | #define ADVK_OB_WIN_MATCH_LS(win) ADVK_OB_WIN_REG_ADDR(win, 0x00) | |
95 | #define ADVK_OB_WIN_ENABLE BIT(0) | |
96 | #define ADVK_OB_WIN_MATCH_MS(win) ADVK_OB_WIN_REG_ADDR(win, 0x04) | |
97 | #define ADVK_OB_WIN_REMAP_LS(win) ADVK_OB_WIN_REG_ADDR(win, 0x08) | |
98 | #define ADVK_OB_WIN_REMAP_MS(win) ADVK_OB_WIN_REG_ADDR(win, 0x0c) | |
99 | #define ADVK_OB_WIN_MASK_LS(win) ADVK_OB_WIN_REG_ADDR(win, 0x10) | |
100 | #define ADVK_OB_WIN_MASK_MS(win) ADVK_OB_WIN_REG_ADDR(win, 0x14) | |
101 | #define ADVK_OB_WIN_ACTIONS(win) ADVK_OB_WIN_REG_ADDR(win, 0x18) | |
102 | #define ADVK_OB_WIN_DEFAULT_ACTIONS (ADVK_OB_WIN_ACTIONS(ADVK_OB_WIN_COUNT-1) + 0x4) | |
103 | #define ADVK_OB_WIN_FUNC_NUM_MASK GENMASK(31, 24) | |
104 | #define ADVK_OB_WIN_FUNC_NUM_SHIFT 24 | |
105 | #define ADVK_OB_WIN_FUNC_NUM_ENABLE BIT(23) | |
106 | #define ADVK_OB_WIN_BUS_NUM_BITS_MASK GENMASK(22, 20) | |
107 | #define ADVK_OB_WIN_BUS_NUM_BITS_SHIFT 20 | |
108 | #define ADVK_OB_WIN_MSG_CODE_ENABLE BIT(22) | |
109 | #define ADVK_OB_WIN_MSG_CODE_MASK GENMASK(21, 14) | |
110 | #define ADVK_OB_WIN_MSG_CODE_SHIFT 14 | |
111 | #define ADVK_OB_WIN_MSG_PAYLOAD_LEN BIT(12) | |
112 | #define ADVK_OB_WIN_ATTR_ENABLE BIT(11) | |
113 | #define ADVK_OB_WIN_ATTR_TC_MASK GENMASK(10, 8) | |
114 | #define ADVK_OB_WIN_ATTR_TC_SHIFT 8 | |
115 | #define ADVK_OB_WIN_ATTR_RELAXED BIT(7) | |
116 | #define ADVK_OB_WIN_ATTR_NOSNOOP BIT(6) | |
117 | #define ADVK_OB_WIN_ATTR_POISON BIT(5) | |
118 | #define ADVK_OB_WIN_ATTR_IDO BIT(4) | |
119 | #define ADVK_OB_WIN_TYPE_MASK GENMASK(3, 0) | |
120 | #define ADVK_OB_WIN_TYPE_SHIFT 0 | |
121 | #define ADVK_OB_WIN_TYPE_MEM 0x0 | |
122 | #define ADVK_OB_WIN_TYPE_IO 0x4 | |
123 | #define ADVK_OB_WIN_TYPE_CONFIG_TYPE0 0x8 | |
124 | #define ADVK_OB_WIN_TYPE_CONFIG_TYPE1 0x9 | |
125 | #define ADVK_OB_WIN_TYPE_MSG 0xc | |
126 | ||
127 | /* Local Management Interface registers */ | |
128 | #define ADVK_LMI_BASE_ADDR 0x6000 | |
129 | #define ADVK_LMI_PHY_CFG0 (ADVK_LMI_BASE_ADDR + 0x0) | |
130 | #define ADVK_LMI_PHY_CFG0_LTSSM_MASK GENMASK(29, 24) | |
131 | #define ADVK_LMI_PHY_CFG0_LTSSM_SHIFT 24 | |
132 | #define ADVK_LMI_PHY_CFG0_LTSSM_L0 0x10 | |
133 | #define ADVK_LMI_PHY_CFG0_LTSSM_DISABLED 0x20 | |
134 | #define ADVK_LMI_VENDOR_ID (ADVK_LMI_BASE_ADDR + 0x44) | |
135 | ||
136 | /* Core Control registers */ | |
137 | #define ADVK_CORE_CTRL_BASE_ADDR 0x18000 | |
138 | #define ADVK_CORE_CTRL_CONFIG (ADVK_CORE_CTRL_BASE_ADDR + 0x0) | |
139 | #define ADVK_CORE_CTRL_CONFIG_COMMAND_MODE BIT(0) | |
e51f2b14 | 140 | |
e51f2b14 | 141 | /* PCIe Retries & Timeout definitions */ |
eccbd4ad T |
142 | #define PIO_MAX_RETRIES 1500 |
143 | #define PIO_WAIT_TIMEOUT 1000 | |
144 | #define LINK_MAX_RETRIES 10 | |
e51f2b14 WD |
145 | #define LINK_WAIT_TIMEOUT 100000 |
146 | ||
cf2a589a | 147 | #define CFG_RD_CRS_VAL 0xFFFF0001 |
e51f2b14 | 148 | |
e51f2b14 WD |
149 | /** |
150 | * struct pcie_advk - Advk PCIe controller state | |
151 | * | |
8247c90e | 152 | * @base: The base address of the register space. |
8247c90e MB |
153 | * @sec_busno: Bus number for the device behind the PCIe root-port. |
154 | * @dev: The pointer to PCI uclass device. | |
155 | * @reset_gpio: GPIO descriptor for PERST. | |
156 | * @cfgcache: Buffer for emulation of PCIe Root Port's PCI Bridge registers | |
157 | * that are not available on Aardvark. | |
158 | * @cfgcrssve: For CRSSVE emulation. | |
e51f2b14 WD |
159 | */ |
160 | struct pcie_advk { | |
96a3c989 | 161 | void *base; |
96a3c989 MB |
162 | int sec_busno; |
163 | struct udevice *dev; | |
164 | struct gpio_desc reset_gpio; | |
fed5beca | 165 | u32 cfgcache[(0x3c - 0x10) / 4]; |
96a3c989 | 166 | bool cfgcrssve; |
e51f2b14 WD |
167 | }; |
168 | ||
169 | static inline void advk_writel(struct pcie_advk *pcie, uint val, uint reg) | |
170 | { | |
171 | writel(val, pcie->base + reg); | |
172 | } | |
173 | ||
174 | static inline uint advk_readl(struct pcie_advk *pcie, uint reg) | |
175 | { | |
176 | return readl(pcie->base + reg); | |
177 | } | |
178 | ||
2727e9dd T |
179 | /** |
180 | * pcie_advk_link_up() - Check if PCIe link is up or not | |
181 | * | |
182 | * @pcie: The PCI device to access | |
183 | * | |
184 | * Return true on link up. | |
185 | * Return false on link down. | |
186 | */ | |
187 | static bool pcie_advk_link_up(struct pcie_advk *pcie) | |
188 | { | |
189 | u32 val, ltssm_state; | |
190 | ||
191 | val = advk_readl(pcie, ADVK_LMI_PHY_CFG0); | |
192 | ltssm_state = (val & ADVK_LMI_PHY_CFG0_LTSSM_MASK) >> ADVK_LMI_PHY_CFG0_LTSSM_SHIFT; | |
193 | return ltssm_state >= ADVK_LMI_PHY_CFG0_LTSSM_L0 && ltssm_state < ADVK_LMI_PHY_CFG0_LTSSM_DISABLED; | |
194 | } | |
195 | ||
e51f2b14 WD |
196 | /** |
197 | * pcie_advk_addr_valid() - Check for valid bus address | |
198 | * | |
cb056005 T |
199 | * @pcie: Pointer to the PCI bus |
200 | * @busno: Bus number of PCI device | |
201 | * @dev: Device number of PCI device | |
202 | * @func: Function number of PCI device | |
e51f2b14 | 203 | * @bdf: The PCI device to access |
e51f2b14 | 204 | * |
cb056005 | 205 | * Return: true on valid, false on invalid |
e51f2b14 | 206 | */ |
cb056005 T |
207 | static bool pcie_advk_addr_valid(struct pcie_advk *pcie, |
208 | int busno, u8 dev, u8 func) | |
e51f2b14 | 209 | { |
2a9059ae T |
210 | /* On the root bus there is only one PCI Bridge */ |
211 | if (busno == 0 && (dev != 0 || func != 0)) | |
cb056005 T |
212 | return false; |
213 | ||
2727e9dd T |
214 | /* Access to other buses is possible when link is up */ |
215 | if (busno != 0 && !pcie_advk_link_up(pcie)) | |
216 | return false; | |
217 | ||
e51f2b14 | 218 | /* |
cb056005 T |
219 | * In PCI-E only a single device (0) can exist on the secondary bus. |
220 | * Beyond the secondary bus, there might be a Switch and anything is | |
221 | * possible. | |
e51f2b14 | 222 | */ |
cb056005 T |
223 | if (busno == pcie->sec_busno && dev != 0) |
224 | return false; | |
e51f2b14 | 225 | |
cb056005 | 226 | return true; |
e51f2b14 WD |
227 | } |
228 | ||
229 | /** | |
230 | * pcie_advk_wait_pio() - Wait for PIO access to be accomplished | |
231 | * | |
232 | * @pcie: The PCI device to access | |
233 | * | |
eccbd4ad | 234 | * Wait up to 1.5 seconds for PIO access to be accomplished. |
e51f2b14 | 235 | * |
d9ac6e28 T |
236 | * Return positive - retry count if PIO access is accomplished. |
237 | * Return negative - error if PIO access is timed out. | |
e51f2b14 WD |
238 | */ |
239 | static int pcie_advk_wait_pio(struct pcie_advk *pcie) | |
240 | { | |
241 | uint start, isr; | |
242 | uint count; | |
243 | ||
d9ac6e28 | 244 | for (count = 1; count <= PIO_MAX_RETRIES; count++) { |
cf2a589a T |
245 | start = advk_readl(pcie, ADVK_PIO_START); |
246 | isr = advk_readl(pcie, ADVK_PIO_ISR); | |
e51f2b14 | 247 | if (!start && isr) |
d9ac6e28 | 248 | return count; |
e51f2b14 WD |
249 | /* |
250 | * Do not check the PIO state too frequently, | |
251 | * 100us delay is appropriate. | |
252 | */ | |
253 | udelay(PIO_WAIT_TIMEOUT); | |
254 | } | |
255 | ||
eccbd4ad | 256 | dev_err(pcie->dev, "PIO read/write transfer time out\n"); |
d9ac6e28 | 257 | return -ETIMEDOUT; |
e51f2b14 WD |
258 | } |
259 | ||
260 | /** | |
261 | * pcie_advk_check_pio_status() - Validate PIO status and get the read result | |
262 | * | |
263 | * @pcie: Pointer to the PCI bus | |
4cd61c43 T |
264 | * @allow_crs: Only for read requests, if CRS response is allowed |
265 | * @read_val: Pointer to the read result | |
e51f2b14 | 266 | * |
d9ac6e28 | 267 | * Return: 0 on success |
e51f2b14 WD |
268 | */ |
269 | static int pcie_advk_check_pio_status(struct pcie_advk *pcie, | |
4cd61c43 | 270 | bool allow_crs, |
e51f2b14 WD |
271 | uint *read_val) |
272 | { | |
d9ac6e28 | 273 | int ret; |
e51f2b14 WD |
274 | uint reg; |
275 | unsigned int status; | |
276 | char *strcomp_status, *str_posted; | |
277 | ||
cf2a589a T |
278 | reg = advk_readl(pcie, ADVK_PIO_STAT); |
279 | status = (reg & ADVK_PIO_COMPLETION_STATUS_MASK) >> | |
280 | ADVK_PIO_COMPLETION_STATUS_SHIFT; | |
e51f2b14 WD |
281 | |
282 | switch (status) { | |
cf2a589a T |
283 | case ADVK_PIO_COMPLETION_STATUS_OK: |
284 | if (reg & ADVK_PIO_ERR_STATUS) { | |
e51f2b14 | 285 | strcomp_status = "COMP_ERR"; |
d9ac6e28 | 286 | ret = -EFAULT; |
e51f2b14 WD |
287 | break; |
288 | } | |
289 | /* Get the read result */ | |
4cd61c43 | 290 | if (read_val) |
cf2a589a | 291 | *read_val = advk_readl(pcie, ADVK_PIO_RD_DATA); |
e51f2b14 WD |
292 | /* No error */ |
293 | strcomp_status = NULL; | |
d9ac6e28 | 294 | ret = 0; |
e51f2b14 | 295 | break; |
cf2a589a | 296 | case ADVK_PIO_COMPLETION_STATUS_UR: |
4cd61c43 | 297 | strcomp_status = "UR"; |
d9ac6e28 | 298 | ret = -EOPNOTSUPP; |
e51f2b14 | 299 | break; |
cf2a589a | 300 | case ADVK_PIO_COMPLETION_STATUS_CRS: |
4cd61c43 | 301 | if (allow_crs && read_val) { |
e51f2b14 WD |
302 | /* For reading, CRS is not an error status. */ |
303 | *read_val = CFG_RD_CRS_VAL; | |
304 | strcomp_status = NULL; | |
d9ac6e28 | 305 | ret = 0; |
e51f2b14 WD |
306 | } else { |
307 | strcomp_status = "CRS"; | |
d9ac6e28 | 308 | ret = -EAGAIN; |
e51f2b14 WD |
309 | } |
310 | break; | |
cf2a589a | 311 | case ADVK_PIO_COMPLETION_STATUS_CA: |
e51f2b14 | 312 | strcomp_status = "CA"; |
d9ac6e28 | 313 | ret = -ECANCELED; |
e51f2b14 WD |
314 | break; |
315 | default: | |
316 | strcomp_status = "Unknown"; | |
d9ac6e28 | 317 | ret = -EINVAL; |
e51f2b14 WD |
318 | break; |
319 | } | |
320 | ||
321 | if (!strcomp_status) | |
d9ac6e28 | 322 | return ret; |
e51f2b14 | 323 | |
cf2a589a | 324 | if (reg & ADVK_PIO_NON_POSTED_REQ) |
e51f2b14 WD |
325 | str_posted = "Non-posted"; |
326 | else | |
327 | str_posted = "Posted"; | |
328 | ||
157bc52b | 329 | dev_dbg(pcie->dev, "%s PIO Response Status: %s, %#x @ %#x\n", |
e51f2b14 | 330 | str_posted, strcomp_status, reg, |
cf2a589a | 331 | advk_readl(pcie, ADVK_PIO_ADDR_LS)); |
e51f2b14 | 332 | |
d9ac6e28 | 333 | return ret; |
e51f2b14 WD |
334 | } |
335 | ||
336 | /** | |
337 | * pcie_advk_read_config() - Read from configuration space | |
338 | * | |
339 | * @bus: Pointer to the PCI bus | |
340 | * @bdf: Identifies the PCIe device to access | |
341 | * @offset: The offset into the device's configuration space | |
342 | * @valuep: A pointer at which to store the read value | |
343 | * @size: Indicates the size of access to perform | |
344 | * | |
345 | * Read a value of size @size from offset @offset within the configuration | |
346 | * space of the device identified by the bus, device & function numbers in @bdf | |
347 | * on the PCI bus @bus. | |
348 | * | |
349 | * Return: 0 on success | |
350 | */ | |
c4e72c4a | 351 | static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, |
e51f2b14 WD |
352 | uint offset, ulong *valuep, |
353 | enum pci_size_t size) | |
354 | { | |
355 | struct pcie_advk *pcie = dev_get_priv(bus); | |
cb056005 | 356 | int busno = PCI_BUS(bdf) - dev_seq(bus); |
d9ac6e28 | 357 | int retry_count; |
4cd61c43 | 358 | bool allow_crs; |
cb056005 | 359 | ulong data; |
e51f2b14 WD |
360 | uint reg; |
361 | int ret; | |
362 | ||
363 | dev_dbg(pcie->dev, "PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) ", | |
364 | PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); | |
365 | ||
cb056005 | 366 | if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) { |
e51f2b14 WD |
367 | dev_dbg(pcie->dev, "- out of range\n"); |
368 | *valuep = pci_get_ff(size); | |
369 | return 0; | |
370 | } | |
371 | ||
cb056005 | 372 | /* |
2a9059ae | 373 | * The configuration space of the PCI Bridge on the root bus (zero) is |
cb056005 T |
374 | * not accessible via PIO transfers like all other PCIe devices. PCI |
375 | * Bridge config registers are available directly in Aardvark memory | |
fed5beca T |
376 | * space starting at offset zero. The PCI Bridge config space is of |
377 | * Type 0, but the BAR registers (including ROM BAR) don't have the same | |
378 | * meaning as in the PCIe specification. Therefore do not access BAR | |
379 | * registers and non-common registers (those which have different | |
2a9059ae | 380 | * meaning for Type 0 and Type 1 config space) of the PCI Bridge |
fed5beca | 381 | * and instead read their content from driver virtual cfgcache[]. |
cb056005 | 382 | */ |
2a9059ae | 383 | if (busno == 0) { |
fed5beca | 384 | if ((offset >= 0x10 && offset < 0x34) || (offset >= 0x38 && offset < 0x3c)) |
cb056005 | 385 | data = pcie->cfgcache[(offset - 0x10) / 4]; |
cb056005 | 386 | else |
819a43c9 | 387 | data = advk_readl(pcie, ADVK_ROOT_PORT_PCI_CFG_OFF + (offset & ~3)); |
cb056005 T |
388 | |
389 | if ((offset & ~3) == (PCI_HEADER_TYPE & ~3)) { | |
390 | /* | |
391 | * Change Header Type of PCI Bridge device to Type 1 | |
392 | * (0x01, used by PCI Bridges) because hardwired value | |
393 | * is Type 0 (0x00, used by Endpoint devices). | |
394 | */ | |
395 | data &= ~0x007f0000; | |
396 | data |= PCI_HEADER_TYPE_BRIDGE << 16; | |
397 | } | |
398 | ||
819a43c9 | 399 | if ((offset & ~3) == ADVK_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_RTCTL) { |
1d7ad685 T |
400 | /* CRSSVE bit is stored only in cache */ |
401 | if (pcie->cfgcrssve) | |
402 | data |= PCI_EXP_RTCTL_CRSSVE; | |
403 | } | |
404 | ||
819a43c9 | 405 | if ((offset & ~3) == ADVK_ROOT_PORT_PCI_EXP_OFF + (PCI_EXP_RTCAP & ~3)) { |
1d7ad685 T |
406 | /* CRS is emulated below, so set CRSVIS capability */ |
407 | data |= PCI_EXP_RTCAP_CRSVIS << 16; | |
408 | } | |
409 | ||
cb056005 T |
410 | *valuep = pci_conv_32_to_size(data, offset, size); |
411 | ||
412 | return 0; | |
413 | } | |
414 | ||
758262bc T |
415 | /* |
416 | * Returning fabricated CRS value (0xFFFF0001) by PCIe Root Complex to | |
417 | * OS is allowed only for 4-byte PCI_VENDOR_ID config read request and | |
418 | * only when CRSSVE bit in Root Port PCIe device is enabled. In all | |
419 | * other error PCIe Root Complex must return all-ones. | |
1d7ad685 | 420 | * |
758262bc T |
421 | * U-Boot currently does not support handling of CRS return value for |
422 | * PCI_VENDOR_ID config read request and also does not set CRSSVE bit. | |
1d7ad685 T |
423 | * So it means that pcie->cfgcrssve is false. But the code is prepared |
424 | * for returning CRS, so that if U-Boot does support CRS in the future, | |
425 | * it will work for Aardvark. | |
758262bc | 426 | */ |
bd4064ff | 427 | allow_crs = (offset == PCI_VENDOR_ID) && (size == PCI_SIZE_32) && pcie->cfgcrssve; |
4cd61c43 | 428 | |
cf2a589a | 429 | if (advk_readl(pcie, ADVK_PIO_START)) { |
eccbd4ad T |
430 | dev_err(pcie->dev, |
431 | "Previous PIO read/write transfer is still running\n"); | |
4cd61c43 T |
432 | if (allow_crs) { |
433 | *valuep = CFG_RD_CRS_VAL; | |
434 | return 0; | |
435 | } | |
436 | *valuep = pci_get_ff(size); | |
d9ac6e28 | 437 | return -EAGAIN; |
eccbd4ad | 438 | } |
e51f2b14 WD |
439 | |
440 | /* Program the control register */ | |
cf2a589a T |
441 | reg = advk_readl(pcie, ADVK_PIO_CTRL); |
442 | reg &= ~ADVK_PIO_CTRL_TYPE_MASK; | |
cb056005 | 443 | if (busno == pcie->sec_busno) |
cf2a589a | 444 | reg |= ADVK_PIO_CTRL_TYPE_RD_TYPE0 << ADVK_PIO_CTRL_TYPE_SHIFT; |
e51f2b14 | 445 | else |
cf2a589a T |
446 | reg |= ADVK_PIO_CTRL_TYPE_RD_TYPE1 << ADVK_PIO_CTRL_TYPE_SHIFT; |
447 | advk_writel(pcie, reg, ADVK_PIO_CTRL); | |
e51f2b14 WD |
448 | |
449 | /* Program the address registers */ | |
a4bc38da | 450 | reg = PCIE_ECAM_OFFSET(busno, PCI_DEV(bdf), PCI_FUNC(bdf), (offset & ~0x3)); |
cf2a589a T |
451 | advk_writel(pcie, reg, ADVK_PIO_ADDR_LS); |
452 | advk_writel(pcie, 0, ADVK_PIO_ADDR_MS); | |
e51f2b14 | 453 | |
57fa6fb9 | 454 | /* Program the data strobe */ |
cf2a589a | 455 | advk_writel(pcie, 0xf, ADVK_PIO_WR_DATA_STRB); |
57fa6fb9 | 456 | |
d9ac6e28 T |
457 | retry_count = 0; |
458 | ||
459 | retry: | |
e51f2b14 | 460 | /* Start the transfer */ |
cf2a589a T |
461 | advk_writel(pcie, 1, ADVK_PIO_ISR); |
462 | advk_writel(pcie, 1, ADVK_PIO_START); | |
e51f2b14 | 463 | |
d9ac6e28 T |
464 | ret = pcie_advk_wait_pio(pcie); |
465 | if (ret < 0) { | |
4cd61c43 T |
466 | if (allow_crs) { |
467 | *valuep = CFG_RD_CRS_VAL; | |
468 | return 0; | |
469 | } | |
470 | *valuep = pci_get_ff(size); | |
d9ac6e28 | 471 | return ret; |
eccbd4ad | 472 | } |
e51f2b14 | 473 | |
d9ac6e28 T |
474 | retry_count += ret; |
475 | ||
e51f2b14 | 476 | /* Check PIO status and get the read result */ |
4cd61c43 | 477 | ret = pcie_advk_check_pio_status(pcie, allow_crs, ®); |
d9ac6e28 T |
478 | if (ret == -EAGAIN && retry_count < PIO_MAX_RETRIES) |
479 | goto retry; | |
4cd61c43 T |
480 | if (ret) { |
481 | *valuep = pci_get_ff(size); | |
e51f2b14 | 482 | return ret; |
4cd61c43 | 483 | } |
e51f2b14 WD |
484 | |
485 | dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08x)\n", | |
486 | offset, size, reg); | |
487 | *valuep = pci_conv_32_to_size(reg, offset, size); | |
488 | ||
489 | return 0; | |
490 | } | |
491 | ||
492 | /** | |
493 | * pcie_calc_datastrobe() - Calculate data strobe | |
494 | * | |
495 | * @offset: The offset into the device's configuration space | |
496 | * @size: Indicates the size of access to perform | |
497 | * | |
498 | * Calculate data strobe according to offset and size | |
499 | * | |
500 | */ | |
501 | static uint pcie_calc_datastrobe(uint offset, enum pci_size_t size) | |
502 | { | |
503 | uint bytes, data_strobe; | |
504 | ||
505 | switch (size) { | |
506 | case PCI_SIZE_8: | |
507 | bytes = 1; | |
508 | break; | |
509 | case PCI_SIZE_16: | |
510 | bytes = 2; | |
511 | break; | |
512 | default: | |
513 | bytes = 4; | |
514 | } | |
515 | ||
516 | data_strobe = GENMASK(bytes - 1, 0) << (offset & 0x3); | |
517 | ||
518 | return data_strobe; | |
519 | } | |
520 | ||
521 | /** | |
522 | * pcie_advk_write_config() - Write to configuration space | |
523 | * | |
524 | * @bus: Pointer to the PCI bus | |
525 | * @bdf: Identifies the PCIe device to access | |
526 | * @offset: The offset into the device's configuration space | |
527 | * @value: The value to write | |
528 | * @size: Indicates the size of access to perform | |
529 | * | |
530 | * Write the value @value of size @size from offset @offset within the | |
531 | * configuration space of the device identified by the bus, device & function | |
532 | * numbers in @bdf on the PCI bus @bus. | |
533 | * | |
534 | * Return: 0 on success | |
535 | */ | |
536 | static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, | |
537 | uint offset, ulong value, | |
538 | enum pci_size_t size) | |
539 | { | |
540 | struct pcie_advk *pcie = dev_get_priv(bus); | |
cb056005 | 541 | int busno = PCI_BUS(bdf) - dev_seq(bus); |
d9ac6e28 | 542 | int retry_count; |
cb056005 | 543 | ulong data; |
e51f2b14 | 544 | uint reg; |
d9ac6e28 | 545 | int ret; |
e51f2b14 WD |
546 | |
547 | dev_dbg(pcie->dev, "PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", | |
548 | PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); | |
549 | dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08lx)\n", | |
550 | offset, size, value); | |
551 | ||
cb056005 | 552 | if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) { |
e51f2b14 WD |
553 | dev_dbg(pcie->dev, "- out of range\n"); |
554 | return 0; | |
555 | } | |
556 | ||
cb056005 | 557 | /* |
fed5beca T |
558 | * As explained in pcie_advk_read_config(), PCI Bridge config registers |
559 | * are available directly in Aardvark memory space starting at offset | |
560 | * zero. Type 1 specific registers are not available, so we write their | |
561 | * content only into driver virtual cfgcache[]. | |
cb056005 | 562 | */ |
2a9059ae | 563 | if (busno == 0) { |
fed5beca T |
564 | if ((offset >= 0x10 && offset < 0x34) || |
565 | (offset >= 0x38 && offset < 0x3c)) { | |
cb056005 T |
566 | data = pcie->cfgcache[(offset - 0x10) / 4]; |
567 | data = pci_conv_size_to_32(data, value, offset, size); | |
aaddce0d T |
568 | /* This PCI bridge does not have configurable bars */ |
569 | if ((offset & ~3) == PCI_BASE_ADDRESS_0 || | |
fed5beca T |
570 | (offset & ~3) == PCI_BASE_ADDRESS_1 || |
571 | (offset & ~3) == PCI_ROM_ADDRESS1) | |
aaddce0d | 572 | data = 0x0; |
cb056005 | 573 | pcie->cfgcache[(offset - 0x10) / 4] = data; |
cb056005 | 574 | } else { |
819a43c9 | 575 | data = advk_readl(pcie, ADVK_ROOT_PORT_PCI_CFG_OFF + (offset & ~3)); |
cb056005 | 576 | data = pci_conv_size_to_32(data, value, offset, size); |
819a43c9 | 577 | advk_writel(pcie, data, ADVK_ROOT_PORT_PCI_CFG_OFF + (offset & ~3)); |
cb056005 T |
578 | } |
579 | ||
cb056005 T |
580 | if (offset == PCI_SECONDARY_BUS || |
581 | (offset == PCI_PRIMARY_BUS && size != PCI_SIZE_8)) | |
582 | pcie->sec_busno = (data >> 8) & 0xff; | |
583 | ||
819a43c9 | 584 | if ((offset & ~3) == ADVK_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_RTCTL) |
1d7ad685 T |
585 | pcie->cfgcrssve = data & PCI_EXP_RTCTL_CRSSVE; |
586 | ||
cb056005 T |
587 | return 0; |
588 | } | |
589 | ||
cf2a589a | 590 | if (advk_readl(pcie, ADVK_PIO_START)) { |
eccbd4ad T |
591 | dev_err(pcie->dev, |
592 | "Previous PIO read/write transfer is still running\n"); | |
d9ac6e28 | 593 | return -EAGAIN; |
eccbd4ad | 594 | } |
e51f2b14 WD |
595 | |
596 | /* Program the control register */ | |
cf2a589a T |
597 | reg = advk_readl(pcie, ADVK_PIO_CTRL); |
598 | reg &= ~ADVK_PIO_CTRL_TYPE_MASK; | |
cb056005 | 599 | if (busno == pcie->sec_busno) |
cf2a589a | 600 | reg |= ADVK_PIO_CTRL_TYPE_WR_TYPE0 << ADVK_PIO_CTRL_TYPE_SHIFT; |
e51f2b14 | 601 | else |
cf2a589a T |
602 | reg |= ADVK_PIO_CTRL_TYPE_WR_TYPE1 << ADVK_PIO_CTRL_TYPE_SHIFT; |
603 | advk_writel(pcie, reg, ADVK_PIO_CTRL); | |
e51f2b14 WD |
604 | |
605 | /* Program the address registers */ | |
a4bc38da | 606 | reg = PCIE_ECAM_OFFSET(busno, PCI_DEV(bdf), PCI_FUNC(bdf), (offset & ~0x3)); |
cf2a589a T |
607 | advk_writel(pcie, reg, ADVK_PIO_ADDR_LS); |
608 | advk_writel(pcie, 0, ADVK_PIO_ADDR_MS); | |
e51f2b14 WD |
609 | dev_dbg(pcie->dev, "\tPIO req. - addr = 0x%08x\n", reg); |
610 | ||
611 | /* Program the data register */ | |
612 | reg = pci_conv_size_to_32(0, value, offset, size); | |
cf2a589a | 613 | advk_writel(pcie, reg, ADVK_PIO_WR_DATA); |
e51f2b14 WD |
614 | dev_dbg(pcie->dev, "\tPIO req. - val = 0x%08x\n", reg); |
615 | ||
616 | /* Program the data strobe */ | |
617 | reg = pcie_calc_datastrobe(offset, size); | |
cf2a589a | 618 | advk_writel(pcie, reg, ADVK_PIO_WR_DATA_STRB); |
e51f2b14 WD |
619 | dev_dbg(pcie->dev, "\tPIO req. - strb = 0x%02x\n", reg); |
620 | ||
d9ac6e28 T |
621 | retry_count = 0; |
622 | ||
623 | retry: | |
e51f2b14 | 624 | /* Start the transfer */ |
cf2a589a T |
625 | advk_writel(pcie, 1, ADVK_PIO_ISR); |
626 | advk_writel(pcie, 1, ADVK_PIO_START); | |
e51f2b14 | 627 | |
d9ac6e28 T |
628 | ret = pcie_advk_wait_pio(pcie); |
629 | if (ret < 0) | |
630 | return ret; | |
631 | ||
632 | retry_count += ret; | |
e51f2b14 WD |
633 | |
634 | /* Check PIO status */ | |
d9ac6e28 T |
635 | ret = pcie_advk_check_pio_status(pcie, false, NULL); |
636 | if (ret == -EAGAIN && retry_count < PIO_MAX_RETRIES) | |
637 | goto retry; | |
638 | return ret; | |
e51f2b14 WD |
639 | } |
640 | ||
e51f2b14 WD |
641 | /** |
642 | * pcie_advk_wait_for_link() - Wait for link training to be accomplished | |
643 | * | |
644 | * @pcie: The PCI device to access | |
645 | * | |
646 | * Wait up to 1 second for link training to be accomplished. | |
e51f2b14 | 647 | */ |
6c7ccb97 | 648 | static void pcie_advk_wait_for_link(struct pcie_advk *pcie) |
e51f2b14 WD |
649 | { |
650 | int retries; | |
651 | ||
652 | /* check if the link is up or not */ | |
eccbd4ad | 653 | for (retries = 0; retries < LINK_MAX_RETRIES; retries++) { |
e51f2b14 | 654 | if (pcie_advk_link_up(pcie)) { |
cb056005 | 655 | printf("PCIe: Link up\n"); |
6c7ccb97 | 656 | return; |
e51f2b14 WD |
657 | } |
658 | ||
659 | udelay(LINK_WAIT_TIMEOUT); | |
660 | } | |
661 | ||
cb056005 | 662 | printf("PCIe: Link down\n"); |
e51f2b14 WD |
663 | } |
664 | ||
b321722f T |
665 | /* |
666 | * Set PCIe address window register which could be used for memory | |
667 | * mapping. | |
668 | */ | |
669 | static void pcie_advk_set_ob_win(struct pcie_advk *pcie, u8 win_num, | |
670 | phys_addr_t match, phys_addr_t remap, | |
671 | phys_addr_t mask, u32 actions) | |
672 | { | |
cf2a589a T |
673 | advk_writel(pcie, ADVK_OB_WIN_ENABLE | |
674 | lower_32_bits(match), ADVK_OB_WIN_MATCH_LS(win_num)); | |
675 | advk_writel(pcie, upper_32_bits(match), ADVK_OB_WIN_MATCH_MS(win_num)); | |
676 | advk_writel(pcie, lower_32_bits(remap), ADVK_OB_WIN_REMAP_LS(win_num)); | |
677 | advk_writel(pcie, upper_32_bits(remap), ADVK_OB_WIN_REMAP_MS(win_num)); | |
678 | advk_writel(pcie, lower_32_bits(mask), ADVK_OB_WIN_MASK_LS(win_num)); | |
679 | advk_writel(pcie, upper_32_bits(mask), ADVK_OB_WIN_MASK_MS(win_num)); | |
680 | advk_writel(pcie, actions, ADVK_OB_WIN_ACTIONS(win_num)); | |
b321722f T |
681 | } |
682 | ||
683 | static void pcie_advk_disable_ob_win(struct pcie_advk *pcie, u8 win_num) | |
684 | { | |
cf2a589a T |
685 | advk_writel(pcie, 0, ADVK_OB_WIN_MATCH_LS(win_num)); |
686 | advk_writel(pcie, 0, ADVK_OB_WIN_MATCH_MS(win_num)); | |
687 | advk_writel(pcie, 0, ADVK_OB_WIN_REMAP_LS(win_num)); | |
688 | advk_writel(pcie, 0, ADVK_OB_WIN_REMAP_MS(win_num)); | |
689 | advk_writel(pcie, 0, ADVK_OB_WIN_MASK_LS(win_num)); | |
690 | advk_writel(pcie, 0, ADVK_OB_WIN_MASK_MS(win_num)); | |
691 | advk_writel(pcie, 0, ADVK_OB_WIN_ACTIONS(win_num)); | |
b321722f T |
692 | } |
693 | ||
694 | static void pcie_advk_set_ob_region(struct pcie_advk *pcie, int *wins, | |
695 | struct pci_region *region, u32 actions) | |
696 | { | |
697 | phys_addr_t phys_start = region->phys_start; | |
698 | pci_addr_t bus_start = region->bus_start; | |
699 | pci_size_t size = region->size; | |
700 | phys_addr_t win_mask; | |
701 | u64 win_size; | |
702 | ||
703 | if (*wins == -1) | |
704 | return; | |
705 | ||
706 | /* | |
707 | * The n-th PCIe window is configured by tuple (match, remap, mask) | |
960d4597 | 708 | * and an access to address A uses this window if A matches the |
b321722f T |
709 | * match with given mask. |
710 | * So every PCIe window size must be a power of two and every start | |
711 | * address must be aligned to window size. Minimal size is 64 KiB | |
a8314950 T |
712 | * because lower 16 bits of mask must be zero. Remapped address |
713 | * may have set only bits from the mask. | |
b321722f | 714 | */ |
cf2a589a | 715 | while (*wins < ADVK_OB_WIN_COUNT && size > 0) { |
b321722f T |
716 | /* Calculate the largest aligned window size */ |
717 | win_size = (1ULL << (fls64(size) - 1)) | | |
718 | (phys_start ? (1ULL << __ffs64(phys_start)) : 0); | |
719 | win_size = 1ULL << __ffs64(win_size); | |
a8314950 T |
720 | win_mask = ~(win_size - 1); |
721 | if (win_size < 0x10000 || (bus_start & ~win_mask)) | |
b321722f T |
722 | break; |
723 | ||
724 | dev_dbg(pcie->dev, | |
725 | "Configuring PCIe window %d: [0x%llx-0x%llx] as 0x%x\n", | |
726 | *wins, (u64)phys_start, (u64)phys_start + win_size, | |
727 | actions); | |
b321722f T |
728 | pcie_advk_set_ob_win(pcie, *wins, phys_start, bus_start, |
729 | win_mask, actions); | |
730 | ||
731 | phys_start += win_size; | |
732 | bus_start += win_size; | |
733 | size -= win_size; | |
734 | (*wins)++; | |
735 | } | |
736 | ||
737 | if (size > 0) { | |
738 | *wins = -1; | |
739 | dev_err(pcie->dev, | |
740 | "Invalid PCIe region [0x%llx-0x%llx]\n", | |
741 | (u64)region->phys_start, | |
742 | (u64)region->phys_start + region->size); | |
743 | } | |
744 | } | |
745 | ||
e51f2b14 WD |
746 | /** |
747 | * pcie_advk_setup_hw() - PCIe initailzation | |
748 | * | |
749 | * @pcie: The PCI device to access | |
750 | * | |
751 | * Return: 0 on success | |
752 | */ | |
753 | static int pcie_advk_setup_hw(struct pcie_advk *pcie) | |
754 | { | |
b321722f T |
755 | struct pci_region *io, *mem, *pref; |
756 | int i, wins; | |
e51f2b14 WD |
757 | u32 reg; |
758 | ||
682bad8c | 759 | /* Set from Command to Direct mode */ |
cf2a589a T |
760 | reg = advk_readl(pcie, ADVK_CORE_CTRL_CONFIG); |
761 | reg &= ~ADVK_CORE_CTRL_CONFIG_COMMAND_MODE; | |
762 | advk_writel(pcie, reg, ADVK_CORE_CTRL_CONFIG); | |
e51f2b14 WD |
763 | |
764 | /* Set PCI global control register to RC mode */ | |
cf2a589a T |
765 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL0); |
766 | reg |= ADVK_GLOBAL_CTRL0_IS_RC; | |
767 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL0); | |
e51f2b14 | 768 | |
2fa30d04 T |
769 | /* |
770 | * Replace incorrect PCI vendor id value 0x1b4b by correct value 0x11ab. | |
cf2a589a | 771 | * ADVK_LMI_VENDOR_ID contains vendor id in low 16 bits and subsystem vendor |
2fa30d04 | 772 | * id in high 16 bits. Updating this register changes readback value of |
cf2a589a | 773 | * read-only vendor id bits in Root Port PCI_VENDOR_ID register. Workaround |
2fa30d04 T |
774 | * for erratum 4.1: "The value of device and vendor ID is incorrect". |
775 | */ | |
cf2a589a | 776 | advk_writel(pcie, 0x11ab11ab, ADVK_LMI_VENDOR_ID); |
2fa30d04 | 777 | |
cb056005 T |
778 | /* |
779 | * Change Class Code of PCI Bridge device to PCI Bridge (0x600400), | |
780 | * because default value is Mass Storage Controller (0x010400), causing | |
781 | * U-Boot to fail to recognize it as P2P Bridge. | |
782 | * | |
783 | * Note that this Aardvark PCI Bridge does not have a compliant Type 1 | |
784 | * Configuration Space and it even cannot be accessed via Aardvark's | |
fed5beca | 785 | * PCI config space access method. Aardvark PCI Bridge Config space is |
cb056005 | 786 | * available in internal Aardvark registers starting at offset 0x0 |
fed5beca T |
787 | * and has format of Type 0 config space. |
788 | * | |
789 | * Moreover Type 0 BAR registers (ranges 0x10 - 0x28 and 0x30 - 0x34) | |
790 | * have the same format in Marvell's specification as in PCIe | |
791 | * specification, but their meaning is totally different (and not even | |
792 | * the same meaning as explained in the corresponding comment in the | |
793 | * pci_mvebu driver; aardvark is still different). | |
794 | * | |
795 | * So our driver converts Type 0 config space to Type 1 and reports | |
796 | * Header Type as Type 1. Access to BAR registers and to non-existent | |
797 | * Type 1 registers is redirected to the virtual cfgcache[] buffer, | |
798 | * which avoids changing unrelated registers. | |
cb056005 | 799 | */ |
819a43c9 | 800 | reg = advk_readl(pcie, ADVK_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION); |
cb056005 | 801 | reg &= ~0xffffff00; |
d7b90409 | 802 | reg |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8; |
819a43c9 T |
803 | advk_writel(pcie, reg, ADVK_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION); |
804 | ||
805 | /* Enable generation and checking of ECRC on PCIe Root Port */ | |
806 | reg = advk_readl(pcie, ADVK_ROOT_PORT_PCI_ERR_OFF + PCI_ERR_CAP); | |
807 | reg |= PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE; | |
808 | advk_writel(pcie, reg, ADVK_ROOT_PORT_PCI_ERR_OFF + PCI_ERR_CAP); | |
809 | ||
810 | /* Set PCIe Device Control register on PCIe Root Port */ | |
811 | reg = advk_readl(pcie, ADVK_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_DEVCTL); | |
812 | reg &= ~PCI_EXP_DEVCTL_RELAX_EN; | |
813 | reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; | |
814 | reg &= ~PCI_EXP_DEVCTL_PAYLOAD; | |
815 | reg &= ~PCI_EXP_DEVCTL_READRQ; | |
816 | reg |= PCI_EXP_DEVCTL_PAYLOAD_512B; | |
817 | reg |= PCI_EXP_DEVCTL_READRQ_512B; | |
818 | advk_writel(pcie, reg, ADVK_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_DEVCTL); | |
e51f2b14 WD |
819 | |
820 | /* Program PCIe Control 2 to disable strict ordering */ | |
cf2a589a T |
821 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL2); |
822 | reg &= ~ADVK_GLOBAL_CTRL2_STRICT_ORDER_EN; | |
823 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL2); | |
e51f2b14 WD |
824 | |
825 | /* Set GEN2 */ | |
cf2a589a T |
826 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL0); |
827 | reg &= ~ADVK_GLOBAL_CTRL0_SPEED_GEN_MASK; | |
828 | reg |= ADVK_GLOBAL_CTRL0_SPEED_GEN_2 << ADVK_GLOBAL_CTRL0_SPEED_GEN_SHIFT; | |
829 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL0); | |
e51f2b14 WD |
830 | |
831 | /* Set lane X1 */ | |
cf2a589a T |
832 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL0); |
833 | reg &= ~ADVK_GLOBAL_CTRL0_LANE_COUNT_MASK; | |
834 | reg |= ADVK_GLOBAL_CTRL0_LANE_COUNT_1 << ADVK_GLOBAL_CTRL0_LANE_COUNT_SHIFT; | |
835 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL0); | |
e51f2b14 WD |
836 | |
837 | /* Enable link training */ | |
cf2a589a T |
838 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL0); |
839 | reg |= ADVK_GLOBAL_CTRL0_LINK_TRAINING_EN; | |
840 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL0); | |
e51f2b14 WD |
841 | |
842 | /* | |
843 | * Enable AXI address window location generation: | |
844 | * When it is enabled, the default outbound window | |
845 | * configurations (Default User Field: 0xD0074CFC) | |
846 | * are used to transparent address translation for | |
847 | * the outbound transactions. Thus, PCIe address | |
b321722f T |
848 | * windows are not required for transparent memory |
849 | * access when default outbound window configuration | |
850 | * is set for memory access. | |
e51f2b14 | 851 | */ |
cf2a589a T |
852 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL2); |
853 | reg |= ADVK_GLOBAL_CTRL2_ADDRWIN_MAP_EN; | |
854 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL2); | |
e51f2b14 WD |
855 | |
856 | /* | |
857 | * Bypass the address window mapping for PIO: | |
858 | * Since PIO access already contains all required | |
859 | * info over AXI interface by PIO registers, the | |
860 | * address window is not required. | |
861 | */ | |
cf2a589a T |
862 | reg = advk_readl(pcie, ADVK_PIO_CTRL); |
863 | reg |= ADVK_PIO_CTRL_ADDR_WIN_DISABLE; | |
864 | advk_writel(pcie, reg, ADVK_PIO_CTRL); | |
e51f2b14 | 865 | |
b321722f T |
866 | /* |
867 | * Set memory access in Default User Field so it | |
868 | * is not required to configure PCIe address for | |
869 | * transparent memory access. | |
870 | */ | |
cf2a589a | 871 | advk_writel(pcie, ADVK_OB_WIN_TYPE_MEM, ADVK_OB_WIN_DEFAULT_ACTIONS); |
b321722f T |
872 | |
873 | /* | |
874 | * Configure PCIe address windows for non-memory or | |
875 | * non-transparent access as by default PCIe uses | |
876 | * transparent memory access. | |
877 | */ | |
878 | wins = 0; | |
879 | pci_get_regions(pcie->dev, &io, &mem, &pref); | |
880 | if (io) | |
cf2a589a | 881 | pcie_advk_set_ob_region(pcie, &wins, io, ADVK_OB_WIN_TYPE_IO); |
b321722f | 882 | if (mem && mem->phys_start != mem->bus_start) |
cf2a589a | 883 | pcie_advk_set_ob_region(pcie, &wins, mem, ADVK_OB_WIN_TYPE_MEM); |
b321722f | 884 | if (pref && pref->phys_start != pref->bus_start) |
cf2a589a | 885 | pcie_advk_set_ob_region(pcie, &wins, pref, ADVK_OB_WIN_TYPE_MEM); |
b321722f T |
886 | |
887 | /* Disable remaining PCIe outbound windows */ | |
cf2a589a | 888 | for (i = ((wins >= 0) ? wins : 0); i < ADVK_OB_WIN_COUNT; i++) |
b321722f T |
889 | pcie_advk_disable_ob_win(pcie, i); |
890 | ||
891 | if (wins == -1) | |
892 | return -EINVAL; | |
893 | ||
e51f2b14 | 894 | /* Wait for PCIe link up */ |
6c7ccb97 | 895 | pcie_advk_wait_for_link(pcie); |
e51f2b14 | 896 | |
e51f2b14 WD |
897 | return 0; |
898 | } | |
899 | ||
900 | /** | |
901 | * pcie_advk_probe() - Probe the PCIe bus for active link | |
902 | * | |
903 | * @dev: A pointer to the device being operated on | |
904 | * | |
905 | * Probe for an active link on the PCIe bus and configure the controller | |
906 | * to enable this port. | |
907 | * | |
908 | * Return: 0 on success, else -ENODEV | |
909 | */ | |
910 | static int pcie_advk_probe(struct udevice *dev) | |
911 | { | |
912 | struct pcie_advk *pcie = dev_get_priv(dev); | |
913 | ||
828d3262 | 914 | gpio_request_by_name(dev, "reset-gpios", 0, &pcie->reset_gpio, |
e51f2b14 WD |
915 | GPIOD_IS_OUT); |
916 | /* | |
917 | * Issue reset to add-in card through the dedicated GPIO. | |
918 | * Some boards are connecting the card reset pin to common system | |
919 | * reset wire and others are using separate GPIO port. | |
920 | * In the last case we have to release a reset of the addon card | |
921 | * using this GPIO. | |
922 | * | |
923 | * FIX-ME: | |
924 | * The PCIe RESET signal is not supposed to be released along | |
925 | * with the SOC RESET signal. It should be lowered as early as | |
926 | * possible before PCIe PHY initialization. Moreover, the PCIe | |
927 | * clock should be gated as well. | |
928 | */ | |
828d3262 | 929 | if (dm_gpio_is_valid(&pcie->reset_gpio)) { |
279b5736 | 930 | dev_dbg(dev, "Toggle PCIE Reset GPIO ...\n"); |
828d3262 | 931 | dm_gpio_set_value(&pcie->reset_gpio, 1); |
563b85bd | 932 | mdelay(200); |
828d3262 | 933 | dm_gpio_set_value(&pcie->reset_gpio, 0); |
835d969c | 934 | } else { |
279b5736 | 935 | dev_warn(dev, "PCIE Reset on GPIO support is missing\n"); |
e51f2b14 | 936 | } |
e51f2b14 | 937 | |
e51f2b14 WD |
938 | pcie->dev = pci_get_controller(dev); |
939 | ||
cb056005 T |
940 | /* PCI Bridge support 32-bit I/O and 64-bit prefetch mem addressing */ |
941 | pcie->cfgcache[(PCI_IO_BASE - 0x10) / 4] = | |
942 | PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8); | |
943 | pcie->cfgcache[(PCI_PREF_MEMORY_BASE - 0x10) / 4] = | |
944 | PCI_PREF_RANGE_TYPE_64 | (PCI_PREF_RANGE_TYPE_64 << 16); | |
945 | ||
e51f2b14 WD |
946 | return pcie_advk_setup_hw(pcie); |
947 | } | |
948 | ||
828d3262 T |
949 | static int pcie_advk_remove(struct udevice *dev) |
950 | { | |
828d3262 | 951 | struct pcie_advk *pcie = dev_get_priv(dev); |
5f50b88a | 952 | u32 reg; |
b321722f T |
953 | int i; |
954 | ||
cf2a589a | 955 | for (i = 0; i < ADVK_OB_WIN_COUNT; i++) |
b321722f | 956 | pcie_advk_disable_ob_win(pcie, i); |
828d3262 | 957 | |
819a43c9 T |
958 | reg = advk_readl(pcie, ADVK_ROOT_PORT_PCI_CFG_OFF + PCI_COMMAND); |
959 | reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | |
960 | advk_writel(pcie, reg, ADVK_ROOT_PORT_PCI_CFG_OFF + PCI_COMMAND); | |
7b85aefd | 961 | |
cf2a589a T |
962 | reg = advk_readl(pcie, ADVK_GLOBAL_CTRL0); |
963 | reg &= ~ADVK_GLOBAL_CTRL0_LINK_TRAINING_EN; | |
964 | advk_writel(pcie, reg, ADVK_GLOBAL_CTRL0); | |
5f50b88a | 965 | |
828d3262 T |
966 | return 0; |
967 | } | |
968 | ||
e51f2b14 | 969 | /** |
d1998a9f | 970 | * pcie_advk_of_to_plat() - Translate from DT to device state |
e51f2b14 WD |
971 | * |
972 | * @dev: A pointer to the device being operated on | |
973 | * | |
974 | * Translate relevant data from the device tree pertaining to device @dev into | |
975 | * state that the driver will later make use of. This state is stored in the | |
976 | * device's private data structure. | |
977 | * | |
978 | * Return: 0 on success, else -EINVAL | |
979 | */ | |
d1998a9f | 980 | static int pcie_advk_of_to_plat(struct udevice *dev) |
e51f2b14 WD |
981 | { |
982 | struct pcie_advk *pcie = dev_get_priv(dev); | |
983 | ||
984 | /* Get the register base address */ | |
a12a73b6 JJ |
985 | pcie->base = dev_read_addr_ptr(dev); |
986 | if (!pcie->base) | |
e51f2b14 WD |
987 | return -EINVAL; |
988 | ||
989 | return 0; | |
990 | } | |
991 | ||
992 | static const struct dm_pci_ops pcie_advk_ops = { | |
993 | .read_config = pcie_advk_read_config, | |
994 | .write_config = pcie_advk_write_config, | |
995 | }; | |
996 | ||
997 | static const struct udevice_id pcie_advk_ids[] = { | |
a544d65f | 998 | { .compatible = "marvell,armada-3700-pcie" }, |
e51f2b14 WD |
999 | { } |
1000 | }; | |
1001 | ||
1002 | U_BOOT_DRIVER(pcie_advk) = { | |
1003 | .name = "pcie_advk", | |
1004 | .id = UCLASS_PCI, | |
1005 | .of_match = pcie_advk_ids, | |
1006 | .ops = &pcie_advk_ops, | |
d1998a9f | 1007 | .of_to_plat = pcie_advk_of_to_plat, |
e51f2b14 | 1008 | .probe = pcie_advk_probe, |
828d3262 T |
1009 | .remove = pcie_advk_remove, |
1010 | .flags = DM_FLAG_OS_PREPARE, | |
41575d8e | 1011 | .priv_auto = sizeof(struct pcie_advk), |
e51f2b14 | 1012 | }; |