aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-eeprom.c
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2009-08-13 16:30:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:33:11 -0400
commit415e49936b4b29b34c2fb561eeab867d41fc43a6 (patch)
tree2cf697d948c5eb0256b29d3c60a45f7c00ab1337 /drivers/net/wireless/iwlwifi/iwl-eeprom.c
parent3b24716fc978db9c27c4a069e5201460479340a4 (diff)
iwlwifi: traverse linklist to find the valid OTP block
For devices using OTP memory, EEPROM image can start from any one of the OTP blocks. If shadow RAM is disabled, we need to traverse link list to find the last valid block, then start the EEPROM image reading. If OTP is not full, the valid block is the block _before_ the last block on the link list; the last block on the link list is the empty block ready for next OTP refresh/update. If OTP is full, then the last block is the valid block to be used for configure the device. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-eeprom.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c185
1 files changed, 150 insertions, 35 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index ded63320a463..01b95e89009a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
152} 152}
153EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); 153EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
154 154
155static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
156{
157 u32 otpgp;
158
159 otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
160 if (mode == IWL_OTP_ACCESS_ABSOLUTE)
161 iwl_clear_bit(priv, CSR_OTP_GP_REG,
162 CSR_OTP_GP_REG_OTP_ACCESS_MODE);
163 else
164 iwl_set_bit(priv, CSR_OTP_GP_REG,
165 CSR_OTP_GP_REG_OTP_ACCESS_MODE);
166}
167
155static int iwlcore_get_nvm_type(struct iwl_priv *priv) 168static int iwlcore_get_nvm_type(struct iwl_priv *priv)
156{ 169{
157 u32 otpgp; 170 u32 otpgp;
@@ -252,6 +265,124 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
252 return ret; 265 return ret;
253} 266}
254 267
268static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
269{
270 int ret = 0;
271 u32 r;
272 u32 otpgp;
273
274 _iwl_write32(priv, CSR_EEPROM_REG,
275 CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
276 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
277 CSR_EEPROM_REG_READ_VALID_MSK,
278 IWL_EEPROM_ACCESS_TIMEOUT);
279 if (ret < 0) {
280 IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
281 return ret;
282 }
283 r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
284 /* check for ECC errors: */
285 otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
286 if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
287 /* stop in this case */
288 /* set the uncorrectable OTP ECC bit for acknowledgement */
289 iwl_set_bit(priv, CSR_OTP_GP_REG,
290 CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
291 IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
292 return -EINVAL;
293 }
294 if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
295 /* continue in this case */
296 /* set the correctable OTP ECC bit for acknowledgement */
297 iwl_set_bit(priv, CSR_OTP_GP_REG,
298 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
299 IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
300 }
301 *eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
302 return 0;
303}
304
305/*
306 * iwl_is_otp_empty: check for empty OTP
307 */
308static bool iwl_is_otp_empty(struct iwl_priv *priv)
309{
310 u16 next_link_addr = 0, link_value;
311 bool is_empty = false;
312
313 /* locate the beginning of OTP link list */
314 if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) {
315 if (!link_value) {
316 IWL_ERR(priv, "OTP is empty\n");
317 is_empty = true;
318 }
319 } else {
320 IWL_ERR(priv, "Unable to read first block of OTP list.\n");
321 is_empty = true;
322 }
323
324 return is_empty;
325}
326
327
328/*
329 * iwl_find_otp_image: find EEPROM image in OTP
330 * finding the OTP block that contains the EEPROM image.
331 * the last valid block on the link list (the block _before_ the last block)
332 * is the block we should read and used to configure the device.
333 * If all the available OTP blocks are full, the last block will be the block
334 * we should read and used to configure the device.
335 * only perform this operation if shadow RAM is disabled
336 */
337static int iwl_find_otp_image(struct iwl_priv *priv,
338 u16 *validblockaddr)
339{
340 u16 next_link_addr = 0, link_value = 0, valid_addr;
341 int ret = 0;
342 int usedblocks = 0;
343
344 /* set addressing mode to absolute to traverse the link list */
345 iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE);
346
347 /* checking for empty OTP or error */
348 if (iwl_is_otp_empty(priv))
349 return -EINVAL;
350
351 /*
352 * start traverse link list
353 * until reach the max number of OTP blocks
354 * different devices have different number of OTP blocks
355 */
356 do {
357 /* save current valid block address
358 * check for more block on the link list
359 */
360 valid_addr = next_link_addr;
361 next_link_addr = link_value;
362 IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
363 usedblocks, next_link_addr);
364 if (iwl_read_otp_word(priv, next_link_addr, &link_value))
365 return -EINVAL;
366 if (!link_value) {
367 /*
368 * reach the end of link list,
369 * set address point to the starting address
370 * of the image
371 */
372 goto done;
373 }
374 /* more in the link list, continue */
375 usedblocks++;
376 } while (usedblocks < priv->cfg->max_ll_items);
377 /* OTP full, use last block */
378 IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
379done:
380 *validblockaddr = valid_addr;
381 /* skip first 2 bytes (link list pointer) */
382 *validblockaddr += 2;
383 return ret;
384}
385
255/** 386/**
256 * iwl_eeprom_init - read EEPROM contents 387 * iwl_eeprom_init - read EEPROM contents
257 * 388 *
@@ -266,15 +397,14 @@ int iwl_eeprom_init(struct iwl_priv *priv)
266 int sz; 397 int sz;
267 int ret; 398 int ret;
268 u16 addr; 399 u16 addr;
269 u32 otpgp; 400 u16 validblockaddr = 0;
401 u16 cache_addr = 0;
270 402
271 priv->nvm_device_type = iwlcore_get_nvm_type(priv); 403 priv->nvm_device_type = iwlcore_get_nvm_type(priv);
272 if (priv->nvm_device_type == -ENOENT) 404 if (priv->nvm_device_type == -ENOENT)
273 return -ENOENT; 405 return -ENOENT;
274 /* allocate eeprom */ 406 /* allocate eeprom */
275 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) 407 IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
276 priv->cfg->eeprom_size =
277 OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
278 sz = priv->cfg->eeprom_size; 408 sz = priv->cfg->eeprom_size;
279 priv->eeprom = kzalloc(sz, GFP_KERNEL); 409 priv->eeprom = kzalloc(sz, GFP_KERNEL);
280 if (!priv->eeprom) { 410 if (!priv->eeprom) {
@@ -302,46 +432,31 @@ int iwl_eeprom_init(struct iwl_priv *priv)
302 if (ret) { 432 if (ret) {
303 IWL_ERR(priv, "Failed to initialize OTP access.\n"); 433 IWL_ERR(priv, "Failed to initialize OTP access.\n");
304 ret = -ENOENT; 434 ret = -ENOENT;
305 goto err; 435 goto done;
306 } 436 }
307 _iwl_write32(priv, CSR_EEPROM_GP, 437 _iwl_write32(priv, CSR_EEPROM_GP,
308 iwl_read32(priv, CSR_EEPROM_GP) & 438 iwl_read32(priv, CSR_EEPROM_GP) &
309 ~CSR_EEPROM_GP_IF_OWNER_MSK); 439 ~CSR_EEPROM_GP_IF_OWNER_MSK);
310 /* clear */ 440
311 _iwl_write32(priv, CSR_OTP_GP_REG, 441 iwl_set_bit(priv, CSR_OTP_GP_REG,
312 iwl_read32(priv, CSR_OTP_GP_REG) |
313 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | 442 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
314 CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); 443 CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
315 444 /* traversing the linked list if no shadow ram supported */
316 for (addr = 0; addr < sz; addr += sizeof(u16)) { 445 if (!priv->cfg->shadow_ram_support) {
317 u32 r; 446 if (iwl_find_otp_image(priv, &validblockaddr)) {
318 447 ret = -ENOENT;
319 _iwl_write32(priv, CSR_EEPROM_REG,
320 CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
321
322 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
323 CSR_EEPROM_REG_READ_VALID_MSK,
324 IWL_EEPROM_ACCESS_TIMEOUT);
325 if (ret < 0) {
326 IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
327 goto done; 448 goto done;
328 } 449 }
329 r = _iwl_read_direct32(priv, CSR_EEPROM_REG); 450 }
330 /* check for ECC errors: */ 451 for (addr = validblockaddr; addr < validblockaddr + sz;
331 otpgp = iwl_read32(priv, CSR_OTP_GP_REG); 452 addr += sizeof(u16)) {
332 if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { 453 u16 eeprom_data;
333 /* stop in this case */ 454
334 IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n"); 455 ret = iwl_read_otp_word(priv, addr, &eeprom_data);
456 if (ret)
335 goto done; 457 goto done;
336 } 458 e[cache_addr / 2] = eeprom_data;
337 if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { 459 cache_addr += sizeof(u16);
338 /* continue in this case */
339 _iwl_write32(priv, CSR_OTP_GP_REG,
340 iwl_read32(priv, CSR_OTP_GP_REG) |
341 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
342 IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
343 }
344 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
345 } 460 }
346 } else { 461 } else {
347 /* eeprom is an array of 16bit values */ 462 /* eeprom is an array of 16bit values */