|
| 1 | +/* IBM_PROLOG_BEGIN_TAG */ |
| 2 | +/* This is an automatically generated prolog. */ |
| 3 | +/* */ |
| 4 | +/* $Source: import/chips/p9/procedures/ppe_closed/ippe/ioa/io_lib.c $ */ |
| 5 | +/* */ |
| 6 | +/* OpenPOWER HCODE Project */ |
| 7 | +/* */ |
| 8 | +/* COPYRIGHT 2018 */ |
| 9 | +/* [+] International Business Machines Corp. */ |
| 10 | +/* */ |
| 11 | +/* */ |
| 12 | +/* Licensed under the Apache License, Version 2.0 (the "License"); */ |
| 13 | +/* you may not use this file except in compliance with the License. */ |
| 14 | +/* You may obtain a copy of the License at */ |
| 15 | +/* */ |
| 16 | +/* http://www.apache.org/licenses/LICENSE-2.0 */ |
| 17 | +/* */ |
| 18 | +/* Unless required by applicable law or agreed to in writing, software */ |
| 19 | +/* distributed under the License is distributed on an "AS IS" BASIS, */ |
| 20 | +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ |
| 21 | +/* implied. See the License for the specific language governing */ |
| 22 | +/* permissions and limitations under the License. */ |
| 23 | +/* */ |
| 24 | +/* IBM_PROLOG_END_TAG */ |
| 25 | +// *!--------------------------------------------------------------------------- |
| 26 | +// *! (C) Copyright International Business Machines Corp. 2016 |
| 27 | +// *! All Rights Reserved -- Property of IBM |
| 28 | +// *! *** IBM Confidential *** |
| 29 | +// *!--------------------------------------------------------------------------- |
| 30 | +// *! FILENAME : io_lib.c |
| 31 | +// *! TITLE : |
| 32 | +// *! DESCRIPTION : |
| 33 | +// *! |
| 34 | +// *! OWNER NAME : John Rell Email: jgrell@us.ibm.com |
| 35 | +// *! BACKUP NAME : Mike Spear Email: mspear@us.ibm.com |
| 36 | +// *! |
| 37 | +// *!--------------------------------------------------------------------------- |
| 38 | +// CHANGE HISTORY: |
| 39 | +//------------------------------------------------------------------------------ |
| 40 | +// Version ID: |Author: | Comment: |
| 41 | +// ------------|--------|------------------------------------------------------- |
| 42 | +// vbr17072600 |vbr | Copied gcr_wr_raw from other branch. |
| 43 | +// vbr16081800 |vbr | Moved some functions from eo_common to io_lib (and renamed some). |
| 44 | +// vbr16070700 |vbr | Removed deprecated put/get; minor stack/code size optimizations |
| 45 | +// vbr16070100 |vbr | Removed RMW option from put_ptr_int (only does RMW). |
| 46 | +// vbr16062800 |vbr | Optimization |
| 47 | +// mbs16062400 |mbs | Added gcr_addr struct |
| 48 | +// mbs16062400 |mbs | Added put_ptr, put_ptr_fast, and get_ptr functions |
| 49 | +// vbr16050500 |vbr |- Moved mem_regs and various functions from eo_common to io_lib |
| 50 | +// vbr16050300 |vbr |- Added lcl_get() |
| 51 | +// mbs16040800 |mbs |- Added instance parm to mmio_put and mmio_get, and adjusted bit fields |
| 52 | +// ----------------------------------------------------------------------------- |
| 53 | + |
| 54 | +#include "io_lib.h" |
| 55 | +#include "pk.h" |
| 56 | + |
| 57 | +#include "ppe_mem_reg_const_pkg.h" |
| 58 | +#include "ppe_com_reg_const_pkg.h" |
| 59 | +#include "ppe_opt_reg_const_pkg.h" |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | +//////////////////////////////////////////////////////////////////////////////////////////// |
| 64 | +// GCR ADDRESS FORMING FUNCTIONS |
| 65 | +//////////////////////////////////////////////////////////////////////////////////////////// |
| 66 | + |
| 67 | +// These functions are setup to interace with a "t_gcr_addr" structure which is only infrequently updated. |
| 68 | +// A pointer to this structure can be passed down the call stack and provide all the necessary information |
| 69 | +// to put and get functions as well as precalculated masks |
| 70 | + |
| 71 | +void set_gcr_addr(t_gcr_addr* gcr_addr, int bus_id, int reg_id, int lane) |
| 72 | +{ |
| 73 | + gcr_addr->bus_id = bus_id; |
| 74 | + gcr_addr->reg_id = reg_id; |
| 75 | + gcr_addr->lane = lane; |
| 76 | + |
| 77 | + // Single thread on gcr_port 0 |
| 78 | + gcr_addr->gcr_port_addr = 0xC0000200; |
| 79 | + |
| 80 | + gcr_addr->gcr_read_packet = |
| 81 | + 0x9000000000E00000 //base_gcr_write_msg |
| 82 | + | ((uint64_t)bus_id << (63 - 10)) // 53 |
| 83 | + | ((uint64_t)reg_id << (63 - 16)) // 47 |
| 84 | + | ((uint64_t)lane << (63 - 31)); // 32 |
| 85 | + |
| 86 | + gcr_addr->gcr_write_packet = gcr_addr->gcr_read_packet | 0x0800000000000000; |
| 87 | + |
| 88 | + return; |
| 89 | +}; |
| 90 | + |
| 91 | + |
| 92 | +void set_gcr_addr_bus_id(t_gcr_addr* gcr_addr, int bus_id) |
| 93 | +{ |
| 94 | + gcr_addr->bus_id = bus_id; |
| 95 | + |
| 96 | + gcr_addr->gcr_read_packet = (gcr_addr->gcr_read_packet & 0xf81fffffffffffff) |
| 97 | + | ((uint64_t)bus_id << (63 - 10)); |
| 98 | + |
| 99 | + gcr_addr->gcr_write_packet = gcr_addr->gcr_read_packet | 0x0800000000000000; |
| 100 | + |
| 101 | + return; |
| 102 | +} |
| 103 | + |
| 104 | +void set_gcr_addr_reg_id(t_gcr_addr* gcr_addr, int reg_id) |
| 105 | +{ |
| 106 | + gcr_addr->reg_id = reg_id; |
| 107 | + |
| 108 | + gcr_addr->gcr_read_packet = (gcr_addr->gcr_read_packet & 0xffe07fffffffffff) |
| 109 | + | ((uint64_t)reg_id << (63 - 16)); |
| 110 | + |
| 111 | + gcr_addr->gcr_write_packet = gcr_addr->gcr_read_packet | 0x0800000000000000; |
| 112 | + |
| 113 | + return; |
| 114 | +} |
| 115 | + |
| 116 | +void set_gcr_addr_lane(t_gcr_addr* gcr_addr, int lane) |
| 117 | +{ |
| 118 | + gcr_addr->lane = lane; |
| 119 | + |
| 120 | + gcr_addr->gcr_read_packet = (gcr_addr->gcr_read_packet & 0xffffffe0ffffffff) |
| 121 | + | ((uint64_t)lane << (63 - 31)); |
| 122 | + |
| 123 | + gcr_addr->gcr_write_packet = gcr_addr->gcr_read_packet | 0x0800000000000000; |
| 124 | + |
| 125 | + return; |
| 126 | +} |
| 127 | + |
| 128 | + |
| 129 | +//////////////////////////////////////////////////////////////////////////////////////////// |
| 130 | +// HW I/O FUNCTIONS |
| 131 | +//////////////////////////////////////////////////////////////////////////////////////////// |
| 132 | + |
| 133 | +void mmio_put(int instance, int addr, int data) |
| 134 | +{ |
| 135 | + uint64_t volatile* lclmem_addr = (uint64_t*)(0xC0000250); |
| 136 | + |
| 137 | + (*lclmem_addr) = |
| 138 | + 0x8000000000000000 // 0, write |
| 139 | + | ((uint64_t)instance << (63 - 11)) // 2:3, DL Instance (00 : DL0, 01 : DL1, 10 : DL2, 11 : PHY) |
| 140 | + | ((uint64_t)addr << (63 - 11)) // 11:31 |
| 141 | + | ((uint64_t)data); // 32:63 |
| 142 | + |
| 143 | + // poll for msg rcvd flag to indicate an echo |
| 144 | + while ( ((*lclmem_addr) & 0x3) == 0x0 ); |
| 145 | + |
| 146 | + return; |
| 147 | +} |
| 148 | + |
| 149 | +uint32_t mmio_get(int instance, int addr) |
| 150 | +{ |
| 151 | + uint64_t volatile* lclmem_addr = (uint64_t*)(0xC0000250); |
| 152 | + |
| 153 | + (*lclmem_addr) = |
| 154 | + 0x0000000000000000 // 0, read |
| 155 | + | ((uint64_t)instance << (63 - 11)) // 2:3, DL Instance (00 : DL0, 01 : DL1, 10 : DL2, 11 : PHY) |
| 156 | + | ((uint64_t)addr << (63 - 11)); // 11:31 |
| 157 | + |
| 158 | + // poll for read data flag |
| 159 | + uint64_t result = (*lclmem_addr); |
| 160 | + |
| 161 | + while ( (result & 0x1) == 0x0 ) |
| 162 | + { |
| 163 | + result = (*lclmem_addr); |
| 164 | + }; |
| 165 | + |
| 166 | + uint32_t r_data = (uint32_t)(result >> 32); |
| 167 | + |
| 168 | + return r_data; // 16 bits |
| 169 | + |
| 170 | + //return; |
| 171 | +} |
| 172 | + |
| 173 | + |
| 174 | +// This allows writing a raw GCR packet to the bus. |
| 175 | +// Primarily meant as a workaround for the GCR interrupt packet not being ack'd. |
| 176 | +void gcr_wr_raw(t_gcr_addr* gcr_addr, uint64_t packet) |
| 177 | +{ |
| 178 | + // Setup the pointer |
| 179 | + uint64_t volatile* lclmem_addr = (uint64_t*)gcr_addr->gcr_port_addr; |
| 180 | + |
| 181 | + // wait on previous op while start bit is set but echo flag is not set |
| 182 | + while (((*lclmem_addr) & 0xC000000000000003) == 0x8000000000000000 ); |
| 183 | + |
| 184 | + // send write op and exit |
| 185 | + (*lclmem_addr) = packet; |
| 186 | +} //gcr_wr_raw |
| 187 | + |
| 188 | + |
| 189 | +// fast put where the packet is preformed and the data field uses all 16 bits so we just need to fill in the reg addr and 16-bit data |
| 190 | +//void put_ptr_fast_int(t_gcr_addr *gcr_addr, int reg_addr, int endbit, int data) { |
| 191 | +void put_ptr_fast_int(t_gcr_addr* gcr_addr, uint64_t reg_addr, int shift_amt, int data) |
| 192 | +{ |
| 193 | + //uint64_t w_data = data << (15+4 - endbit); |
| 194 | + uint64_t w_data = data << shift_amt; |
| 195 | + |
| 196 | + uint64_t packet = |
| 197 | + gcr_addr->gcr_write_packet |
| 198 | + | ((uint64_t)reg_addr) // already shifted |
| 199 | + | ((uint64_t)w_data); |
| 200 | + |
| 201 | + // Put result to reg |
| 202 | + uint64_t volatile* lclmem_addr = (uint64_t*)gcr_addr->gcr_port_addr; |
| 203 | + |
| 204 | + // wait on previous op while start bit is set but echo flag is not set |
| 205 | + while (((*lclmem_addr) & 0xC000000000000003) == 0x8000000000000000 ); |
| 206 | + |
| 207 | + // send write op and exit |
| 208 | + (*lclmem_addr) = packet; |
| 209 | + |
| 210 | + return; |
| 211 | +} |
| 212 | + |
| 213 | + |
| 214 | +// put where the packet is preformed. always does read-modify-write. |
| 215 | +void put_ptr_int(t_gcr_addr* gcr_addr, uint64_t reg_addr, uint64_t and_mask, int shift_amt, int data) |
| 216 | +{ |
| 217 | + uint64_t volatile* lclmem_addr = (uint64_t*)gcr_addr->gcr_port_addr; |
| 218 | + uint64_t packet; |
| 219 | + uint64_t w_data; |
| 220 | + |
| 221 | + // For a read-modify-write, first do a read of the register in question. |
| 222 | + // However we don't need to do a full get() because we don't care about shifting the |
| 223 | + // data around. |
| 224 | + |
| 225 | + packet = |
| 226 | + gcr_addr->gcr_read_packet |
| 227 | + | ((uint64_t)reg_addr);// already shifted |
| 228 | + |
| 229 | + // wait on previous op while start bit is set but echo flag or read response flag is not set |
| 230 | + while (((*lclmem_addr) & 0xC000000000000003) == 0x8000000000000000 ); |
| 231 | + |
| 232 | + (*lclmem_addr) = packet; |
| 233 | + |
| 234 | + |
| 235 | + // ****************************************************************** |
| 236 | + // Form AND and OR masks - do all this while the read command is running |
| 237 | + // ****************************************************************** |
| 238 | + |
| 239 | + /* |
| 240 | + // Form the mask by shifting a one N+1 times and then subtracting one to make a ones mask of length N |
| 241 | + uint64_t and_mask = (1 << (endbit - startbit + 1)) - 1; |
| 242 | +
|
| 243 | + // Shift the mask into the proper bit field for the gcr packet |
| 244 | + and_mask <<= (15+4 - endbit); |
| 245 | +
|
| 246 | + // Invert the mask so all the bits except the start/end bit data field are ones (e.g. xfffffffffffff1ff) |
| 247 | + and_mask = (~and_mask); |
| 248 | +
|
| 249 | + // Now mask off all but the actual 16 bit data field, so we have ones with hole in the middle (e.g. x00000000000ff1f0) |
| 250 | + and_mask &= 0x00000000000ffff0; |
| 251 | +
|
| 252 | + w_data = data << (15+4 - endbit); |
| 253 | + */ |
| 254 | + w_data = data << shift_amt; |
| 255 | + |
| 256 | + // Prepare or_mask |
| 257 | + uint64_t or_mask = |
| 258 | + gcr_addr->gcr_write_packet |
| 259 | + | ((uint64_t)reg_addr) // already shifted |
| 260 | + | ((uint64_t)w_data); // 4 |
| 261 | + |
| 262 | + // ****************************************************************** |
| 263 | + |
| 264 | + // poll for read response packet flag to indicate returned data |
| 265 | + packet = (*lclmem_addr); |
| 266 | + |
| 267 | + while ( (packet & 0x4000000000000000) == 0x0 ) |
| 268 | + { |
| 269 | + packet = (*lclmem_addr); |
| 270 | + }; |
| 271 | + |
| 272 | + // Apply masks |
| 273 | + packet &= and_mask; |
| 274 | + |
| 275 | + packet |= or_mask; |
| 276 | + |
| 277 | + // write data back and exit |
| 278 | + (*lclmem_addr) = packet; |
| 279 | + |
| 280 | + // poll for msg rcvd flag to indicate an echo |
| 281 | + //while ( ((*lclmem_addr) & 0x3) == 0x0 ); |
| 282 | + |
| 283 | + return; |
| 284 | +} //put_ptr_int |
| 285 | + |
| 286 | +void put_ptr_fast_id(t_gcr_addr* gcr_addr, int reg_id, uint64_t reg_addr, int endbit, int data) |
| 287 | +{ |
| 288 | + set_gcr_addr_reg_id(gcr_addr, reg_id); |
| 289 | + put_ptr_fast(gcr_addr, reg_addr, endbit, data); |
| 290 | +} |
| 291 | + |
| 292 | +void put_ptr_id (t_gcr_addr* gcr_addr, int reg_id, uint64_t reg_addr, int startbit, int endbit, int data, int rmw) |
| 293 | +{ |
| 294 | + set_gcr_addr_reg_id(gcr_addr, reg_id); |
| 295 | + put_ptr(gcr_addr, reg_addr, startbit, endbit, data, rmw); |
| 296 | +} |
| 297 | + |
| 298 | +uint32_t get_ptr_id (t_gcr_addr* gcr_addr, int reg_id, uint64_t reg_addr, int startbit, int endbit) |
| 299 | +{ |
| 300 | + set_gcr_addr_reg_id(gcr_addr, reg_id); |
| 301 | + return get_ptr(gcr_addr, reg_addr, startbit, endbit); |
| 302 | +} |
| 303 | + |
| 304 | + |
| 305 | +// get where the packet is preformed |
| 306 | +//uint32_t get_ptr_int(t_gcr_addr *gcr_addr, int reg_addr, int startbit, int endbit) { |
| 307 | +uint32_t get_ptr_int(t_gcr_addr* gcr_addr, uint64_t reg_addr, uint64_t and_mask, int shift_amt) |
| 308 | +{ |
| 309 | + uint64_t volatile* lclmem_addr = (uint64_t*)(gcr_addr->gcr_port_addr); |
| 310 | + |
| 311 | + (*lclmem_addr) = |
| 312 | + gcr_addr->gcr_read_packet |
| 313 | + | ((uint64_t)reg_addr);// already shifted |
| 314 | + |
| 315 | + /* |
| 316 | + // ****************************************************************** |
| 317 | + // Form AND mask - do all this while the read command is running |
| 318 | + // ****************************************************************** |
| 319 | + // Form the mask by shifting a one N+1 times and then subtracting one to make a ones mask of length N |
| 320 | + uint64_t and_mask = (1 << (endbit - startbit + 1)) - 1; |
| 321 | +
|
| 322 | + // Shift the mask into the proper bit field for the gcr packet |
| 323 | + uint32_t shift_amt = (4 + 15 - endbit); |
| 324 | +
|
| 325 | + and_mask <<= shift_amt; |
| 326 | +
|
| 327 | + // ****************************************************************** |
| 328 | + */ |
| 329 | + |
| 330 | + // poll for read response packet flag to indicate returned data |
| 331 | + uint64_t result = (*lclmem_addr); |
| 332 | + |
| 333 | + while ( (result & 0x4000000000000000) == 0x0 ) |
| 334 | + { |
| 335 | + result = (*lclmem_addr); |
| 336 | + }; |
| 337 | + |
| 338 | + uint32_t r_data = (uint32_t)((result & and_mask) >> shift_amt); |
| 339 | + |
| 340 | + return r_data; // 16 bits |
| 341 | +} |
| 342 | + |
| 343 | + |
| 344 | +void lcl_put(int reg_addr, int width, int data) |
| 345 | +{ |
| 346 | + |
| 347 | + uint64_t volatile* lclmem_addr = (uint64_t*)(0xC0000000 | reg_addr); |
| 348 | + |
| 349 | + (*lclmem_addr) = (uint64_t)data << (64 - width); |
| 350 | + |
| 351 | + return; |
| 352 | +} |
| 353 | + |
| 354 | +uint32_t lcl_get(int reg_addr, int width) |
| 355 | +{ |
| 356 | + uint64_t volatile* lclmem_addr = (uint64_t*)(0xC0000000 | reg_addr); |
| 357 | + uint32_t r_data = (uint32_t)((*lclmem_addr) >> (64 - width)); |
| 358 | + return r_data; |
| 359 | +} |
| 360 | + |
| 361 | +void set_fir() |
| 362 | +{ |
| 363 | + uint64_t volatile* fir_addr = (uint64_t*)(0xC0000240); |
| 364 | + |
| 365 | + (*fir_addr) = 0x1; // Any write will trigger the FIR, regardless of data |
| 366 | + |
| 367 | + return; |
| 368 | +} |
0 commit comments