xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libbdk-hal/bdk-pcie.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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