/* * Copyright (c) 2009-2010 NVIDIA Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the NVIDIA Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "nvcommon.h" #include "nvodm_query_gpio.h" #include "nvodm_modules.h" #include "nvodm_query_discovery.h" #include "nvodm_query.h" #include "nvrm_drf.h" #include "subboards/nvodm_query_discovery_pm275_addresses.h" static NvOdmPeripheralConnectivity s_Peripherals_Default[] = { #include "subboards/nvodm_query_discovery_pm275_peripherals.h" }; #define PROCESSOR_BOARD_ID_I2C_ADDRESS ((0x56)<<1) #define NVODM_QUERY_I2C_CLOCK_SPEED 100 // kHz #define NVODM_QUERY_BOARD_HEADER_START 0x04 // Offset to Part Number in EERPOM #define NVODM_QUERY_I2C_EEPROM_ADDRESS 0xA0 // I2C device base address for EEPROM (7'h50) #define EEPROM_ID_PM275 0x024B #define VENTANA_REV_C_ACCEL NV_ODM_GUID('k','x','t','9','-','0','0','0') #define VENTANA_REV_A_ACCEL NV_ODM_GUID('k','x','t','9','-','0','9','0') static NvOdmI2cStatus NvOdmPeripheralI2cRead8( NvOdmServicesI2cHandle hOdmI2c, NvU8 I2cAddr, NvU8 Offset, NvU8 *pData) { NvU8 ReadBuffer[1]; NvOdmI2cStatus Error; NvOdmI2cTransactionInfo TransactionInfo; ReadBuffer[0] = Offset; TransactionInfo.Address = I2cAddr; TransactionInfo.Buf = ReadBuffer; TransactionInfo.Flags = NVODM_I2C_IS_WRITE; TransactionInfo.NumBytes = 1; Error = NvOdmI2cTransaction( hOdmI2c, &TransactionInfo, 1, NVODM_QUERY_I2C_CLOCK_SPEED, NV_WAIT_INFINITE); if (Error != NvOdmI2cStatus_Success) { return Error; } NvOdmOsMemset(ReadBuffer, 0, sizeof(ReadBuffer)); TransactionInfo.Address = (I2cAddr | 0x1); TransactionInfo.Buf = ReadBuffer; TransactionInfo.Flags = 0; TransactionInfo.NumBytes = 1; // Read data from ROM at the specified offset Error = NvOdmI2cTransaction( hOdmI2c, &TransactionInfo, 1, NVODM_QUERY_I2C_CLOCK_SPEED, NV_WAIT_INFINITE); if (Error != NvOdmI2cStatus_Success) { return Error; } *pData = ReadBuffer[0]; return Error; } static NvBool NvOdmPeripheralReadPartNumber( NvOdmServicesI2cHandle hOdmI2c, NvU8 EepromInst, NvOdmBoardInfo *pBoardInfo) { NvOdmI2cStatus Error; NvU32 i; NvU8 I2cAddr, Offset; NvU8 ReadBuffer[sizeof(NvOdmBoardInfo)]; NvOdmOsMemset(ReadBuffer, 0, sizeof(ReadBuffer)); // EepromInst*2, since 7-bit addressing I2cAddr = NVODM_QUERY_I2C_EEPROM_ADDRESS + (EepromInst << 1); /** * Offset to the board number entry in EEPROM. */ Offset = NVODM_QUERY_BOARD_HEADER_START; for (i=0; iBoardID = BoardModuleTable.BoardID; pBoardInfo->SKU = BoardModuleTable.SKU; pBoardInfo->Fab = BoardModuleTable.Fab; pBoardInfo->Revision = BoardModuleTable.Revision; pBoardInfo->MinorRevision = BoardModuleTable.MinorRevision; return NV_TRUE; } // Match not found pBoardInfo = NULL; return NV_FALSE; } static const NvOdmPeripheralConnectivity *NvApGetAllPeripherals(NvU32 *pNum) { *pNum = NV_ARRAY_SIZE(s_Peripherals_Default); return s_Peripherals_Default; } static NvU32 ReadBoardFabVersion(void) { NvOdmBoardInfo BoardInfo; NvBool IsBoardPresent; static NvBool s_IsFabRead = NV_FALSE; static NvU32 BoardFabNumber = -1; if (!s_IsFabRead) { IsBoardPresent = NvOdmPeripheralGetBoardInfo(EEPROM_ID_PM275, &BoardInfo); if (!IsBoardPresent) { return BoardFabNumber; } s_IsFabRead = NV_TRUE; BoardFabNumber = BoardInfo.Fab; } return BoardFabNumber; } // This implements a simple linear search across the entire set of currently- // connected peripherals to find the set of GUIDs that Match the search // criteria. More clever implementations are possible, but given the // relatively small search space (max dozens of peripherals) and the relative // infrequency of enumerating peripherals, this is the easiest implementation. const NvOdmPeripheralConnectivity *NvOdmPeripheralGetGuid(NvU64 SearchGuid) { const NvOdmPeripheralConnectivity *pAllPeripherals; NvU32 NumPeripherals; NvU32 i; NvU32 BoardFabNum; pAllPeripherals = NvApGetAllPeripherals(&NumPeripherals); if (!pAllPeripherals || !NumPeripherals) return NULL; BoardFabNum = ReadBoardFabVersion(); if ((SearchGuid == VENTANA_REV_A_ACCEL) && (BoardFabNum != 0)) return NULL; if ((SearchGuid == VENTANA_REV_C_ACCEL) && (BoardFabNum != 2)) return NULL; for (i = 0; i < NumPeripherals; i++) { if (SearchGuid == pAllPeripherals[i].Guid) { return &pAllPeripherals[i]; } } return NULL; } static NvBool IsBusMatch( const NvOdmPeripheralConnectivity *pPeriph, const NvOdmPeripheralSearch *pSearchAttrs, const NvU32 *pSearchVals, NvU32 offset, NvU32 NumAttrs) { NvU32 i, j; NvBool IsMatch = NV_FALSE; for (i=0; iNumAddress; i++) { j = offset; do { switch (pSearchAttrs[j]) { case NvOdmPeripheralSearch_IoModule: IsMatch = (pSearchVals[j] == (NvU32)(pPeriph->AddressList[i].Interface)); break; case NvOdmPeripheralSearch_Address: IsMatch = (pSearchVals[j] == pPeriph->AddressList[i].Address); break; case NvOdmPeripheralSearch_Instance: IsMatch = (pSearchVals[j] == pPeriph->AddressList[i].Instance); break; case NvOdmPeripheralSearch_PeripheralClass: default: NV_ASSERT(!"Bad Query!"); break; } j++; } while (IsMatch && jClass)); break; case NvOdmPeripheralSearch_IoModule: IsMatch = IsBusMatch(pPeriph, pSearchAttrs, pSearchVals, i, NumAttrs); break; case NvOdmPeripheralSearch_Address: case NvOdmPeripheralSearch_Instance: // In correctly-formed searches, these parameters will be parsed by // IsBusMatch, so we ignore them here. break; default: NV_ASSERT(!"Bad search attribute!"); break; } } return IsMatch; } NvU32 NvOdmPeripheralEnumerate( const NvOdmPeripheralSearch *pSearchAttrs, const NvU32 *pSearchVals, NvU32 NumAttrs, NvU64 *pGuidList, NvU32 NumGuids) { const NvOdmPeripheralConnectivity *pAllPeripherals; NvU32 NumPeripherals; NvU32 Matches; NvU32 i; pAllPeripherals = NvApGetAllPeripherals(&NumPeripherals); if (!pAllPeripherals || !NumPeripherals) { return 0; } if (!pSearchAttrs || !pSearchVals) { NumAttrs = 0; } for (i=0, Matches=0; i