summaryrefslogtreecommitdiffstats
path: root/pk/ppe42/ppe42_scom.c
diff options
context:
space:
mode:
authorGlenn Miles <milesg@us.ibm.com>2015-02-18 13:54:50 -0600
committerDerk Rembold <rembold@de.ibm.com>2015-02-19 09:45:49 -0600
commitf7a56090b73768f8fec063e41aba12662ee59a45 (patch)
treed2373137870269e93d215ba65319ad1af4b131c3 /pk/ppe42/ppe42_scom.c
parentd84a1393ddec82dda67207a6f21edb5153877b5a (diff)
downloadtalos-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.c241
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;
+}
OpenPOWER on IntegriCloud