diff options
author | Ron Rindjunsky <ron.rindjunsky@intel.com> | 2008-05-15 01:54:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:03 -0400 |
commit | dbb983b70a4696666112591572ed49c48c58da26 (patch) | |
tree | 459da770965257429dbacfc07f230a4fbd8fc22d /drivers/net/wireless/iwlwifi/iwl-5000.c | |
parent | b600e4e1c5cd8928fef83bb983ab76c9a6f655bc (diff) |
iwlwifi: add ucode loaders for iwl5000
This patch adds ucode initialization handler and functions to load
ucode for iwl5000 NIC.
Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-5000.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 00ad360fc5e5..b6bdffc5a424 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -287,6 +287,139 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | |||
287 | return &priv->eeprom[address]; | 287 | return &priv->eeprom[address]; |
288 | } | 288 | } |
289 | 289 | ||
290 | /* | ||
291 | * ucode | ||
292 | */ | ||
293 | static int iwl5000_load_section(struct iwl_priv *priv, | ||
294 | struct fw_desc *image, | ||
295 | u32 dst_addr) | ||
296 | { | ||
297 | int ret = 0; | ||
298 | unsigned long flags; | ||
299 | |||
300 | dma_addr_t phy_addr = image->p_addr; | ||
301 | u32 byte_cnt = image->len; | ||
302 | |||
303 | spin_lock_irqsave(&priv->lock, flags); | ||
304 | ret = iwl_grab_nic_access(priv); | ||
305 | if (ret) { | ||
306 | spin_unlock_irqrestore(&priv->lock, flags); | ||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | iwl_write_direct32(priv, | ||
311 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
312 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
313 | |||
314 | iwl_write_direct32(priv, | ||
315 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
316 | |||
317 | iwl_write_direct32(priv, | ||
318 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
319 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
320 | |||
321 | /* FIME: write the MSB of the phy_addr in CTRL1 | ||
322 | * iwl_write_direct32(priv, | ||
323 | IWL_FH_TFDIB_CTRL1_REG(IWL_FH_SRVC_CHNL), | ||
324 | ((phy_addr & MSB_MSK) | ||
325 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_count); | ||
326 | */ | ||
327 | iwl_write_direct32(priv, | ||
328 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), byte_cnt); | ||
329 | iwl_write_direct32(priv, | ||
330 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
331 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
332 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
333 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
334 | |||
335 | iwl_write_direct32(priv, | ||
336 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
337 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
338 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL | | ||
339 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
340 | |||
341 | iwl_release_nic_access(priv); | ||
342 | spin_unlock_irqrestore(&priv->lock, flags); | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int iwl5000_load_given_ucode(struct iwl_priv *priv, | ||
347 | struct fw_desc *inst_image, | ||
348 | struct fw_desc *data_image) | ||
349 | { | ||
350 | int ret = 0; | ||
351 | |||
352 | ret = iwl5000_load_section( | ||
353 | priv, inst_image, RTC_INST_LOWER_BOUND); | ||
354 | if (ret) | ||
355 | return ret; | ||
356 | |||
357 | IWL_DEBUG_INFO("INST uCode section being loaded...\n"); | ||
358 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
359 | priv->ucode_write_complete, 5 * HZ); | ||
360 | if (ret == -ERESTARTSYS) { | ||
361 | IWL_ERROR("Could not load the INST uCode section due " | ||
362 | "to interrupt\n"); | ||
363 | return ret; | ||
364 | } | ||
365 | if (!ret) { | ||
366 | IWL_ERROR("Could not load the INST uCode section\n"); | ||
367 | return -ETIMEDOUT; | ||
368 | } | ||
369 | |||
370 | priv->ucode_write_complete = 0; | ||
371 | |||
372 | ret = iwl5000_load_section( | ||
373 | priv, data_image, RTC_DATA_LOWER_BOUND); | ||
374 | if (ret) | ||
375 | return ret; | ||
376 | |||
377 | IWL_DEBUG_INFO("DATA uCode section being loaded...\n"); | ||
378 | |||
379 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
380 | priv->ucode_write_complete, 5 * HZ); | ||
381 | if (ret == -ERESTARTSYS) { | ||
382 | IWL_ERROR("Could not load the INST uCode section due " | ||
383 | "to interrupt\n"); | ||
384 | return ret; | ||
385 | } else if (!ret) { | ||
386 | IWL_ERROR("Could not load the DATA uCode section\n"); | ||
387 | return -ETIMEDOUT; | ||
388 | } else | ||
389 | ret = 0; | ||
390 | |||
391 | priv->ucode_write_complete = 0; | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | static int iwl5000_load_ucode(struct iwl_priv *priv) | ||
397 | { | ||
398 | int ret = 0; | ||
399 | |||
400 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
401 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
402 | IWL_DEBUG_INFO("Init ucode found. Loading init ucode...\n"); | ||
403 | ret = iwl5000_load_given_ucode(priv, | ||
404 | &priv->ucode_init, &priv->ucode_init_data); | ||
405 | if (!ret) { | ||
406 | IWL_DEBUG_INFO("Init ucode load complete.\n"); | ||
407 | priv->ucode_type = UCODE_INIT; | ||
408 | } | ||
409 | } else { | ||
410 | IWL_DEBUG_INFO("Init ucode not found, or already loaded. " | ||
411 | "Loading runtime ucode...\n"); | ||
412 | ret = iwl5000_load_given_ucode(priv, | ||
413 | &priv->ucode_code, &priv->ucode_data); | ||
414 | if (!ret) { | ||
415 | IWL_DEBUG_INFO("Runtime ucode load complete.\n"); | ||
416 | priv->ucode_type = UCODE_RT; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | return ret; | ||
421 | } | ||
422 | |||
290 | static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | 423 | static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
291 | { | 424 | { |
292 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || | 425 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || |
@@ -488,6 +621,7 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
488 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 621 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
489 | .disable_tx_fifo = iwl5000_disable_tx_fifo, | 622 | .disable_tx_fifo = iwl5000_disable_tx_fifo, |
490 | .rx_handler_setup = iwl5000_rx_handler_setup, | 623 | .rx_handler_setup = iwl5000_rx_handler_setup, |
624 | .load_ucode = iwl5000_load_ucode, | ||
491 | .apm_ops = { | 625 | .apm_ops = { |
492 | .init = iwl5000_apm_init, | 626 | .init = iwl5000_apm_init, |
493 | .config = iwl5000_nic_config, | 627 | .config = iwl5000_nic_config, |