/* Block number and block width (bytes) definitions */ #define SC27XX_EFUSE_BLOCK_MAX 32 #define SC27XX_EFUSE_BLOCK_WIDTH 2
/* Timeout (ms) for the trylock of hardware spinlocks */ #define SC27XX_EFUSE_HWLOCK_TIMEOUT 5000
/* Timeout (us) of polling the status */ #define SC27XX_EFUSE_POLL_TIMEOUT 3000000 #define SC27XX_EFUSE_POLL_DELAY_US 10000
/* * Since different PMICs of SC27xx series can have different * address , we should save address in the device data structure.
*/ struct sc27xx_efuse_variant_data {
u32 module_en;
};
/* * On Spreadtrum platform, we have multi-subsystems will access the unique * efuse controller, so we need one hardware spinlock to synchronize between * the multiple subsystems.
*/ staticint sc27xx_efuse_lock(struct sc27xx_efuse *efuse)
{ int ret;
mutex_lock(&efuse->mutex);
ret = hwspin_lock_timeout_raw(efuse->hwlock,
SC27XX_EFUSE_HWLOCK_TIMEOUT); if (ret) {
dev_err(efuse->dev, "timeout to get the hwspinlock\n");
mutex_unlock(&efuse->mutex); return ret;
}
if (blk_index > SC27XX_EFUSE_BLOCK_MAX ||
bytes > SC27XX_EFUSE_BLOCK_WIDTH) return -EINVAL;
ret = sc27xx_efuse_lock(efuse); if (ret) return ret;
/* Enable the efuse controller. */
ret = regmap_update_bits(efuse->regmap, efuse->var_data->module_en,
SC27XX_EFUSE_EN, SC27XX_EFUSE_EN); if (ret) goto unlock_efuse;
/* * Before reading, we should ensure the efuse controller is in * standby state.
*/
ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_STANDBY); if (ret) goto disable_efuse;
/* Set the block address to be read. */
ret = regmap_write(efuse->regmap,
efuse->base + SC27XX_EFUSE_BLOCK_INDEX,
blk_index & SC27XX_EFUSE_BLOCK_MASK); if (ret) goto disable_efuse;
/* Start reading process from efuse memory. */
ret = regmap_update_bits(efuse->regmap,
efuse->base + SC27XX_EFUSE_MODE_CTRL,
SC27XX_EFUSE_RD_START,
SC27XX_EFUSE_RD_START); if (ret) goto disable_efuse;
/* * Polling the read done status to make sure the reading process * is completed, that means the data can be read out now.
*/
ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_RD_DONE); if (ret) goto disable_efuse;
/* Read data from efuse memory. */
ret = regmap_read(efuse->regmap, efuse->base + SC27XX_EFUSE_DATA_RD,
&buf); if (ret) goto disable_efuse;
/* Clear the read done flag. */
ret = regmap_update_bits(efuse->regmap,
efuse->base + SC27XX_EFUSE_MODE_CTRL,
SC27XX_EFUSE_CLR_RDDONE,
SC27XX_EFUSE_CLR_RDDONE);
disable_efuse: /* Disable the efuse controller after reading. */
regmap_update_bits(efuse->regmap, efuse->var_data->module_en, SC27XX_EFUSE_EN, 0);
unlock_efuse:
sc27xx_efuse_unlock(efuse);
if (!ret) {
buf >>= blk_offset;
memcpy(val, &buf, bytes);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.