diff options
author | Glenn Miles <milesg@us.ibm.com> | 2015-02-18 13:54:50 -0600 |
---|---|---|
committer | Derk Rembold <rembold@de.ibm.com> | 2015-02-19 09:45:49 -0600 |
commit | f7a56090b73768f8fec063e41aba12662ee59a45 (patch) | |
tree | d2373137870269e93d215ba65319ad1af4b131c3 /pk/ppe42/ppe42_scom.c | |
parent | d84a1393ddec82dda67207a6f21edb5153877b5a (diff) | |
download | talos-sbe-f7a56090b73768f8fec063e41aba12662ee59a45.tar.gz talos-sbe-f7a56090b73768f8fec063e41aba12662ee59a45.zip |
Seed the files in the pk directory
Change-Id: I03398098e6625f0e06e4a96769b03002a1c71d35
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15813
Reviewed-by: Glenn R. Miles <milesg@us.ibm.com>
Reviewed-by: Derk Rembold <rembold@de.ibm.com>
Tested-by: Derk Rembold <rembold@de.ibm.com>
Diffstat (limited to 'pk/ppe42/ppe42_scom.c')
-rw-r--r-- | pk/ppe42/ppe42_scom.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/pk/ppe42/ppe42_scom.c b/pk/ppe42/ppe42_scom.c new file mode 100644 index 00000000..e9fe2e6c --- /dev/null +++ b/pk/ppe42/ppe42_scom.c @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppe42_scom.c +/// \brief Lowest level PK SCOM definitions. +/// +/// Currently these SCOM functions are only optimized for functionality, not +/// speed. Speed optimization will be done when we have full compiler support +/// for the low-level stvd and lvd SCOM OPs. +/// +/// A FAPI-lite SCOM can call these PK SCOM functions. +/// +/// Comment: +/// - No need to poll for SCOM completion, nor return error code of SCOM fails. +/// A SCOM fail will cause the GPE to hang if configured to do so. But do we +/// necessarily have to do this? Wouldn't a gentle recovery from a SCOM fail +/// be preferred? + +#include "pk.h" +#include "ppe42_scom.h" + + +uint32_t putscom_abs(uint32_t i_address, uint64_t i_data) +{ + + // CMO-Declaring variables tied to specific registers enables us to protect + // the SCOM data and address variables used in the new stvd and lvd 64-bit + // scom instructions. This protection is needed since the new instructions' + // operands are not yet properly considered by the compiler. + // Note that l_dataH is used to represent the "beginning", i.e. High-order, + // part of the 64-bit data in d8 (i.e., r8+r9). + uint32_t register l_dataH asm("r8")=0; + uint32_t register l_dataL asm("r9")=0; + uint32_t register l_addr_eff asm("r10")=0; + uint32_t register l_scratch asm("r31")=0; + + l_addr_eff = i_address; + l_dataH = (uint32_t)(i_data>>32); + l_dataL = (uint32_t)(i_data); + + // CMO-The following sequence forces usage of l_dataH/L and l_addr_eff + // and thus the population of them as well. + // Further note that unless l_dataH/L are placed right before the following + // sequence, more specifically, if they're placed at the top of putscom(), + // r8, or l_dataH, might be overwritten in the if(chiplet_id) section. + // Secondly, we test l_addr_eff for non-zero through the CR0 register + // (which was populated in the "mr." instruction.) This is to convince the + // compiler that we actually used l_addr_eff for something. + // At present the test result causes no action except to execute the stvd + // instruction in either case. + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_dataH) ); + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_dataL) ); + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_addr_eff) ); + asm volatile ( \ + "beq 0x4 \n" ); + + // CMO-This instruction is not fully supported by the compiler (as of + // 20150108): + // - Works: It is correctly translated into the proper OP code + // format. + // - Works not: The compiler does not seem to recognize the usage + // of the two l_xyz variables in that it doesn't + // know prior to this command that the registers that + // contain the values of l_xyz need to be protected + // up to this point. Thus, we are forced to use those + // two l_xyz variables in some dummy instructions just + // before this point in order to fake protection. + asm volatile ( \ + "stvd %[data], 0(%[effective_address]) \n" \ + : [data]"=r"(l_dataH) \ + : [effective_address]"r"(l_addr_eff) ); + + // CMO-TBD + // Check PIB response code in 0x00001007(17:19) + // Translate PIB rc to PK rc + // Does this rc get reset to zero on success? + // Do we need to check this rc prior to issuing the SCOM? + + return 0; +} + +uint32_t _putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t i_data) +{ + uint32_t l_rc=0; + uint32_t l_cid=0; + uint32_t l_addr_eff=0; + + if (i_chiplet_id) + { + // Accommodate two different ways of supplying the chiplet ID: + // 0xNN000000: Only bits in high-order two nibbles : Valid + // 0x000000NN: Only bits in low-order two nibbles : Valid + // + if ((i_chiplet_id & 0xFF000000) == i_chiplet_id) + { + // Valid: Chiplet ID in high-order two nibbles. + l_cid = i_chiplet_id; + } + else if ((i_chiplet_id & 0x000000FF) == i_chiplet_id) + { + // Valid: Chiplet ID in low-order two nibbles. Convert to high-order. + l_cid = i_chiplet_id << 24; + } + else + { + // Invalid: Invalid type of chiplet ID + PK_TRACE("putscom() : Invalid value of i_chiplet_id (=0x%08X)",i_chiplet_id); + return 1; //CMO-improve Return sensible rc here. + } + + l_addr_eff = (i_address & 0x00FFFFFF) | l_cid; + } + else + { + // Chiplet ID is zero. Accept address as is. + // This is useful for PIB addresses and non-EX chiplets, and even for + // EX chiplets if the fully qualified EX chiplet addr is already known. + l_addr_eff = i_address; + + } + + l_rc = putscom_abs(l_addr_eff, i_data); + + + return l_rc; +} + + +uint32_t getscom_abs( uint32_t i_address, uint64_t *o_data) +{ + + // CMO-Declaring variables tied to specific registers enables us to protect + // the SCOM data and address variables used in the new stvd and lvd 64-bit + // data instructions. This protection is needed since the new instructions + // are not yet properly considered by the compiler. + // Note that l_dataH is used to represent the "beginning", i.e. High-order, + // part of the 64-bit data in d8 (i.e., r8+r9). + uint32_t register l_dataH asm("r8")=0; + uint32_t register l_dataL asm("r9")=0; + uint32_t register l_addr_eff asm("r10")=0; + uint32_t register l_scratch asm("r31")=0; + + + l_addr_eff = i_address; + + // CMO-The following sequence forces usage of l_addr_eff and thus the + // population of it as well. + // Secondly, we test l_addr_eff for non-zero through the CR0 register + // (which was populated in the "mr." instruction.) This is to convince the + // compiler that we actually used l_addr_eff for something. + // At present the test result causes no action except to execute the lvd + // instruction in either case. + asm volatile ( \ + "mr. %0, %1 \n" \ + : "=r"(l_scratch) \ + : "r"(l_addr_eff) ); + asm volatile ( \ + "beq 0x4 \n" ); + + asm volatile ( \ + "lvd %[data], 0(%[effective_address]) \n" \ + : [data]"=r"(l_dataH) \ + : [effective_address]"r"(l_addr_eff) ); + + // CMO-The following sequence moves the read data, in l_dataH/L, into the + // 64-bit o_data location. + asm volatile ( \ + "stw %0, 0(%1) \n" \ + : "=r"(l_dataH) \ + : "r"(o_data) ); + asm volatile ( \ + "stw %0, 4(%1) \n" \ + : "=r"(l_dataL) \ + : "r"(o_data) ); + + // CMO-TBD + // Check PIB response code in 0x00001007(17:19) + // Translate PIB rc to PK rc + + return 0; +} + +uint32_t _getscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t *o_data) +{ + uint32_t l_rc=0; + uint32_t l_cid=0; + uint32_t l_addr_eff=0; + + if (i_chiplet_id) + { + // Accommodate two different ways of supplying the chiplet ID: + // 0xNN000000: Only bits in high-order two nibbles : Valid + // 0x000000NN: Only bits in low-order two nibbles : Valid + // + if ((i_chiplet_id & 0xFF000000) == i_chiplet_id) + { + // Valid: Chiplet ID in high-order two nibbles. + l_cid = i_chiplet_id; + } + else if ((i_chiplet_id & 0x000000FF) == i_chiplet_id) + { + // Valid: Chiplet ID in low-order two nibbles. Convert to high-order. + l_cid = i_chiplet_id << 24; + } + else + { + // Invalid: Invalid type of chiplet ID + PK_TRACE("getscom() : Invalid value of i_chiplet_id (=0x%08X)",i_chiplet_id); + return 1; //CMO-improve Return sensible rc here. + } + + l_addr_eff = (i_address & 0x00FFFFFF) | l_cid; + } + else + { + // Chiplet ID is zero. Accept address as is. + // This is useful for PIB addresses and non-EX chiplets, and even for + // EX chiplets if the fully qualified EX chiplet addr is already known. + l_addr_eff = i_address; + } + + l_rc = getscom_abs(l_addr_eff, o_data); + + // CMO-TBD + // Check PIB response code in 0x00001007(17:19) + // Translate PIB rc to PK rc + + return l_rc; +} |