diff options
author | Venu Byravarasu <vbyravarasu@nvidia.com> | 2010-05-17 11:30:37 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-17 11:38:48 -0700 |
commit | 7babb616e672128db7ec4a3efa8fbe0c09fed1b5 (patch) | |
tree | f55d88e06805192f334ecc4b93461accd6380e0a /arch/arm/mach-tegra/include/nvddk_fuse.h | |
parent | b8a0f3f1d92e521fb517219daa5083363a4a57e0 (diff) |
tegra-kernel-fuse: Add fuse burning support from Linux via sysfs
A fuse module is added to support programming and reading back
fuse values.
This module is built as part of kernel.
Bug 657504
Tested on: Whistler
Change-Id: I5663679c8d41834aa4077e9940a0595f6575af64
Reviewed-on: http://git-master/r/1259
Reviewed-by: Andy Carman <acarman@nvidia.com>
Tested-by: Andy Carman <acarman@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/include/nvddk_fuse.h')
-rw-r--r-- | arch/arm/mach-tegra/include/nvddk_fuse.h | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/nvddk_fuse.h b/arch/arm/mach-tegra/include/nvddk_fuse.h new file mode 100644 index 000000000000..52796d3c86f8 --- /dev/null +++ b/arch/arm/mach-tegra/include/nvddk_fuse.h @@ -0,0 +1,423 @@ +/* + * Copyright (c) 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. + * + */ + +#ifndef INCLUDED_NVDDK_FUSE_H +#define INCLUDED_NVDDK_FUSE_H + +#include "nvrm_module.h" +/** + * @defgroup nvddk_fuse_group Fuse Programming APIs + * + * Enables fuse programming. + * + * @par Library Usage + * + * - Calling the NvDdkDisableFuseProgram() API before exiting the boot loader + * disables further fuse programming until the next system reset. (See the + * example code.) + * - It is advised that you disable the JTAG while using this code in + * the final version. + * - Enabling clock and voltage to program the fuse is out of scope of this + * library. You must ensure that these are enabled prior to using the library + * functions. + * - The library works on physical mapped memory or on virtual mapped with + * one-to-one mapping for the fuse registers. + * + * @par Example Code + * + * The following example shows one way to use Fuse Programming APIs. + * @note You must ensure fuse clock and fuse voltage is enabled prior + * to programming fuses. + * + * @code + * // + * // Fuse Programming Example + * // + * #include "nvddk_fuse.h" + * #include "nvtest.h" + * #include "nvrm_init.h" + * #include "nvrm_pmu.h" + * #include "nvodm_query_discovery.h" + * #include "nvodm_services.h" + * + * #define DISABLE_PROGRMING_TEST 0 + * + * static NvError NvddkFuseProgramTest(NvTestApplicationHandle h ) + * { + * NvError err = NvSuccess; + * err = NvDdkFuseProgram(); + * if(err != NvError_Success) + * { + * NvOsDebugPrintf("NvDdkFuseProgram failed \n"); + * return err; + * } + * // Check fuse sense. + * NvDdkFuseSense(); + * // Verify the fuses and return the result. + * err = NvDdkFuseVerify(); + * if(err != NvError_Success) + * NvOsDebugPrintf("NvDdkFuseVerify failed \n"); + * return err; + * } + * + * static NvError PrepareFuseData(void) + * { + * // Initialize argument sizes to zero to perform initial queries. + * NvU32 BootDevSel_Size = 0; + * NvU32 BootDevConfig_Size = 0; + * NvU32 ResevOdm_size = 0; + * NvU32 size = 0; + * + * // Specify values to be programmed. + * NvU16 BootDevConfig_Data = 0x9; // Set device config value to 0x9. + * NvU8 BootDevSel_Data = 0x1; // Set boot select to 0x1 for NAND. + * NvU8 ResevOdm_Data[32] = {0xEF,0xCD,0xAB,0x89, + * 0x78,0x56,0x34,0x12, + * 0xa,0xb,0xc,0xd, + * 0xAA,0xBB,0xCC,0xDD, + * 0,0,0,0, + * 0,0,0,0, + * 0x78,0x56,0x34,0x12, + * 0x78,0x56,0x34,0x12}; + * + * NvU8 skpDevSelStrap_data = 1; + * NvError e; + * + * // Query the sizes of the fuse values. + * e = NvDdkFuseGet(NvDdkFuseDataType_SecBootDeviceSelect, + * &BootDevSel_Data, &BootDevSel_Size); + * if (e != NvError_Success) return e; + * + * e = NvDdkFuseGet(NvDdkFuseDataType_SecBootDeviceConfig, + * &BootDevConfig_Data, &BootDevConfig_Size); + * if (e != NvError_Success) return e; + * + * #ifdef DISABLE_PROGRMING_TEST + * NvDdkDisableFuseProgram(); + * #endif + * + * e = NvDdkFuseGet(NvDdkFuseDataType_ReservedOdm, + * &ResevOdm_Data, &ResevOdm_size); + * if (e != NvError_Success) return e; + * + * e = NvDdkFuseGet(NvDdkFuseDataType_SkipDevSelStraps, + * &skpDevSelStrap_data, &size); + * if (e != NvError_Success) return e; + * + * + * // Set the fuse values. + * e = NvDdkFuseSet(NvDdkFuseDataType_SecBootDeviceSelect, + * &BootDevSel_Data, &BootDevSel_Size); + * if (e != NvError_Success) return e; + * + * e = NvDdkFuseSet(NvDdkFuseDataType_SecBootDeviceConfig, + * &BootDevConfig_Data, &BootDevConfig_Size); + * if (e != NvError_Success) return e; + * + * e = NvDdkFuseSet(NvDdkFuseDataType_SkipDevSelStraps, + * &skpDevSelStrap_data, &size); + * if (e != NvError_Success) return e; + * + * + * e = NvDdkFuseSet(NvDdkFuseDataType_ReservedOdm, + * &ResevOdm_Data, &ResevOdm_size); + * if (e != NvError_Success) return e; + * + * return e; + * } + * + * + * NvError NvTestMain(int argc, char *argv[]) + * { + * NvTestApplication h; + * NvError err; + * + * NVTEST_INIT( &h ); + * // Enable fuse clock and fuse voltage prior to programming fuses. + * err = PrepareFuseData(); + * if( err != NvSuccess) + * return err; + * + * NvOdmOsWaitUS(10000); + * + * NVTEST_RUN(&h, NvddkFuseProgramTest); + * + * NVTEST_RESULT( &h ); + * } + * @endcode + * + * @ingroup nvddk_modules + * @{ + */ + +#if defined(__cplusplus) +extern "C" +{ +#endif + + +#include "nvcommon.h" +#include "nverror.h" + + +/* ----------- Program/Verify API's -------------- */ + +/** + * Defines types of fuse data to set or query. + */ +typedef enum +{ + /// Specifies a default (unset) value. + NvDdkFuseDataType_None = 0, + + /// Specifies a device key (DK). + NvDdkFuseDataType_DeviceKey, + + /** + * Specifies a JTAG disable flag: + * - NV_TRUE specifies to permanently disable JTAG-based debugging. + * - NV_FALSE indicates that JTAG-based debugging is not permanently + * disabled. + */ + NvDdkFuseDataType_JtagDisable, + + /** + * Specifies a key programmed flag (read-only): + * - NV_TRUE indicates that either the SBK or the DK value is nonzero. + * - NV_FALSE indicates that both the SBK and DK values are zero (0). + * + * @note Once the ODM production fuse is set to NV_TRUE, applications + * can no longer read back the SBK or DK value; however, by using + * this \c KeyProgrammed query it is still possible to determine + * whether or not the SBK or DK has been programmed to a nonzero value. + */ + NvDdkFuseDataType_KeyProgrammed, + + /** + * Specifies an ODM production flag: + * - NV_TRUE specifies the chip is in ODM production mode. + * - NV_FALSE indicates that the chip is not in ODM production mode. + */ + NvDdkFuseDataType_OdmProduction, + + /** + * Specifies a secondary boot device configuration. + * This value is chip-dependent. + * For Tegra APX 2600, use the NVBOOT_FUSE_*_CONFIG_* + * defines from: + * <pre> + * /src/drivers/hwinc/ap15/nvboot_fuse.h + * </pre> + */ + NvDdkFuseDataType_SecBootDeviceConfig, + + /** + * Specifies a secondary boot device selection. + * This value is chip-independent and is described in \c nvddk_bootdevices.h. + * The chip-dependent version of this data is + * ::NvDdkFuseDataType_SecBootDeviceSelectRaw. + * For Tegra APX 2600, the values for \c SecBootDeviceSelect and + * \c SecBootDeviceSelectRaw are identical. + */ + NvDdkFuseDataType_SecBootDeviceSelect, + + /** Specifies a secure boot key (SBK). */ + NvDdkFuseDataType_SecureBootKey, + + /** + * Specifies a stock-keeping unit (read-only). + * This value is chip-dependent. + * See chip-specific documentation for legal values. + */ + NvDdkFuseDataType_Sku, + + /** + * Specifies spare fuse bits (read-only). + * Reserved for future use by NVIDIA. + */ + NvDdkFuseDataType_SpareBits, + + /** + * Specifies software reserved fuse bits (read-only). + * Reserved for future use by NVIDIA. + */ + NvDdkFuseDataType_SwReserved, + + /** + * Specifies skip device select straps (applies to Tegra 200 series only): + * - NV_TRUE specifies to ignore the device selection straps setting + * and that the boot device is specified via the + * \c SecBootDeviceSelect and \c SecBootDeviceConfig fuse settings. + * - NV_FALSE indicates that the boot device is specified via the device + * selection straps setting. + */ + NvDdkFuseDataType_SkipDevSelStraps, + + /** + * Specifies a secondary boot device selection. + * This value is chip-dependent. + * The chip-independent version of this data is + * ::NvDdkFuseDataType_SecBootDeviceSelect. + * For Tegra APX 2600, use the \c NvBootFuseBootDevice enum + * values found at: + * <pre> + * /src/drivers/hwinc/ap15/nvboot_fuse.h + * </pre> + */ + NvDdkFuseDataType_SecBootDeviceSelectRaw, + + /** + * Specifies raw field for reserved the ODM. + * This value is ODM-specific. Reserved for customers. + */ + NvDdkFuseDataType_ReservedOdm, + + /** The following must be last. */ + NvDdkFuseDataType_Num, + /** Ignore -- Forces compilers to make 32-bit enums. */ + NvDdkFuseDataType_Force32 = 0x7FFFFFFF +} NvDdkFuseDataType; + +// Gets the base address for Fuse anc CAR modules. +// Call this function before accessing any other API of Fuse. +NvError NvDdkFuseOpen(NvRmDeviceHandle hRmDevice); + +// to free up all resources +void NvDdkFuseClose(void); +/** + * Gets a value from the fuse registers. + * + *@pre NvDdkFuseOpen should have been called before using this API + * @pre Do not call this function while the programming power is applied! + * + * After programming fuses and removing the programming power, + * NvDdkFuseSense() must be called to read the new values. + * + * By passing a size of 0, the caller is requesting to be told the + * expected size. + * + * Treatment of fuse data depends upon its size: + * - if \a *pSize == 1, treat \a *pData as an NvU8 + * - if \a *pSize == 2, treat \a *pData as an NvU16 + * - if \a *pSize == 4, treat \a *pData as an NvU32 + * - else, treat \a *pData as an array of NvU8 values (i.e., NvU8[]). + */ +NvError NvDdkFuseGet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize); + +/** + * Schedules fuses to be programmed to the specified values when the next + * NvDdkFuseProgram() operation is performed. + * + *@pre NvDdkFuseOpen should have been called before using this API + * + * @note Attempting to program the ODM production fuse at the same + * time as the SBK or DK causes an error, because it is not + * possible to verify that the SBK or DK were programmed correctly. + * After triggering this error, all further attempts to set fuse + * values will fail, as will \c NvDdkFuseProgram, until NvDdkFuseClear() + * has been called. + * + * By passing a size of 0, the caller is requesting to be told the + * expected size. + * + * Treatment of fuse data depends upon its size: + * - if \a *pSize == 1, treat \a *pData as an NvU8 + * - if \a *pSize == 2, treat \a *pData as an NvU16 + * - if \a *pSize == 4, treat \a *pData as an NvU32 + * - else, treat \a *pData as an array of NvU8 values (i.e., NvU8[]). + * + * @retval NvError_BadValue If other than "reserved ODM fuse" is set in ODM + * production mode. + * @retval NvError_AccessDenied If programming to fuse registers is disabled. + */ +NvError NvDdkFuseSet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize); + +/** + * Reads the current fuse data into the fuse registers. + * + *@pre NvDdkFuseOpen should have been called before using this API + * + * \c NvDdkFuseSense must be called at least once, either: + * - After programming fuses and removing the programming power, + * - Prior to calling NvDdkFuseVerify(), or + * - Prior to calling NvDdkFuseGet(). + */ +void NvDdkFuseSense(void); + +/** + * Programs all fuses based on cache data changed via the NvDdkFuseSet() API. + * + *@pre NvDdkFuseOpen should have been called before using this API + * + * @pre Prior to invoking this routine, the caller is responsible for supplying + * valid fuse programming voltage. + * + * @retval NvError_AccessDenied If programming to fuse registers is disabled. + * @return An error if an invalid combination of fuse values was provided. + */ +NvError NvDdkFuseProgram(void); + +/** + * Verify all fuses scheduled via the NvDdkFuseSet() API. + * + *@pre NvDdkFuseOpen should have been called before using this API + * + * @pre Prior to invoking this routine, the caller is responsible for ensuring + * that fuse programming voltage is removed and subsequently calling + * NvDdkFuseSense(). + */ +NvError NvDdkFuseVerify(void); + +/** + * Clears the cache of fuse data, once NvDdkFuseProgram() and NvDdkFuseVerify() + * API are called to clear all buffers. + * + *@pre NvDdkFuseOpen should have been called before using this API + */ +void NvDdkFuseClear(void); + + +/** + * Disables further fuse programming until the next system reset. + * + *@pre NvDdkFuseOpen should have been called before using this API + */ +void NvDdkDisableFuseProgram(void); + + +#if defined(__cplusplus) +} +#endif + +/** @} */ +#endif // INCLUDED_NVDDK_FUSE_H + |