4 * Copyright(c) 2017 Cavium, Inc.. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Cavium, Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "lio_common.h"
39 #include "lio_response_manager.h"
40 #include "lio_device.h"
41 #include "lio_mem_ops.h"
43 #define MEMOPS_IDX LIO_MAX_BAR1_MAP_INDEX
45 #if BYTE_ORDER == BIG_ENDIAN
47 lio_toggle_bar1_swapmode(struct octeon_device *oct, uint32_t idx)
51 mask = oct->fn_list.bar1_idx_read(oct, idx);
52 mask = (mask & 0x2) ? (mask & ~2) : (mask | 2);
53 oct->fn_list.bar1_idx_write(oct, idx, mask);
56 #else /* BYTE_ORDER != BIG_ENDIAN */
57 #define lio_toggle_bar1_swapmode(oct, idx)
58 #endif /* BYTE_ORDER == BIG_ENDIAN */
61 lio_write_bar1_mem8(struct octeon_device *oct, uint32_t reg, uint64_t val)
64 bus_space_write_1(oct->mem_bus_space[1].tag,
65 oct->mem_bus_space[1].handle, reg, val);
69 static inline uint32_t
70 lio_read_bar1_mem32(struct octeon_device *oct, uint32_t reg)
73 return (bus_space_read_4(oct->mem_bus_space[1].tag,
74 oct->mem_bus_space[1].handle, reg));
78 lio_write_bar1_mem32(struct octeon_device *oct, uint32_t reg, uint32_t val)
81 bus_space_write_4(oct->mem_bus_space[1].tag,
82 oct->mem_bus_space[1].handle, reg, val);
86 static inline uint64_t
87 lio_read_bar1_mem64(struct octeon_device *oct, uint32_t reg)
91 return (lio_read_bar1_mem32(oct, reg) |
92 ((uint64_t)lio_read_bar1_mem32(oct, reg + 4) << 32));
94 return (bus_space_read_8(oct->mem_bus_space[1].tag,
95 oct->mem_bus_space[1].handle, reg));
100 lio_write_bar1_mem64(struct octeon_device *oct, uint32_t reg, uint64_t val)
104 lio_write_bar1_mem32(oct, reg, (uint32_t)val);
105 lio_write_bar1_mem32(oct, reg + 4, val >> 32);
107 bus_space_write_8(oct->mem_bus_space[1].tag,
108 oct->mem_bus_space[1].handle, reg, val);
113 lio_pci_fastwrite(struct octeon_device *oct, uint32_t offset,
114 uint8_t *hostbuf, uint32_t len)
117 while ((len) && ((unsigned long)offset) & 7) {
118 lio_write_bar1_mem8(oct, offset++, *(hostbuf++));
122 lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
125 lio_write_bar1_mem64(oct, offset, *((uint64_t *)hostbuf));
131 lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
134 lio_write_bar1_mem8(oct, offset++, *(hostbuf++));
137 static inline uint64_t
138 lio_read_bar1_mem8(struct octeon_device *oct, uint32_t reg)
141 return (bus_space_read_1(oct->mem_bus_space[1].tag,
142 oct->mem_bus_space[1].handle, reg));
146 lio_pci_fastread(struct octeon_device *oct, uint32_t offset,
147 uint8_t *hostbuf, uint32_t len)
150 while ((len) && ((unsigned long)offset) & 7) {
151 *(hostbuf++) = lio_read_bar1_mem8(oct, offset++);
155 lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
158 *((uint64_t *)hostbuf) = lio_read_bar1_mem64(oct, offset);
164 lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
167 *(hostbuf++) = lio_read_bar1_mem8(oct, offset++);
170 /* Core mem read/write with temporary bar1 settings. */
171 /* op = 1 to read, op = 0 to write. */
173 lio_pci_rw_core_mem(struct octeon_device *oct, uint64_t addr,
174 uint8_t *hostbuf, uint32_t len, uint32_t op)
176 uint64_t static_mapping_base;
177 uint32_t copy_len = 0, index_reg_val = 0;
180 static_mapping_base = oct->console_nb_info.dram_region_base;
182 if (static_mapping_base && static_mapping_base ==
183 (addr & 0xFFFFFFFFFFC00000ULL)) {
184 int bar1_index = oct->console_nb_info.bar1_index;
186 offset = (bar1_index << 22) + (addr & 0x3fffff);
189 lio_pci_fastread(oct, offset, hostbuf, len);
191 lio_pci_fastwrite(oct, offset, hostbuf, len);
195 mtx_lock(&oct->mem_access_lock);
197 /* Save the original index reg value. */
198 index_reg_val = oct->fn_list.bar1_idx_read(oct, MEMOPS_IDX);
200 oct->fn_list.bar1_idx_setup(oct, addr, MEMOPS_IDX, 1);
201 offset = (MEMOPS_IDX << 22) + (addr & 0x3fffff);
204 * If operation crosses a 4MB boundary, split the transfer
205 * at the 4MB boundary.
207 if (((addr + len - 1) & ~(0x3fffff)) != (addr & ~(0x3fffff))) {
208 copy_len = (uint32_t)(((addr & ~(0x3fffff)) +
209 (MEMOPS_IDX << 22)) - addr);
214 if (op) { /* read from core */
215 lio_pci_fastread(oct, offset, hostbuf,
218 lio_pci_fastwrite(oct, offset, hostbuf,
228 oct->fn_list.bar1_idx_write(oct, MEMOPS_IDX, index_reg_val);
230 mtx_unlock(&oct->mem_access_lock);
234 lio_pci_read_core_mem(struct octeon_device *oct, uint64_t coreaddr,
235 uint8_t *buf, uint32_t len)
238 lio_pci_rw_core_mem(oct, coreaddr, buf, len, 1);
242 lio_pci_write_core_mem(struct octeon_device *oct, uint64_t coreaddr,
243 uint8_t *buf, uint32_t len)
246 lio_pci_rw_core_mem(oct, coreaddr, buf, len, 0);
250 lio_read_device_mem64(struct octeon_device *oct, uint64_t coreaddr)
254 lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&ret, 8, 1);
256 return (be64toh(ret));
260 lio_read_device_mem32(struct octeon_device *oct, uint64_t coreaddr)
264 lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&ret, 4, 1);
266 return (be32toh(ret));
270 lio_write_device_mem32(struct octeon_device *oct, uint64_t coreaddr,
273 __be32 t = htobe32(val);
275 lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&t, 4, 0);