diff options
author | Dan Crowell <dcrowell@us.ibm.com> | 2011-09-08 16:08:26 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2011-10-05 12:49:57 -0500 |
commit | 336f6ac6abc1d5ee4efc1229be06a66baf06643b (patch) | |
tree | e3476d2423567ad81249cc215d195dbc36c4a04f /src/usr/fsi/fsidd.H | |
parent | 485bb5c0e6d2c7c5df6560a996dc264e94f2058a (diff) | |
download | talos-hostboot-336f6ac6abc1d5ee4efc1229be06a66baf06643b.tar.gz talos-hostboot-336f6ac6abc1d5ee4efc1229be06a66baf06643b.zip |
Initialize the FSI hardware - Story 3551
This code will initialize the FSI hardware and allow access
to remote slaves.
Note - current code is hardcoded to using the MFSI-0 port on the
master processor wrapped back into its own CFAM.
Note2 - One testcase is disabled pending integration of required
fixes to the simics models.
Contains work for
- Task 3830 : FSI Master Regs
- Task 3831 : FSI Slave Regs
Change-Id: I8dd5f0e03cf083e35cf8241db22ad6d76ba85fac
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/359
Tested-by: Jenkins Server
Reviewed-by: Thi N. Tran <thi@us.ibm.com>
Reviewed-by: ADAM R. MUHLE <armuhle@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/fsi/fsidd.H')
-rw-r--r-- | src/usr/fsi/fsidd.H | 296 |
1 files changed, 203 insertions, 93 deletions
diff --git a/src/usr/fsi/fsidd.H b/src/usr/fsi/fsidd.H index f577f6571..d87ca4ed2 100644 --- a/src/usr/fsi/fsidd.H +++ b/src/usr/fsi/fsidd.H @@ -26,97 +26,135 @@ #include <sys/sync.h> #include <util/locked/list.H> #include <list> +#include <errl/errlentry.H> +#include <usr/devicefw/driverif.H> +#include <fsi/fsiif.H> /** @file fsidd.H - * @brief Provides the interfaces to the FSI Device Driver + * @brief Provides the definition of the FSI Device Driver class */ -class FsiDD; - -// Predeclare these so we can make them friends -namespace FSI { -errlHndl_t ddRead(DeviceFW::OperationType i_opType, - TARGETING::Target* i_target, - void* io_buffer, - size_t& io_buflen, - int64_t i_accessType, - va_list i_args); -errlHndl_t ddWrite(DeviceFW::OperationType i_opType, - TARGETING::Target* i_target, - void* io_buffer, - size_t& io_buflen, - int64_t i_accessType, - va_list i_args); -} +//@todo - pre-declare fake attribute call +FSI::FsiChipInfo_t temp_attr_call(TARGETING::Target* i_target); /** * Class to handle the FSI Master operations - * there will be one instance per master + * there will be a single instance within hostboot */ class FsiDD { public: /** - * @brief Performs an FSI Read Operation + * @brief Static Initializer + * @param[in] Task Args pointer passed by init service + */ + static void init( void* i_taskArgs ); + + /** + * @brief Initialize the FSI hardware * - * @param[in] i_address Address to read (relative to FSI Master chip) - * @param[in] io_buflen Number of bytes to access, returns - * number of bytes actually read + * @param[out] o_numPorts Number of FSI ports that were + * successfully initialized + * + * @return errlHndl_t NULL on success + */ + errlHndl_t initializeHardware( uint64_t& o_numPorts ); + + /** + * @brief Performs an FSI Read Operation to an absolute address + * + * @param[in] i_target Chip target of FSI operation + * @param[in] i_address Address to read (relative to target) * @param[out] o_buffer Destination buffer for data * * @return errlHndl_t NULL on success */ - errlHndl_t read(uint64_t i_address, - size_t& io_buflen, + errlHndl_t read(TARGETING::Target* i_target, + uint64_t i_address, uint32_t* o_buffer); /** * @brief Performs an FSI Write Operation * - * @param[in] i_address Address to read (relative to FSI Master chip) - * @param[in] io_buflen Number of bytes to access, returns - * number of bytes actually written - * @param[out] o_buffer Source buffer for data + * @param[in] i_target Chip target of FSI operation + * @param[in] i_address Address to write (relative to target) + * @param[out] i_buffer Source buffer for data * * @return errlHndl_t NULL on success */ - errlHndl_t write(uint64_t i_address, - size_t& io_buflen, + errlHndl_t write(TARGETING::Target* i_target, + uint64_t i_address, uint32_t* i_buffer); + + protected: + /** + * @brief Constructor + */ + FsiDD(); + + + /** + * @brief Destructor + */ + ~FsiDD(); + /** - * @brief Initializes the FSI bus for the given slave + * @brief Performs an FSI Read Operation * - * @param[in] Chip target of FSI-slave + * @param[in] i_address Address to read (relative to FSI Master chip) + * @param[out] o_buffer Destination buffer for data * * @return errlHndl_t NULL on success */ - errlHndl_t initSlave(TARGETING::Target* i_target); + errlHndl_t read(uint64_t i_address, + uint32_t* o_buffer); - protected: /** - * @brief Constructor + * @brief Performs an FSI Write Operation to an absolute address + * + * @param[in] i_address Absolute address to write + * @param[out] i_buffer Source buffer for data + * + * @return errlHndl_t NULL on success + */ + errlHndl_t write(uint64_t i_address, + uint32_t* i_buffer); + + /** + * @brief Initializes the FSI master control registers * - * @param[in] XSCOM target associated with this FSI Master instance + * @param[in] i_master Target of FSI master chip to initialize + * @param[in] i_type Type of FSI interface + * + * @return errlHndl_t NULL on success */ - FsiDD( TARGETING::Target* i_target ); + errlHndl_t initMasterControl(TARGETING::Target* i_master, + FSI::MasterType i_type); /** - * @brief Destructor + * @brief Initializes the FSI link to allow slave access + * + * @param[in] Chip target of FSI-Master + * @param[in] Type of FSI-Master + * @param[in] FSI port (0-7) being initialized (relative to master) + * + * @return errlHndl_t NULL on success */ - ~FsiDD(); + errlHndl_t initPort(TARGETING::Target* i_master, + FSI::MasterType i_type, + uint64_t i_port); /** * @brief Verify Request is in appropriate address range * * @param[in] i_address Starting address (relative to FSI Device) - * @param[in] i_length Number of bytes being accessed * * @return errlHndl_t NULL on success */ - errlHndl_t verifyAddressRange(uint64_t i_address, - size_t i_length); + errlHndl_t verifyAddressRange(uint64_t i_address); + /** * @brief Analyze error bits and recover hardware as needed @@ -167,26 +205,39 @@ class FsiDD uint64_t genOpbScomAddr(uint64_t i_opbOffset); /** - * @brief Initializes the FSI master control registers + * @brief Compute a few useful FSI values based on the target of the + * FSI operation, this will look up some attributes under the covers. * - * @return errlHndl_t NULL on success + * @param[in] i_master Target of FSI Master + * @param[in] i_type Type of FSI interface + * @param[in] i_port FSI link number (relative to master) + * @param[out] o_masterOffset Address offset for master control regs + * @param[out] o_slaveOffset Address offset for slave regs + * @param[out] o_portBit 1-hot bitstring with this chip's port set */ - errlHndl_t initMaster(); + void getFsiInfo( TARGETING::Target* i_master, + FSI::MasterType i_type, + uint8_t i_port, + uint64_t& o_masterOffset, + uint64_t& o_slaveOffset, + uint32_t& o_portBit ); + /** - * FSI Address Space + * @brief Convert a type/port pair into a FSI address offset + * + * @param[in] i_type Type of FSI interface + * @param[in] i_port FSI link number + * @return uint64_t FSI address offset */ - enum { - // Local FSI Space - CFAM_CONFIG_TABLE = 0x000000, /**< Configuration Table of CFAM */ - PEEK_TABLE = 0x000400, /**< Peek Table */ - FSI_SLAVE_REG = 0x000800, /**< FSI Slave Register */ - FSI_SHIFT_ENGINE = 0x000C00, /**< FSI Shift Engine (SCAN) */ - FSI2PIB_ENGINE = 0x001000, /**< FSI2PIB Engine (SCOM) */ - FSI_SCRATCHPAD = 0x001400, /**< FSI Scratchpad */ - FSI_I2C_MASTER = 0x001800, /**< FSI I2C-Master */ - FSI_GEMINI_MBOX = 0x002800, /**< FSI Gemini Mailbox with FSI GPx Registers */ + uint64_t getPortOffset(FSI::MasterType i_type, + uint8_t i_port); + + /** + * FSI Address Space + */ + enum FsiAddressSpace { // Master control registers CMFSI_CONTROL_REG = 0x003000, /**< cMFSI Control Register */ MFSI_CONTROL_REG = 0x003400, /**< MFSI Control Register */ @@ -210,6 +261,7 @@ class FsiDD CMFSI_SLAVE_3 = 0x006000, /**< cMFSI - Slave 3 */ // MFSI Ports (512KB each) + MFSI_PORT_LOCAL = 0x000000, /**< Local master (used for local cMFSI) */ MFSI_PORT_0 = 0x080000, /**< MFSI port 0 */ MFSI_PORT_1 = 0x100000, /**< MFSI port 1 */ MFSI_PORT_2 = 0x180000, /**< MFSI port 2 */ @@ -219,13 +271,19 @@ class FsiDD MFSI_PORT_6 = 0x380000, /**< MFSI port 6 */ MFSI_PORT_7 = 0x400000, /**< MFSI port 7 */ MFSI_PORT_MASK = 0x780000, /**< Mask to look for a valid MFSI port */ + + // Offsets to cascaded slaves within a MFSI port + MFSI_SLAVE_0 = 0x000000, /**< MFSI - Slave 0 */ + MFSI_SLAVE_1 = 0x020000, /**< MFSI - Slave 1 */ + MFSI_SLAVE_2 = 0x040000, /**< MFSI - Slave 2 */ + MFSI_SLAVE_3 = 0x060000, /**< MFSI - Slave 3 */ }; /** * PIB2OPB Registers */ - enum { + enum Pib2OpbRegisters { OPB_REG_CMD = 0x0000, /**< Command Register */ OPB_REG_STAT = 0x0001, /**< Status Register */ OPB_REG_LSTAT = 0x0002, /**< Locked Status */ @@ -244,7 +302,7 @@ class FsiDD // Bit masks OPB_STAT_BUSY = 0x00010000, /**< Bit 15 is the Busy bit */ - OPB_STAT_READ_VALID = 0x00020000, /**< Bit 15 is the Busy bit */ + OPB_STAT_READ_VALID = 0x00020000, /**< Bit 14 is the Valid Read bit */ OPB_STAT_ERR_OPB = 0x09F00000, /**< 4,7-11 are OPB errors */ OPB_STAT_ERR_CMFSI = 0x0000FC00, /**< 16-21 are cMFSI errors */ OPB_STAT_ERR_MFSI = 0x000000FC, /**< 24-29 are MFSI errors */ @@ -253,60 +311,112 @@ class FsiDD MAX_OPB_ATTEMPTS = 10, /**< Maximum number of attempts for OPB reg ops */ }; - + //@todo - move to external header? /** - * Global mutex @todo - make this per target for efficiency + * FSI Control Registers */ - mutex_t iv_fsiMutex; + enum FsiControlRegisters { + FSI_MMODE_000 = 0x000, + FSI_MDLYR_004 = 0x004, + FSI_MCRSP0_008 = 0x008, + FSI_MLEVP0_018 = 0x018, + FSI_MSIEP0_030 = 0x030, + FSI_MAEB_070 = 0x070, + FSI_MRESP0_0D0 = 0x0D0, + FSI_MRESP0_0D1 = 0x0D1, + FSI_MRESP0_0D2 = 0x0D2, + FSI_MRESP0_0D3 = 0x0D3, + FSI_MRESP0_0D4 = 0x0D4, + FSI_MRESP0_0D5 = 0x0D5, + FSI_MRESP0_0D6 = 0x0D6, + FSI_MRESP0_0D7 = 0x0D7, + FSI_MECTRL_2E0 = 0x2E0 + }; + //@todo - move to external header? /** - * Associated target of FSI Master, i.e. XSCOM target + * FSI Slave Registers + * These registers are repeated for every master+port+cascade combo */ - TARGETING::Target* iv_target; + enum FsiSlaveRegisters { + // Local FSI Space + FSIS_CFG_TABLE = 0x000000, /**< Configuration Table of CFAM */ + FSIS_PEEK_TABLE = 0x000400, /**< Peek Table */ - private: - // let my testcase poke around - friend class FsiDDTest; + FSI_SLAVE_REGS = 0x000800, /**< FSI Slave Register */ + FSIS_MODE_00 = FSI_SLAVE_REGS| 0x00, + FSI_SHIFT_ENGINE = 0x000C00, /**< FSI Shift Engine (SCAN) */ + FSI2PIB_ENGINE = 0x001000, /**< FSI2PIB Engine (SCOM) */ + FSI_SCRATCHPAD = 0x001400, /**< FSI Scratchpad */ + FSI_I2C_MASTER = 0x001800, /**< FSI I2C-Master */ + FSI_GEMINI_MBOX = 0x002800, /**< FSI Gemini Mailbox with FSI GPx Registers */ + }; - friend errlHndl_t FSI::ddRead(DeviceFW::OperationType i_opType, - TARGETING::Target* i_target, - void* io_buffer, - size_t& io_buflen, - int64_t i_accessType, - va_list i_args); - friend errlHndl_t FSI::ddWrite(DeviceFW::OperationType i_opType, - TARGETING::Target* i_target, - void* io_buffer, - size_t& io_buflen, - int64_t i_accessType, - va_list i_args); + /** + * General Constants + */ + enum Constants { + MAX_SLAVE_PORTS = 8, /**< Maximum of 8 slave ports */ + LOCAL_MFSI_PORT_SELECT = MAX_SLAVE_PORTS + FSI::MFSI_TYPE, + LOCAL_CMFSI_PORT_SELECT = MAX_SLAVE_PORTS + FSI::CMFSI_TYPE, + }; - /********** - * STATIC - **********/ + /** + * @brief Retrieve the control register address based on type + * @param[in] i_type Type of FSI interface + * @return uint64_t FSI address offset + */ + uint64_t getControlReg(FSI::MasterType i_type) + { + uint64_t ctl_reg = MFSI_CONTROL_REG; + if( FSI::CMFSI_TYPE == i_type ) + { + ctl_reg = CMFSI_CONTROL_REG; + } + return ctl_reg; + }; /** - * List of available instances + * @brief Retrieve the slave enable index + * @param[in] i_master Target of FSI Master + * @param[in] i_type Type of FSI interface + * @return uint64_t Index into iv_slaves array */ - static std::vector<FsiDD*> cv_instances; + uint64_t getSlaveEnableIndex( TARGETING::Target* i_master, + FSI::MasterType i_type ) + { + //default to local slave ports + uint64_t slave_index = MAX_SLAVE_PORTS+i_type; + if( i_master != iv_master ) + { + FSI::FsiChipInfo_t m_info = temp_attr_call(i_master); + slave_index = m_info.port; + } + return slave_index; + }; /** - * Global mutex to handle updates to gv_instances + * Global mutex */ - static mutex_t cv_mux; + mutex_t iv_fsiMutex; + /** + * Active slaves, 1 bit per port, 1=active, + * one entry per MFSI port, plus local MFSI and local cMFSI + */ + uint8_t iv_slaves[MAX_SLAVE_PORTS+2]; - public: /** - * @brief Select the instance for the given target - * - * @param[in] i_target TARGETING::Target* i_target - * - * @return FsiDD* Pointer to instance that matches the target + * Master processor target */ - static FsiDD* getInstance( TARGETING::Target* i_target ); + TARGETING::Target* iv_master; + + private: + + // let my testcase poke around + friend class FsiDDTest; }; |