diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-csr.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debug.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-eeprom.c | 147 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 |
7 files changed, 161 insertions, 27 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index eb89752aff73..fd3673448d7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2298,8 +2298,10 @@ static ssize_t show_version(struct device *d, | |||
2298 | 2298 | ||
2299 | if (priv->eeprom) { | 2299 | if (priv->eeprom) { |
2300 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 2300 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); |
2301 | pos += sprintf(buf + pos, "EEPROM version: 0x%x\n", | 2301 | pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n", |
2302 | eeprom_ver); | 2302 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
2303 | ? "OTP" : "EEPROM", eeprom_ver); | ||
2304 | |||
2303 | } else { | 2305 | } else { |
2304 | pos += sprintf(buf + pos, "EEPROM not initialzed\n"); | 2306 | pos += sprintf(buf + pos, "EEPROM not initialzed\n"); |
2305 | } | 2307 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 6e983149b83b..3d50ef99f88d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -89,6 +89,7 @@ | |||
89 | /* EEPROM reads */ | 89 | /* EEPROM reads */ |
90 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) | 90 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) |
91 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | 91 | #define CSR_EEPROM_GP (CSR_BASE+0x030) |
92 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) | ||
92 | #define CSR_GIO_REG (CSR_BASE+0x03C) | 93 | #define CSR_GIO_REG (CSR_BASE+0x03C) |
93 | #define CSR_GP_UCODE (CSR_BASE+0x044) | 94 | #define CSR_GP_UCODE (CSR_BASE+0x044) |
94 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | 95 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) |
@@ -226,6 +227,10 @@ | |||
226 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) | 227 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) |
227 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) | 228 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) |
228 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | 229 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) |
230 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ | ||
231 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ | ||
232 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ | ||
233 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ | ||
229 | 234 | ||
230 | /* CSR GIO */ | 235 | /* CSR GIO */ |
231 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) | 236 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index db069801bc41..2cf014f523be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -68,7 +68,7 @@ struct iwl_debugfs { | |||
68 | struct dentry *dir_rf; | 68 | struct dentry *dir_rf; |
69 | struct dir_data_files { | 69 | struct dir_data_files { |
70 | struct dentry *file_sram; | 70 | struct dentry *file_sram; |
71 | struct dentry *file_eeprom; | 71 | struct dentry *file_nvm; |
72 | struct dentry *file_stations; | 72 | struct dentry *file_stations; |
73 | struct dentry *file_rx_statistics; | 73 | struct dentry *file_rx_statistics; |
74 | struct dentry *file_tx_statistics; | 74 | struct dentry *file_tx_statistics; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ffc4be3842b2..713f9edd055d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -292,7 +292,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
292 | return ret; | 292 | return ret; |
293 | } | 293 | } |
294 | 294 | ||
295 | static ssize_t iwl_dbgfs_eeprom_read(struct file *file, | 295 | static ssize_t iwl_dbgfs_nvm_read(struct file *file, |
296 | char __user *user_buf, | 296 | char __user *user_buf, |
297 | size_t count, | 297 | size_t count, |
298 | loff_t *ppos) | 298 | loff_t *ppos) |
@@ -306,7 +306,7 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, | |||
306 | buf_size = 4 * eeprom_len + 256; | 306 | buf_size = 4 * eeprom_len + 256; |
307 | 307 | ||
308 | if (eeprom_len % 16) { | 308 | if (eeprom_len % 16) { |
309 | IWL_ERR(priv, "EEPROM size is not multiple of 16.\n"); | 309 | IWL_ERR(priv, "NVM size is not multiple of 16.\n"); |
310 | return -ENODATA; | 310 | return -ENODATA; |
311 | } | 311 | } |
312 | 312 | ||
@@ -318,6 +318,13 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, | |||
318 | } | 318 | } |
319 | 319 | ||
320 | ptr = priv->eeprom; | 320 | ptr = priv->eeprom; |
321 | if (!ptr) { | ||
322 | IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); | ||
323 | return -ENOMEM; | ||
324 | } | ||
325 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n", | ||
326 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
327 | ? "OTP" : "EEPROM"); | ||
321 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 328 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
322 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 329 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
323 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 330 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -419,7 +426,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
419 | channels[i].flags & | 426 | channels[i].flags & |
420 | IEEE80211_CHAN_PASSIVE_SCAN ? | 427 | IEEE80211_CHAN_PASSIVE_SCAN ? |
421 | "passive only" : "active/passive"); | 428 | "passive only" : "active/passive"); |
422 | |||
423 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 429 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
424 | kfree(buf); | 430 | kfree(buf); |
425 | return ret; | 431 | return ret; |
@@ -564,7 +570,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | |||
564 | 570 | ||
565 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 571 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
566 | DEBUGFS_WRITE_FILE_OPS(log_event); | 572 | DEBUGFS_WRITE_FILE_OPS(log_event); |
567 | DEBUGFS_READ_FILE_OPS(eeprom); | 573 | DEBUGFS_READ_FILE_OPS(nvm); |
568 | DEBUGFS_READ_FILE_OPS(stations); | 574 | DEBUGFS_READ_FILE_OPS(stations); |
569 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 575 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
570 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 576 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
@@ -598,7 +604,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
598 | 604 | ||
599 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); | 605 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); |
600 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); | 606 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); |
601 | DEBUGFS_ADD_FILE(eeprom, data); | 607 | DEBUGFS_ADD_FILE(nvm, data); |
602 | DEBUGFS_ADD_FILE(sram, data); | 608 | DEBUGFS_ADD_FILE(sram, data); |
603 | DEBUGFS_ADD_FILE(log_event, data); | 609 | DEBUGFS_ADD_FILE(log_event, data); |
604 | DEBUGFS_ADD_FILE(stations, data); | 610 | DEBUGFS_ADD_FILE(stations, data); |
@@ -629,7 +635,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
629 | if (!priv->dbgfs) | 635 | if (!priv->dbgfs) |
630 | return; | 636 | return; |
631 | 637 | ||
632 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom); | 638 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); |
633 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); | 639 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); |
634 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); | 640 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); |
635 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); | 641 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b6b8327a99fe..8282def00832 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -814,6 +814,11 @@ enum { | |||
814 | MEASUREMENT_ACTIVE = (1 << 1), | 814 | MEASUREMENT_ACTIVE = (1 << 1), |
815 | }; | 815 | }; |
816 | 816 | ||
817 | enum iwl_nvm_type { | ||
818 | NVM_DEVICE_TYPE_EEPROM = 0, | ||
819 | NVM_DEVICE_TYPE_OTP, | ||
820 | }; | ||
821 | |||
817 | /* interrupt statistics */ | 822 | /* interrupt statistics */ |
818 | struct isr_statistics { | 823 | struct isr_statistics { |
819 | u32 hw; | 824 | u32 hw; |
@@ -1024,6 +1029,7 @@ struct iwl_priv { | |||
1024 | 1029 | ||
1025 | /* eeprom */ | 1030 | /* eeprom */ |
1026 | u8 *eeprom; | 1031 | u8 *eeprom; |
1032 | int nvm_device_type; | ||
1027 | struct iwl_eeprom_calib_info *calib_info; | 1033 | struct iwl_eeprom_calib_info *calib_info; |
1028 | 1034 | ||
1029 | enum nl80211_iftype iw_mode; | 1035 | enum nl80211_iftype iw_mode; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index b400bd510fc5..9cc063b8b2d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -152,6 +152,32 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) | |||
152 | } | 152 | } |
153 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); | 153 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); |
154 | 154 | ||
155 | static int iwlcore_get_nvm_type(struct iwl_priv *priv) | ||
156 | { | ||
157 | u32 otpgp; | ||
158 | int nvm_type; | ||
159 | |||
160 | /* OTP only valid for CP/PP and after */ | ||
161 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
162 | case CSR_HW_REV_TYPE_3945: | ||
163 | case CSR_HW_REV_TYPE_4965: | ||
164 | case CSR_HW_REV_TYPE_5300: | ||
165 | case CSR_HW_REV_TYPE_5350: | ||
166 | case CSR_HW_REV_TYPE_5100: | ||
167 | case CSR_HW_REV_TYPE_5150: | ||
168 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
169 | break; | ||
170 | default: | ||
171 | otpgp = iwl_read32(priv, CSR_OTP_GP_REG); | ||
172 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
173 | nvm_type = NVM_DEVICE_TYPE_OTP; | ||
174 | else | ||
175 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
176 | break; | ||
177 | } | ||
178 | return nvm_type; | ||
179 | } | ||
180 | |||
155 | /* | 181 | /* |
156 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | 182 | * The device's EEPROM semaphore prevents conflicts between driver and uCode |
157 | * when accessing the EEPROM; each access is a series of pulses to/from the | 183 | * when accessing the EEPROM; each access is a series of pulses to/from the |
@@ -198,6 +224,35 @@ const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | |||
198 | } | 224 | } |
199 | EXPORT_SYMBOL(iwlcore_eeprom_query_addr); | 225 | EXPORT_SYMBOL(iwlcore_eeprom_query_addr); |
200 | 226 | ||
227 | static int iwl_init_otp_access(struct iwl_priv *priv) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | /* Enable 40MHz radio clock */ | ||
232 | _iwl_write32(priv, CSR_GP_CNTRL, | ||
233 | _iwl_read32(priv, CSR_GP_CNTRL) | | ||
234 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
235 | |||
236 | /* wait for clock to be ready */ | ||
237 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
238 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
239 | 25000); | ||
240 | if (ret < 0) | ||
241 | IWL_ERR(priv, "Time out access OTP\n"); | ||
242 | else { | ||
243 | ret = iwl_grab_nic_access(priv); | ||
244 | if (!ret) { | ||
245 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, | ||
246 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
247 | udelay(5); | ||
248 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, | ||
249 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
250 | iwl_release_nic_access(priv); | ||
251 | } | ||
252 | } | ||
253 | return ret; | ||
254 | } | ||
255 | |||
201 | /** | 256 | /** |
202 | * iwl_eeprom_init - read EEPROM contents | 257 | * iwl_eeprom_init - read EEPROM contents |
203 | * | 258 | * |
@@ -209,11 +264,18 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
209 | { | 264 | { |
210 | u16 *e; | 265 | u16 *e; |
211 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP); | 266 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP); |
212 | int sz = priv->cfg->eeprom_size; | 267 | int sz; |
213 | int ret; | 268 | int ret; |
214 | u16 addr; | 269 | u16 addr; |
270 | u32 otpgp; | ||
271 | |||
272 | priv->nvm_device_type = iwlcore_get_nvm_type(priv); | ||
215 | 273 | ||
216 | /* allocate eeprom */ | 274 | /* allocate eeprom */ |
275 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
276 | priv->cfg->eeprom_size = | ||
277 | OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL; | ||
278 | sz = priv->cfg->eeprom_size; | ||
217 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | 279 | priv->eeprom = kzalloc(sz, GFP_KERNEL); |
218 | if (!priv->eeprom) { | 280 | if (!priv->eeprom) { |
219 | ret = -ENOMEM; | 281 | ret = -ENOMEM; |
@@ -235,30 +297,77 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
235 | ret = -ENOENT; | 297 | ret = -ENOENT; |
236 | goto err; | 298 | goto err; |
237 | } | 299 | } |
238 | 300 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | |
239 | /* eeprom is an array of 16bit values */ | 301 | ret = iwl_init_otp_access(priv); |
240 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | 302 | if (ret) { |
241 | u32 r; | 303 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); |
242 | 304 | ret = -ENOENT; | |
243 | _iwl_write32(priv, CSR_EEPROM_REG, | 305 | goto err; |
244 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 306 | } |
245 | 307 | _iwl_write32(priv, CSR_EEPROM_GP, | |
246 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | 308 | iwl_read32(priv, CSR_EEPROM_GP) & |
247 | CSR_EEPROM_REG_READ_VALID_MSK, | 309 | ~CSR_EEPROM_GP_IF_OWNER_MSK); |
248 | IWL_EEPROM_ACCESS_TIMEOUT); | 310 | /* clear */ |
249 | if (ret < 0) { | 311 | _iwl_write32(priv, CSR_OTP_GP_REG, |
250 | IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); | 312 | iwl_read32(priv, CSR_OTP_GP_REG) | |
251 | goto done; | 313 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | |
314 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
315 | |||
316 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
317 | u32 r; | ||
318 | |||
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; | ||
328 | } | ||
329 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); | ||
330 | /* check for ECC errors: */ | ||
331 | otpgp = iwl_read32(priv, CSR_OTP_GP_REG); | ||
332 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
333 | /* stop in this case */ | ||
334 | IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n"); | ||
335 | goto done; | ||
336 | } | ||
337 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
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 | } | ||
346 | } else { | ||
347 | /* eeprom is an array of 16bit values */ | ||
348 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
349 | u32 r; | ||
350 | |||
351 | _iwl_write32(priv, CSR_EEPROM_REG, | ||
352 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
353 | |||
354 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | ||
355 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
356 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
357 | if (ret < 0) { | ||
358 | IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); | ||
359 | goto done; | ||
360 | } | ||
361 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); | ||
362 | e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); | ||
252 | } | 363 | } |
253 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); | ||
254 | e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); | ||
255 | } | 364 | } |
256 | ret = 0; | 365 | ret = 0; |
257 | done: | 366 | done: |
258 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); | 367 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); |
259 | err: | 368 | err: |
260 | if (ret) | 369 | if (ret) |
261 | kfree(priv->eeprom); | 370 | iwl_eeprom_free(priv); |
262 | alloc_err: | 371 | alloc_err: |
263 | return ret; | 372 | return ret; |
264 | } | 373 | } |
@@ -301,6 +410,8 @@ EXPORT_SYMBOL(iwl_eeprom_query_addr); | |||
301 | 410 | ||
302 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | 411 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) |
303 | { | 412 | { |
413 | if (!priv->eeprom) | ||
414 | return 0; | ||
304 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | 415 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); |
305 | } | 416 | } |
306 | EXPORT_SYMBOL(iwl_eeprom_query16); | 417 | EXPORT_SYMBOL(iwl_eeprom_query16); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 3479153d96ca..195b4ef12c27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -179,6 +179,10 @@ struct iwl_eeprom_channel { | |||
179 | #define EEPROM_5050_TX_POWER_VERSION (4) | 179 | #define EEPROM_5050_TX_POWER_VERSION (4) |
180 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 180 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
181 | 181 | ||
182 | /* OTP */ | ||
183 | #define OTP_LOWER_BLOCKS_TOTAL (3) | ||
184 | #define OTP_BLOCK_SIZE (0x400) | ||
185 | |||
182 | /* 2.4 GHz */ | 186 | /* 2.4 GHz */ |
183 | extern const u8 iwl_eeprom_band_1[14]; | 187 | extern const u8 iwl_eeprom_band_1[14]; |
184 | 188 | ||