1 /***********************license start***********************************
2 * Copyright (c) 2003-2017 Cavium Inc. ([email protected]). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * * Neither the name of Cavium Inc. nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
21 * permission.
22 *
23 * This Software, including technical data, may be subject to U.S. export
24 * control laws, including the U.S. Export Administration Act and its
25 * associated regulations, and may be subject to export or import
26 * regulations in other countries.
27 *
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
37 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39 #include <bdk.h>
40 #include "libbdk-hal/bdk-pcie.h"
41 #include "libbdk-hal/bdk-utils.h"
42 #include "libbdk-hal/if/bdk-if.h"
43
44 /* This code is an optional part of the BDK. It is only linked in
45 if BDK_REQUIRE() needs it */
46 BDK_REQUIRE_DEFINE(PCIE);
47
48 /**
49 * Read 8bits from a Device's config space
50 *
51 * @param pcie_port PCIe port the device is on
52 * @param bus Sub bus
53 * @param dev Device ID
54 * @param fn Device sub function
55 * @param reg Register to access
56 *
57 * @return Result of the read
58 */
bdk_pcie_config_read8(bdk_node_t node,int pcie_port,int bus,int dev,int fn,int reg)59 uint8_t bdk_pcie_config_read8(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg)
60 {
61 uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
62 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Read8(bus=%d, dev=%d, fn=%d, reg=0x%x, internal=0x%llx)\n",
63 node, pcie_port, bus, dev, fn, reg, address);
64 uint8_t result;
65 if (address)
66 result = bdk_read64_uint8(address);
67 else
68 result = 0xff;
69 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Result=0x%02x\n", node, pcie_port, result);
70 return result;
71 }
72
73
74 /**
75 * Read 16bits from a Device's config space
76 *
77 * @param pcie_port PCIe port the device is on
78 * @param bus Sub bus
79 * @param dev Device ID
80 * @param fn Device sub function
81 * @param reg Register to access
82 *
83 * @return Result of the read
84 */
bdk_pcie_config_read16(bdk_node_t node,int pcie_port,int bus,int dev,int fn,int reg)85 uint16_t bdk_pcie_config_read16(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg)
86 {
87 uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
88 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Read16(bus=%d, dev=%d, fn=%d, reg=0x%x, internal=0x%llx)\n",
89 node, pcie_port, bus, dev, fn, reg, address);
90 uint16_t result;
91 if (address)
92 result = bdk_le16_to_cpu(bdk_read64_uint16(address));
93 else
94 result = 0xffff;
95 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Result=0x%04x\n", node, pcie_port, result);
96 return result;
97 }
98
99
100 /**
101 * Read 32bits from a Device's config space
102 *
103 * @param pcie_port PCIe port the device is on
104 * @param bus Sub bus
105 * @param dev Device ID
106 * @param fn Device sub function
107 * @param reg Register to access
108 *
109 * @return Result of the read
110 */
bdk_pcie_config_read32(bdk_node_t node,int pcie_port,int bus,int dev,int fn,int reg)111 uint32_t bdk_pcie_config_read32(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg)
112 {
113 uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
114 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Read32(bus=%d, dev=%d, fn=%d, reg=0x%x, internal=0x%llx)\n",
115 node, pcie_port, bus, dev, fn, reg, address);
116
117 uint32_t result;
118 if (address)
119 result = bdk_le32_to_cpu(bdk_read64_uint32(address));
120 else
121 result = 0xffffffff;
122 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Result=0x%08x\n", node, pcie_port, result);
123
124 /* Errata ECAM-22630: CN88XX pass 1.x, except pass 1.0, will return zero
125 for non-existent devices instead of ones. We look for this special case
126 for 32bit reads for reg=0 so we can scan device properly */
127 if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X) && (reg == 0) && (result == 0))
128 result = 0xffffffff;
129
130 return result;
131 }
132
133
134 /**
135 * Write 8bits to a Device's config space
136 *
137 * @param pcie_port PCIe port the device is on
138 * @param bus Sub bus
139 * @param dev Device ID
140 * @param fn Device sub function
141 * @param reg Register to access
142 * @param val Value to write
143 */
bdk_pcie_config_write8(bdk_node_t node,int pcie_port,int bus,int dev,int fn,int reg,uint8_t val)144 void bdk_pcie_config_write8(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg, uint8_t val)
145 {
146 uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
147 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Write8(bus=%d, dev=%d, fn=%d, reg=0x%x, val=0x%02x, internal=0x%llx)\n",
148 node, pcie_port, bus, dev, fn, reg, val, address);
149 if (address)
150 bdk_write64_uint8(address, val);
151 }
152
153
154 /**
155 * Write 16bits to a Device's config space
156 *
157 * @param pcie_port PCIe port the device is on
158 * @param bus Sub bus
159 * @param dev Device ID
160 * @param fn Device sub function
161 * @param reg Register to access
162 * @param val Value to write
163 */
bdk_pcie_config_write16(bdk_node_t node,int pcie_port,int bus,int dev,int fn,int reg,uint16_t val)164 void bdk_pcie_config_write16(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg, uint16_t val)
165 {
166 uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
167 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Write16(bus=%d, dev=%d, fn=%d, reg=0x%x, val=0x%04x, internal=0x%llx)\n",
168 node, pcie_port, bus, dev, fn, reg, val, address);
169 if (address)
170 bdk_write64_uint16(address, bdk_cpu_to_le16(val));
171 }
172
173
174 /**
175 * Write 32bits to a Device's config space
176 *
177 * @param pcie_port PCIe port the device is on
178 * @param bus Sub bus
179 * @param dev Device ID
180 * @param fn Device sub function
181 * @param reg Register to access
182 * @param val Value to write
183 */
bdk_pcie_config_write32(bdk_node_t node,int pcie_port,int bus,int dev,int fn,int reg,uint32_t val)184 void bdk_pcie_config_write32(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg, uint32_t val)
185 {
186 uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
187 BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Write32(bus=%d, dev=%d, fn=%d, reg=0x%x, val=0x%08x, internal=0x%llx)\n",
188 node, pcie_port, bus, dev, fn, reg, val, address);
189 if (address)
190 bdk_write64_uint32(address, bdk_cpu_to_le32(val));
191 }
192
193 /**
194 * Read 64bits from PCIe using a memory transaction
195 *
196 * @param node Node to read from
197 * @param pcie_port PCIe port to read
198 * @param address PCIe address to read
199 *
200 * @return Result of the read
201 */
bdk_pcie_mem_read64(bdk_node_t node,int pcie_port,uint64_t address)202 uint64_t bdk_pcie_mem_read64(bdk_node_t node, int pcie_port, uint64_t address)
203 {
204 uint64_t base_address = bdk_pcie_get_base_address(node, pcie_port, BDK_PCIE_MEM_NORMAL);
205 return bdk_read64_uint64(base_address + address);
206 }
207
208 /**
209 * Write 64bits to PCIe memory
210 *
211 * @param node Node to write to
212 * @param pcie_port PCIe port to use
213 * @param address Address to write
214 * @param data Data to write
215 */
bdk_pcie_mem_write64(bdk_node_t node,int pcie_port,uint64_t address,uint64_t data)216 void bdk_pcie_mem_write64(bdk_node_t node, int pcie_port, uint64_t address, uint64_t data)
217 {
218 uint64_t base_address = bdk_pcie_get_base_address(node, pcie_port, BDK_PCIE_MEM_NORMAL);
219 bdk_write64_uint64(base_address + address, data);
220 }
221
222