summaryrefslogtreecommitdiffstats
path: root/src/usr/lpc/lpcdd.H
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/lpc/lpcdd.H')
-rw-r--r--src/usr/lpc/lpcdd.H338
1 files changed, 338 insertions, 0 deletions
diff --git a/src/usr/lpc/lpcdd.H b/src/usr/lpc/lpcdd.H
new file mode 100644
index 000000000..598c5fab8
--- /dev/null
+++ b/src/usr/lpc/lpcdd.H
@@ -0,0 +1,338 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/lpc/lpcdd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014 */
+/* [+] Google Inc. */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __LPC_LPCDD_H
+#define __LPC_LPCDD_H
+
+#include <limits.h>
+#include <sys/sync.h>
+#include <stdint.h>
+#include <errl/errlentry.H>
+#include <lpc/lpcif.H>
+
+/** @file lpcdd.H
+ * @brief Provides the interfaces to the LPC Device Driver
+ */
+
+/**
+ * @brief LPC Device Driver Class
+ * Provides access to the LPC bus for a specific Processor
+ */
+class LpcDD
+{
+ public:
+ /**
+ * @brief Performs a LPC Read Operation
+ *
+ * @param i_trans LPC transaction type
+ * @param i_address LPC address
+ * @param o_buffer Buffer to read data into
+ * @param io_buflen Input: Number of bytes to read,
+ * Output: Number of bytes actually read
+ *
+ * @return Error from operation
+ */
+ errlHndl_t readLPC(LPC::TransType i_type,
+ uint32_t i_address,
+ void* o_buffer,
+ size_t& io_buflen);
+
+ /**
+ * @brief Performs a LPC Write Operation
+ *
+ * @param i_trans LPC transaction type
+ * @param i_address LPC address
+ * @param i_buffer Buffer to write data from
+ * @param io_buflen Input: Number of bytes to write,
+ * Output: Number of bytes actually written
+ *
+ * @return Error from operation
+ */
+ errlHndl_t writeLPC(LPC::TransType i_type,
+ uint32_t i_address,
+ const void* i_buffer,
+ size_t& io_buflen);
+
+
+ /**
+ * @brief Enums for different levels of resetting PNOR communication levels
+ */
+ enum ResetLevels
+ {
+ RESET_CLEAR = 0x00000000, /**< Clear Reset Level */
+ RESET_ECCB = 0x00000001, /**< ECCB FW Logic */
+ RESET_OPB_LPCHC_SOFT = 0x00000002, /**< OPB LPCHC Clear Errors */
+ RESET_OPB_LPCHC_HARD = 0x00000004, /**< OPB LPCHC Reset Logic */
+
+ RESET_INIT = RESET_CLEAR, // Nothing to do for initial boot yet
+ };
+
+
+ /**
+ * @brief Reset hardware to get into clean state
+ *
+ * @parm i_resetLevel How much LPC logic to reset
+ *
+ * @return errlHndl_t NULL on success, else error log
+ */
+ errlHndl_t hwReset( ResetLevels i_resetLevel );
+
+ /**
+ * @brief Get the target associated with this dd instance
+ *
+ * @return Pointer to target
+ */
+ TARGETING::Target* getProc( void )
+ {
+ return iv_proc;
+ };
+
+ /**
+ * @brief Constructor
+ * @param[in] Processor target associated with the ECCB logic
+ */
+ LpcDD( TARGETING::Target* i_proc
+ = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL );
+
+
+ /**
+ * @brief Destructor
+ */
+ ~LpcDD();
+
+ protected:
+ /**
+ * @brief LPC HC Registers
+ * These are offsets within the LPC Host Controller Register Space
+ */
+ enum LpcRegAddr {
+ LPC_REG_BAR0 = 0x00, /**< BAR0 : OPB register */
+ LPC_REG_BAR1 = 0x04, /**< BAR1 : LPC I/O space */
+ LPC_REG_BAR2 = 0x08, /**< BAR2 : LPC Memory space */
+ LPC_REG_BAR3 = 0x0C, /**< BAR3 : LPC Firmware space */
+ LPC_REG_ABRTCNT = 0x2C, /**< ABORT COUNT */
+ };
+
+
+ /**
+ * @brief Some general constants
+ *
+ */
+ enum {
+ LPCHC_FW_SPACE = 0xF0000000, /**< LPC Host Controller FW Space */
+ LPCHC_MEM_SPACE = 0xE0000000, /**< LPC Host Controller Mem Space */
+ LPCHC_IO_SPACE = 0xD0010000, /**< LPC Host Controller I/O Space */
+ LPCHC_REG_SPACE = 0xC0012000, /**< LPC Host Ctlr Register Space */
+
+ ECCB_NON_FW_RESET_REG = 0x000B0001, /**< ECCB Reset Reg (non-FW) */
+
+ ECCB_CTL_REG = 0x000B0020, /**< ECCB Control Reg (FW) */
+ ECCB_RESET_REG = 0x000B0021, /**< ECCB Reset Reg (FW) */
+ ECCB_STAT_REG = 0x000B0022, /**< ECCB Status Reg (FW) */
+ ECCB_DATA_REG = 0x000B0023, /**< ECCB Data Reg (FW) */
+
+ // Default Values to set for all operations
+ // 1101.0100.0000.000x.0000.0001.0000.0000.<address>
+ ECCB_CTL_REG_DEFAULT = 0xD400010000000000,
+
+ // Error bits: 41-43, 56 (52=cmd complete) (not 57: only non-fw use)
+ ECCB_STAT_REG_ERROR_MASK = 0x0000000000700080, /**< Error Bits */
+
+ /**< OPB LPCM Sync FIR Reg - used to read the FIR*/
+ OPB_LPCM_FIR_REG = 0x01010C00,
+
+ /**< OPB LPCM Sync FIR Reg WOX_AND - used to clear the FIR */
+ OPB_LPCM_FIR_WOX_AND_REG = 0x01010C01,
+
+ /**< OPB LPCM Sync FIR Mask Reg WO_OR - used to set the mask */
+ OPB_LPCM_FIR_MASK_WO_OR_REG = 0x01010C05,
+
+ OPB_LPCM_FIR_ERROR_MASK = 0xFF00000000000000, /**< Error Bits MASK */
+
+ // LPCHC reset-related registers
+ OPB_MASTER_LS_CONTROL_REG = 0x008, /**<OPBM LS Control Reg */
+ LPCHC_RESET_REG = 0x0FC, /**<LPC HC Reset Register */
+
+ ECCB_RESET_LPC_FAST_RESET = 1ULL << 62, /**< bit 1 = Fast reset */
+
+ ECCB_POLL_TIME_NS = 400000, /**< max time should be 400ms */
+ ECCB_POLL_INCR_NS = 10, /**< minimum increment during poll */
+
+ LPCHC_SYNC_CYCLE_COUNTER_INFINITE = 0xFF000000
+ };
+
+ /**
+ * @brief ECCB Control Register Layout
+ */
+ union ControlReg_t
+ {
+ uint64_t data64;
+ struct
+ {
+ // unused sections should be set to zero
+ uint64_t magic1 : 4; /**< 0:3 = b1101 per spec */
+ uint64_t data_len : 4; /**< 4:7 = b0100 means 4 byte */
+ uint64_t unused1 : 7; /**< 8:14 */
+ uint64_t read_op : 1; /**< 15 = set for read operation */
+ uint64_t unused2 : 7; /**< 16:22 */
+ uint64_t addr_len : 3; /**< 23:25 = b100 means 4 byte */
+ uint64_t unused3 : 6; /**< 26:31 */
+ uint64_t address : 32; /**< 32:63 = LPC Address */
+ };
+
+ ControlReg_t() : data64(ECCB_CTL_REG_DEFAULT) {};
+ };
+
+ /**
+ * @brief ECCB Status Register Layout
+ */
+ union StatusReg_t
+ {
+ uint64_t data64;
+ struct
+ {
+ uint64_t unused : 6; /**< 0:5 */
+ uint64_t read_data : 32; /**< 6:37 */
+ uint64_t unused1 : 3; /**< 38:40 */
+ uint64_t eccb_err : 3; /**< 41:43 = ECCB_Error_Info */
+ uint64_t busy : 1; /**< 44 = Operation Busy */
+ uint64_t unused2 : 7; /**< 45:51 */
+ uint64_t op_done : 1; /**< 52 = Command Complete */
+ uint64_t unused3 : 3; /**< 53:55 */
+ uint64_t addr_parity_err : 1; /**< 56 = ECC Address Register
+ Parity Error */
+ uint64_t unused4 : 7; /**< 57:63 */
+ };
+ StatusReg_t() : data64(0) {};
+ };
+
+ /**
+ * @brief OPB-LPCM FIR Register Layout
+ */
+ union OpbLpcmFirReg_t
+ {
+ uint64_t data64;
+ struct
+ {
+ uint64_t rxits : 1; // Invalid Transfer Size
+ uint64_t rxicmd : 1; // Invalid Command
+ uint64_t rxiaa : 1; // Invalid Address Alignment
+ uint64_t rxhopbe : 1; // OPB Bus Error
+ uint64_t rxhopbt : 1; // OPB Bus Timeout
+ uint64_t rxctgtel : 1; // CI Load/CI Store/OPB Master Hang Timeout
+ uint64_t rxcbpe : 1; // Command Buffer Parity Error
+ uint64_t rxdbpe : 1; // Data Buffer Parity Error
+ uint64_t reserved : 56;
+ };
+ OpbLpcmFirReg_t() : data64(0) {};
+ };
+
+
+ /**
+ * @brief Check For Errors in OPB and LPCHC Status Registers
+ *
+ * @parm o_resetLevel if error, reset level to clear error
+ * @return Error log if error found
+ */
+ errlHndl_t checkForOpbErrors( ResetLevels &o_resetLevel );
+
+ /**
+ * @brief Sanity check the input address for a LPC op and return
+ * full absolute address
+ *
+ * @param[in] i_type LPC range
+ * @param[in] i_addr Relative LPC address
+ * @param[out] o_addr Absolute LPC address
+ *
+ * @return Error from operation
+ */
+ errlHndl_t checkAddr( LPC::TransType i_type,
+ uint32_t i_addr,
+ uint32_t* o_addr );
+
+ /**
+ * @brief Poll for completion of LPC operation
+ *
+ * @param[in] i_ctrl Control register describing operation
+ * @param[out] o_stat Status register for failures
+ *
+ * @return errlHndl_t NULL on success, else error log
+ */
+ errlHndl_t pollComplete( const ControlReg_t& i_ctrl,
+ StatusReg_t& o_stat );
+
+ /**
+ * @brief Add Error Registers to an existing Error Log
+ * @param[inout] io_errl Error log to add data to
+ */
+ void addFFDC(errlHndl_t& io_errl);
+
+ private:
+ /**
+ * @brief Mutex to prevent concurrent LPC accesses to the master
+ */
+ static mutex_t cv_mutex;
+
+ /**
+ * @brief Mutex to prevent concurrent LPC accesses to a given
+ * instance of the LPC logic
+ * Note: this is unused for Master
+ */
+ mutex_t iv_mutex;
+
+ /**
+ * @brief Pointer to mutex in use
+ */
+ mutex_t* ivp_mutex;
+
+ /**
+ * @brief Processor target associated with the ECCB logic
+ */
+ TARGETING::Target* iv_proc;
+
+ /**
+ * @brief Marker to avoid infinite recursion in error handlers
+ */
+ bool iv_ffdcActive;
+
+ /**
+ * @brief Number of times recovered from an error
+ */
+ uint32_t iv_errorHandledCount;
+
+ /**
+ * @brief Indicates recovery from an error has failed
+ */
+ bool iv_errorRecoveryFailed;
+
+ /**
+ * @brief Indicates if class is currently doing a RESET procedure
+ */
+ bool iv_resetActive;
+
+};
+
+
+#endif
OpenPOWER on IntegriCloud