aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-5000.c
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2008-05-15 01:54:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:48:03 -0400
commitdbb983b70a4696666112591572ed49c48c58da26 (patch)
tree459da770965257429dbacfc07f230a4fbd8fc22d /drivers/net/wireless/iwlwifi/iwl-5000.c
parentb600e4e1c5cd8928fef83bb983ab76c9a6f655bc (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.c134
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 */
293static 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
346static 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
396static 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
290static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) 423static 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,