aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-04-15 00:16:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-16 15:59:57 -0400
commit57aab75a39089744aba4bd126df2de526481b128 (patch)
tree34c7a4a3a29aea852e7886e68fc8778390f809e7
parentb454048cb933eb69dd9d46c16bf01e9df997fa3d (diff)
iwlwifi: generalize iwlwifi init flow
This patch creates handlers to support iwlwifi init flow for multiple HWs Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c149
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c179
3 files changed, 174 insertions, 165 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 472ca3d7e03..822169e61e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -114,6 +114,151 @@ static const u16 default_tid_to_tx_fifo[] = {
114 114
115#endif /*CONFIG_IWL4965_HT */ 115#endif /*CONFIG_IWL4965_HT */
116 116
117/* check contents of special bootstrap uCode SRAM */
118static int iwl4965_verify_bsm(struct iwl_priv *priv)
119{
120 __le32 *image = priv->ucode_boot.v_addr;
121 u32 len = priv->ucode_boot.len;
122 u32 reg;
123 u32 val;
124
125 IWL_DEBUG_INFO("Begin verify bsm\n");
126
127 /* verify BSM SRAM contents */
128 val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
129 for (reg = BSM_SRAM_LOWER_BOUND;
130 reg < BSM_SRAM_LOWER_BOUND + len;
131 reg += sizeof(u32), image++) {
132 val = iwl_read_prph(priv, reg);
133 if (val != le32_to_cpu(*image)) {
134 IWL_ERROR("BSM uCode verification failed at "
135 "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
136 BSM_SRAM_LOWER_BOUND,
137 reg - BSM_SRAM_LOWER_BOUND, len,
138 val, le32_to_cpu(*image));
139 return -EIO;
140 }
141 }
142
143 IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
144
145 return 0;
146}
147
148/**
149 * iwl4965_load_bsm - Load bootstrap instructions
150 *
151 * BSM operation:
152 *
153 * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
154 * in special SRAM that does not power down during RFKILL. When powering back
155 * up after power-saving sleeps (or during initial uCode load), the BSM loads
156 * the bootstrap program into the on-board processor, and starts it.
157 *
158 * The bootstrap program loads (via DMA) instructions and data for a new
159 * program from host DRAM locations indicated by the host driver in the
160 * BSM_DRAM_* registers. Once the new program is loaded, it starts
161 * automatically.
162 *
163 * When initializing the NIC, the host driver points the BSM to the
164 * "initialize" uCode image. This uCode sets up some internal data, then
165 * notifies host via "initialize alive" that it is complete.
166 *
167 * The host then replaces the BSM_DRAM_* pointer values to point to the
168 * normal runtime uCode instructions and a backup uCode data cache buffer
169 * (filled initially with starting data values for the on-board processor),
170 * then triggers the "initialize" uCode to load and launch the runtime uCode,
171 * which begins normal operation.
172 *
173 * When doing a power-save shutdown, runtime uCode saves data SRAM into
174 * the backup data cache in DRAM before SRAM is powered down.
175 *
176 * When powering back up, the BSM loads the bootstrap program. This reloads
177 * the runtime uCode instructions and the backup data cache into SRAM,
178 * and re-launches the runtime uCode from where it left off.
179 */
180static int iwl4965_load_bsm(struct iwl_priv *priv)
181{
182 __le32 *image = priv->ucode_boot.v_addr;
183 u32 len = priv->ucode_boot.len;
184 dma_addr_t pinst;
185 dma_addr_t pdata;
186 u32 inst_len;
187 u32 data_len;
188 int i;
189 u32 done;
190 u32 reg_offset;
191 int ret;
192
193 IWL_DEBUG_INFO("Begin load bsm\n");
194
195 /* make sure bootstrap program is no larger than BSM's SRAM size */
196 if (len > IWL_MAX_BSM_SIZE)
197 return -EINVAL;
198
199 /* Tell bootstrap uCode where to find the "Initialize" uCode
200 * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
201 * NOTE: iwl4965_initialize_alive_start() will replace these values,
202 * after the "initialize" uCode has run, to point to
203 * runtime/protocol instructions and backup data cache. */
204 pinst = priv->ucode_init.p_addr >> 4;
205 pdata = priv->ucode_init_data.p_addr >> 4;
206 inst_len = priv->ucode_init.len;
207 data_len = priv->ucode_init_data.len;
208
209 ret = iwl_grab_nic_access(priv);
210 if (ret)
211 return ret;
212
213 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
214 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
215 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
216 iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
217
218 /* Fill BSM memory with bootstrap instructions */
219 for (reg_offset = BSM_SRAM_LOWER_BOUND;
220 reg_offset < BSM_SRAM_LOWER_BOUND + len;
221 reg_offset += sizeof(u32), image++)
222 _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
223
224 ret = iwl4965_verify_bsm(priv);
225 if (ret) {
226 iwl_release_nic_access(priv);
227 return ret;
228 }
229
230 /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
231 iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
232 iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
233 iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
234
235 /* Load bootstrap code into instruction SRAM now,
236 * to prepare to load "initialize" uCode */
237 iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
238
239 /* Wait for load of bootstrap uCode to finish */
240 for (i = 0; i < 100; i++) {
241 done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
242 if (!(done & BSM_WR_CTRL_REG_BIT_START))
243 break;
244 udelay(10);
245 }
246 if (i < 100)
247 IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
248 else {
249 IWL_ERROR("BSM write did not complete!\n");
250 return -EIO;
251 }
252
253 /* Enable future boot loads whenever power management unit triggers it
254 * (e.g. when powering back up after power-save shutdown) */
255 iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
256
257 iwl_release_nic_access(priv);
258
259 return 0;
260}
261
117static int iwl4965_init_drv(struct iwl_priv *priv) 262static int iwl4965_init_drv(struct iwl_priv *priv)
118{ 263{
119 int ret; 264 int ret;
@@ -4789,6 +4934,10 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
4789 4934
4790static struct iwl_lib_ops iwl4965_lib = { 4935static struct iwl_lib_ops iwl4965_lib = {
4791 .init_drv = iwl4965_init_drv, 4936 .init_drv = iwl4965_init_drv,
4937 .hw_nic_init = iwl4965_hw_nic_init,
4938 .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
4939 .alive_notify = iwl4965_alive_notify,
4940 .load_ucode = iwl4965_load_bsm,
4792 .eeprom_ops = { 4941 .eeprom_ops = {
4793 .verify_signature = iwlcore_eeprom_verify_signature, 4942 .verify_signature = iwlcore_eeprom_verify_signature,
4794 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 4943 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 6d82376f43f..889fdbaeb73 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -89,9 +89,18 @@ struct iwl_hcmd_utils_ops {
89struct iwl_lib_ops { 89struct iwl_lib_ops {
90 /* iwlwifi driver (priv) init */ 90 /* iwlwifi driver (priv) init */
91 int (*init_drv)(struct iwl_priv *priv); 91 int (*init_drv)(struct iwl_priv *priv);
92 /* nic init */
93 int (*hw_nic_init)(struct iwl_priv *priv);
94 /* alive notification */
95 int (*alive_notify)(struct iwl_priv *priv);
96 /* check validity of rtc data address */
97 int (*is_valid_rtc_data_addr)(u32 addr);
98 /* 1st ucode load */
99 int (*load_ucode)(struct iwl_priv *priv);
100 /* rfkill */
101 void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
92 /* eeprom operations (as defined in iwl-eeprom.h) */ 102 /* eeprom operations (as defined in iwl-eeprom.h) */
93 struct iwl_eeprom_ops eeprom_ops; 103 struct iwl_eeprom_ops eeprom_ops;
94 void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
95}; 104};
96 105
97struct iwl_ops { 106struct iwl_ops {
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 06e44dad5f0..ecc9cba62bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4305,7 +4305,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
4305 4305
4306 base = le32_to_cpu(priv->card_alive.error_event_table_ptr); 4306 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
4307 4307
4308 if (!iwl4965_hw_valid_rtc_data_addr(base)) { 4308 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
4309 IWL_ERROR("Not valid error log pointer 0x%08X\n", base); 4309 IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
4310 return; 4310 return;
4311 } 4311 }
@@ -4400,7 +4400,7 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
4400 u32 size; /* # entries that we'll print */ 4400 u32 size; /* # entries that we'll print */
4401 4401
4402 base = le32_to_cpu(priv->card_alive.log_event_table_ptr); 4402 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
4403 if (!iwl4965_hw_valid_rtc_data_addr(base)) { 4403 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
4404 IWL_ERROR("Invalid event log pointer 0x%08X\n", base); 4404 IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
4405 return; 4405 return;
4406 } 4406 }
@@ -5175,156 +5175,6 @@ static int iwl4965_verify_ucode(struct iwl_priv *priv)
5175 return rc; 5175 return rc;
5176} 5176}
5177 5177
5178
5179/* check contents of special bootstrap uCode SRAM */
5180static int iwl4965_verify_bsm(struct iwl_priv *priv)
5181{
5182 __le32 *image = priv->ucode_boot.v_addr;
5183 u32 len = priv->ucode_boot.len;
5184 u32 reg;
5185 u32 val;
5186
5187 IWL_DEBUG_INFO("Begin verify bsm\n");
5188
5189 /* verify BSM SRAM contents */
5190 val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
5191 for (reg = BSM_SRAM_LOWER_BOUND;
5192 reg < BSM_SRAM_LOWER_BOUND + len;
5193 reg += sizeof(u32), image ++) {
5194 val = iwl_read_prph(priv, reg);
5195 if (val != le32_to_cpu(*image)) {
5196 IWL_ERROR("BSM uCode verification failed at "
5197 "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
5198 BSM_SRAM_LOWER_BOUND,
5199 reg - BSM_SRAM_LOWER_BOUND, len,
5200 val, le32_to_cpu(*image));
5201 return -EIO;
5202 }
5203 }
5204
5205 IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
5206
5207 return 0;
5208}
5209
5210/**
5211 * iwl4965_load_bsm - Load bootstrap instructions
5212 *
5213 * BSM operation:
5214 *
5215 * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
5216 * in special SRAM that does not power down during RFKILL. When powering back
5217 * up after power-saving sleeps (or during initial uCode load), the BSM loads
5218 * the bootstrap program into the on-board processor, and starts it.
5219 *
5220 * The bootstrap program loads (via DMA) instructions and data for a new
5221 * program from host DRAM locations indicated by the host driver in the
5222 * BSM_DRAM_* registers. Once the new program is loaded, it starts
5223 * automatically.
5224 *
5225 * When initializing the NIC, the host driver points the BSM to the
5226 * "initialize" uCode image. This uCode sets up some internal data, then
5227 * notifies host via "initialize alive" that it is complete.
5228 *
5229 * The host then replaces the BSM_DRAM_* pointer values to point to the
5230 * normal runtime uCode instructions and a backup uCode data cache buffer
5231 * (filled initially with starting data values for the on-board processor),
5232 * then triggers the "initialize" uCode to load and launch the runtime uCode,
5233 * which begins normal operation.
5234 *
5235 * When doing a power-save shutdown, runtime uCode saves data SRAM into
5236 * the backup data cache in DRAM before SRAM is powered down.
5237 *
5238 * When powering back up, the BSM loads the bootstrap program. This reloads
5239 * the runtime uCode instructions and the backup data cache into SRAM,
5240 * and re-launches the runtime uCode from where it left off.
5241 */
5242static int iwl4965_load_bsm(struct iwl_priv *priv)
5243{
5244 __le32 *image = priv->ucode_boot.v_addr;
5245 u32 len = priv->ucode_boot.len;
5246 dma_addr_t pinst;
5247 dma_addr_t pdata;
5248 u32 inst_len;
5249 u32 data_len;
5250 int rc;
5251 int i;
5252 u32 done;
5253 u32 reg_offset;
5254
5255 IWL_DEBUG_INFO("Begin load bsm\n");
5256
5257 /* make sure bootstrap program is no larger than BSM's SRAM size */
5258 if (len > IWL_MAX_BSM_SIZE)
5259 return -EINVAL;
5260
5261 /* Tell bootstrap uCode where to find the "Initialize" uCode
5262 * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
5263 * NOTE: iwl4965_initialize_alive_start() will replace these values,
5264 * after the "initialize" uCode has run, to point to
5265 * runtime/protocol instructions and backup data cache. */
5266 pinst = priv->ucode_init.p_addr >> 4;
5267 pdata = priv->ucode_init_data.p_addr >> 4;
5268 inst_len = priv->ucode_init.len;
5269 data_len = priv->ucode_init_data.len;
5270
5271 rc = iwl_grab_nic_access(priv);
5272 if (rc)
5273 return rc;
5274
5275 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
5276 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
5277 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
5278 iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
5279
5280 /* Fill BSM memory with bootstrap instructions */
5281 for (reg_offset = BSM_SRAM_LOWER_BOUND;
5282 reg_offset < BSM_SRAM_LOWER_BOUND + len;
5283 reg_offset += sizeof(u32), image++)
5284 _iwl_write_prph(priv, reg_offset,
5285 le32_to_cpu(*image));
5286
5287 rc = iwl4965_verify_bsm(priv);
5288 if (rc) {
5289 iwl_release_nic_access(priv);
5290 return rc;
5291 }
5292
5293 /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
5294 iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
5295 iwl_write_prph(priv, BSM_WR_MEM_DST_REG,
5296 RTC_INST_LOWER_BOUND);
5297 iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
5298
5299 /* Load bootstrap code into instruction SRAM now,
5300 * to prepare to load "initialize" uCode */
5301 iwl_write_prph(priv, BSM_WR_CTRL_REG,
5302 BSM_WR_CTRL_REG_BIT_START);
5303
5304 /* Wait for load of bootstrap uCode to finish */
5305 for (i = 0; i < 100; i++) {
5306 done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
5307 if (!(done & BSM_WR_CTRL_REG_BIT_START))
5308 break;
5309 udelay(10);
5310 }
5311 if (i < 100)
5312 IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
5313 else {
5314 IWL_ERROR("BSM write did not complete!\n");
5315 return -EIO;
5316 }
5317
5318 /* Enable future boot loads whenever power management unit triggers it
5319 * (e.g. when powering back up after power-save shutdown) */
5320 iwl_write_prph(priv, BSM_WR_CTRL_REG,
5321 BSM_WR_CTRL_REG_BIT_START_EN);
5322
5323 iwl_release_nic_access(priv);
5324
5325 return 0;
5326}
5327
5328static void iwl4965_nic_start(struct iwl_priv *priv) 5178static void iwl4965_nic_start(struct iwl_priv *priv)
5329{ 5179{
5330 /* Remove all resets to allow NIC to operate */ 5180 /* Remove all resets to allow NIC to operate */
@@ -5634,7 +5484,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv)
5634 */ 5484 */
5635static void iwl4965_alive_start(struct iwl_priv *priv) 5485static void iwl4965_alive_start(struct iwl_priv *priv)
5636{ 5486{
5637 int rc = 0; 5487 int ret = 0;
5638 5488
5639 IWL_DEBUG_INFO("Runtime Alive received.\n"); 5489 IWL_DEBUG_INFO("Runtime Alive received.\n");
5640 5490
@@ -5657,10 +5507,10 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
5657 5507
5658 iwlcore_clear_stations_table(priv); 5508 iwlcore_clear_stations_table(priv);
5659 5509
5660 rc = iwl4965_alive_notify(priv); 5510 ret = priv->cfg->ops->lib->alive_notify(priv);
5661 if (rc) { 5511 if (ret) {
5662 IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", 5512 IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
5663 rc); 5513 ret);
5664 goto restart; 5514 goto restart;
5665 } 5515 }
5666 5516
@@ -5835,7 +5685,8 @@ static void iwl4965_down(struct iwl_priv *priv)
5835 5685
5836static int __iwl4965_up(struct iwl_priv *priv) 5686static int __iwl4965_up(struct iwl_priv *priv)
5837{ 5687{
5838 int rc, i; 5688 int i;
5689 int ret;
5839 5690
5840 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { 5691 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
5841 IWL_WARNING("Exit pending; will not bring the NIC up\n"); 5692 IWL_WARNING("Exit pending; will not bring the NIC up\n");
@@ -5870,10 +5721,10 @@ static int __iwl4965_up(struct iwl_priv *priv)
5870 iwl_rfkill_set_hw_state(priv); 5721 iwl_rfkill_set_hw_state(priv);
5871 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 5722 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
5872 5723
5873 rc = iwl4965_hw_nic_init(priv); 5724 ret = priv->cfg->ops->lib->hw_nic_init(priv);
5874 if (rc) { 5725 if (ret) {
5875 IWL_ERROR("Unable to int nic\n"); 5726 IWL_ERROR("Unable to init nic\n");
5876 return rc; 5727 return ret;
5877 } 5728 }
5878 5729
5879 /* make sure rfkill handshake bits are cleared */ 5730 /* make sure rfkill handshake bits are cleared */
@@ -5906,10 +5757,10 @@ static int __iwl4965_up(struct iwl_priv *priv)
5906 /* load bootstrap state machine, 5757 /* load bootstrap state machine,
5907 * load bootstrap program into processor's memory, 5758 * load bootstrap program into processor's memory,
5908 * prepare to load the "initialize" uCode */ 5759 * prepare to load the "initialize" uCode */
5909 rc = iwl4965_load_bsm(priv); 5760 ret = priv->cfg->ops->lib->load_ucode(priv);
5910 5761
5911 if (rc) { 5762 if (ret) {
5912 IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc); 5763 IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
5913 continue; 5764 continue;
5914 } 5765 }
5915 5766