1 /******************************************************************************
5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
28 *****************************************************************************/
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/sched.h>
38 #include "iwl-5000-hw.h"
43 static int iwlagn_load_section(struct iwl_priv
*priv
, const char *name
,
44 struct fw_desc
*image
, u32 dst_addr
)
46 dma_addr_t phy_addr
= image
->p_addr
;
47 u32 byte_cnt
= image
->len
;
50 priv
->ucode_write_complete
= 0;
52 iwl_write_direct32(priv
,
53 FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL
),
54 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE
);
56 iwl_write_direct32(priv
,
57 FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL
), dst_addr
);
59 iwl_write_direct32(priv
,
60 FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL
),
61 phy_addr
& FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK
);
63 iwl_write_direct32(priv
,
64 FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL
),
65 (iwl_get_dma_hi_addr(phy_addr
)
66 << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT
) | byte_cnt
);
68 iwl_write_direct32(priv
,
69 FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL
),
70 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM
|
71 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX
|
72 FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID
);
74 iwl_write_direct32(priv
,
75 FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL
),
76 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE
|
77 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE
|
78 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD
);
80 IWL_DEBUG_INFO(priv
, "%s uCode section being loaded...\n", name
);
81 ret
= wait_event_interruptible_timeout(priv
->wait_command_queue
,
82 priv
->ucode_write_complete
, 5 * HZ
);
83 if (ret
== -ERESTARTSYS
) {
84 IWL_ERR(priv
, "Could not load the %s uCode section due "
85 "to interrupt\n", name
);
89 IWL_ERR(priv
, "Could not load the %s uCode section\n",
97 static int iwlagn_load_given_ucode(struct iwl_priv
*priv
,
98 struct fw_desc
*inst_image
,
99 struct fw_desc
*data_image
)
103 ret
= iwlagn_load_section(priv
, "INST", inst_image
,
104 IWL50_RTC_INST_LOWER_BOUND
);
108 return iwlagn_load_section(priv
, "DATA", data_image
,
109 IWL50_RTC_DATA_LOWER_BOUND
);
112 int iwlagn_load_ucode(struct iwl_priv
*priv
)
116 /* check whether init ucode should be loaded, or rather runtime ucode */
117 if (priv
->ucode_init
.len
&& (priv
->ucode_type
== UCODE_NONE
)) {
118 IWL_DEBUG_INFO(priv
, "Init ucode found. Loading init ucode...\n");
119 ret
= iwlagn_load_given_ucode(priv
,
120 &priv
->ucode_init
, &priv
->ucode_init_data
);
122 IWL_DEBUG_INFO(priv
, "Init ucode load complete.\n");
123 priv
->ucode_type
= UCODE_INIT
;
126 IWL_DEBUG_INFO(priv
, "Init ucode not found, or already loaded. "
127 "Loading runtime ucode...\n");
128 ret
= iwlagn_load_given_ucode(priv
,
129 &priv
->ucode_code
, &priv
->ucode_data
);
131 IWL_DEBUG_INFO(priv
, "Runtime ucode load complete.\n");
132 priv
->ucode_type
= UCODE_RT
;
139 #define IWL_UCODE_GET(item) \
140 static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\
144 return le32_to_cpu(ucode->u.v1.item); \
145 return le32_to_cpu(ucode->u.v2.item); \
148 static u32
iwlagn_ucode_get_header_size(u32 api_ver
)
151 return UCODE_HEADER_SIZE(1);
152 return UCODE_HEADER_SIZE(2);
155 static u32
iwlagn_ucode_get_build(const struct iwl_ucode_header
*ucode
,
160 return le32_to_cpu(ucode
->u
.v2
.build
);
163 static u8
*iwlagn_ucode_get_data(const struct iwl_ucode_header
*ucode
,
167 return (u8
*) ucode
->u
.v1
.data
;
168 return (u8
*) ucode
->u
.v2
.data
;
171 IWL_UCODE_GET(inst_size
);
172 IWL_UCODE_GET(data_size
);
173 IWL_UCODE_GET(init_size
);
174 IWL_UCODE_GET(init_data_size
);
175 IWL_UCODE_GET(boot_size
);
177 struct iwl_ucode_ops iwlagn_ucode
= {
178 .get_header_size
= iwlagn_ucode_get_header_size
,
179 .get_build
= iwlagn_ucode_get_build
,
180 .get_inst_size
= iwlagn_ucode_get_inst_size
,
181 .get_data_size
= iwlagn_ucode_get_data_size
,
182 .get_init_size
= iwlagn_ucode_get_init_size
,
183 .get_init_data_size
= iwlagn_ucode_get_init_data_size
,
184 .get_boot_size
= iwlagn_ucode_get_boot_size
,
185 .get_data
= iwlagn_ucode_get_data
,