aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/spectrum_cs.c
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@gmail.com>2008-08-21 18:27:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 19:28:05 -0400
commit3994d502017a2239e30152d1231843ad05d04a7b (patch)
treec4f15d1b95783d035d954173167ff08e65665461 /drivers/net/wireless/spectrum_cs.c
parent8f5ae73c5366128d3800cf9765507422bcf1ef96 (diff)
orinoco: Invoke firmware download in main driver
Firmware download is enabled for Agere in orinoco_cs. Symbol firmware download has been moved out of spectrum_cs into orinoco_cs. Firmware download is not enabled for Intersil. Symbol based firmware is restricted to only download on spectrum_cs based cards. The firmware names are hardcoded for each firmware type. Signed-off-by: David Kilroy <kilroyd@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r--drivers/net/wireless/spectrum_cs.c159
1 files changed, 14 insertions, 145 deletions
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 2fb00183cd71..e368759d1d89 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -25,7 +25,6 @@
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/firmware.h>
29#include <pcmcia/cs_types.h> 28#include <pcmcia/cs_types.h>
30#include <pcmcia/cs.h> 29#include <pcmcia/cs.h>
31#include <pcmcia/cistpl.h> 30#include <pcmcia/cistpl.h>
@@ -33,10 +32,6 @@
33#include <pcmcia/ds.h> 32#include <pcmcia/ds.h>
34 33
35#include "orinoco.h" 34#include "orinoco.h"
36#include "hermes_dld.h"
37
38static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
39static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
40 35
41/********************************************************************/ 36/********************************************************************/
42/* Module stuff */ 37/* Module stuff */
@@ -72,26 +67,11 @@ struct orinoco_pccard {
72static int spectrum_cs_config(struct pcmcia_device *link); 67static int spectrum_cs_config(struct pcmcia_device *link);
73static void spectrum_cs_release(struct pcmcia_device *link); 68static void spectrum_cs_release(struct pcmcia_device *link);
74 69
75/********************************************************************/
76/* Firmware downloader */
77/********************************************************************/
78
79/* Position of PDA in the adapter memory */
80#define EEPROM_ADDR 0x3000
81#define EEPROM_LEN 0x200
82#define PDA_OFFSET 0x100
83
84#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
85#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
86
87/* Constants for the CISREG_CCSR register */ 70/* Constants for the CISREG_CCSR register */
88#define HCR_RUN 0x07 /* run firmware after reset */ 71#define HCR_RUN 0x07 /* run firmware after reset */
89#define HCR_IDLE 0x0E /* don't run firmware after reset */ 72#define HCR_IDLE 0x0E /* don't run firmware after reset */
90#define HCR_MEM16 0x10 /* memory width bit, should be preserved */ 73#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
91 74
92/* End markers */
93#define TEXT_END 0x1A /* End of text header */
94
95 75
96#define CS_CHECK(fn, ret) \ 76#define CS_CHECK(fn, ret) \
97 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 77 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
@@ -158,142 +138,29 @@ spectrum_reset(struct pcmcia_device *link, int idle)
158 return -ENODEV; 138 return -ENODEV;
159} 139}
160 140
141/********************************************************************/
142/* Device methods */
143/********************************************************************/
161 144
162/*
163 * Process a firmware image - stop the card, load the firmware, reset
164 * the card and make sure it responds. For the secondary firmware take
165 * care of the PDA - read it and then write it on top of the firmware.
166 */
167static int 145static int
168spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, 146spectrum_cs_hard_reset(struct orinoco_private *priv)
169 const unsigned char *image, const unsigned char *end,
170 int secondary)
171{ 147{
172 int ret; 148 struct orinoco_pccard *card = priv->card;
173 const unsigned char *ptr; 149 struct pcmcia_device *link = card->p_dev;
174 const unsigned char *first_block;
175
176 /* Plug Data Area (PDA) */
177 __le16 pda[PDA_WORDS];
178
179 /* Binary block begins after the 0x1A marker */
180 ptr = image;
181 while (*ptr++ != TEXT_END);
182 first_block = ptr;
183
184 /* Read the PDA from EEPROM */
185 if (secondary) {
186 ret = hermes_read_pda(hw, pda, PDA_ADDR, sizeof(pda), 1);
187 if (ret)
188 return ret;
189 }
190
191 /* Stop the firmware, so that it can be safely rewritten */
192 ret = spectrum_reset(link, 1);
193 if (ret)
194 return ret;
195
196 /* Program the adapter with new firmware */
197 ret = hermes_program(hw, first_block, end);
198 if (ret)
199 return ret;
200
201 /* Write the PDA to the adapter */
202 if (secondary) {
203 size_t len = hermes_blocks_length(first_block);
204 ptr = first_block + len;
205 ret = hermes_apply_pda(hw, ptr, pda);
206 if (ret)
207 return ret;
208 }
209
210 /* Run the firmware */
211 ret = spectrum_reset(link, 0);
212 if (ret)
213 return ret;
214
215 /* Reset hermes chip and make sure it responds */
216 ret = hermes_init(hw);
217
218 /* hermes_reset() should return 0 with the secondary firmware */
219 if (secondary && ret != 0)
220 return -ENODEV;
221 150
222 /* And this should work with any firmware */ 151 /* Soft reset using COR and HCR */
223 if (!hermes_present(hw)) 152 spectrum_reset(link, 0);
224 return -ENODEV;
225 153
226 return 0; 154 return 0;
227} 155}
228 156
229
230/*
231 * Download the firmware into the card, this also does a PCMCIA soft
232 * reset on the card, to make sure it's in a sane state.
233 */
234static int 157static int
235spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) 158spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
236{
237 int ret;
238 const struct firmware *fw_entry;
239
240 if (request_firmware(&fw_entry, primary_fw_name,
241 &handle_to_dev(link)) != 0) {
242 printk(KERN_ERR PFX "Cannot find firmware: %s\n",
243 primary_fw_name);
244 return -ENOENT;
245 }
246
247 /* Load primary firmware */
248 ret = spectrum_dl_image(hw, link, fw_entry->data,
249 fw_entry->data + fw_entry->size, 0);
250 release_firmware(fw_entry);
251 if (ret) {
252 printk(KERN_ERR PFX "Primary firmware download failed\n");
253 return ret;
254 }
255
256 if (request_firmware(&fw_entry, secondary_fw_name,
257 &handle_to_dev(link)) != 0) {
258 printk(KERN_ERR PFX "Cannot find firmware: %s\n",
259 secondary_fw_name);
260 return -ENOENT;
261 }
262
263 /* Load secondary firmware */
264 ret = spectrum_dl_image(hw, link, fw_entry->data,
265 fw_entry->data + fw_entry->size, 1);
266 release_firmware(fw_entry);
267 if (ret) {
268 printk(KERN_ERR PFX "Secondary firmware download failed\n");
269 }
270
271 return ret;
272}
273
274/********************************************************************/
275/* Device methods */
276/********************************************************************/
277
278static int
279spectrum_cs_hard_reset(struct orinoco_private *priv)
280{ 159{
281 struct orinoco_pccard *card = priv->card; 160 struct orinoco_pccard *card = priv->card;
282 struct pcmcia_device *link = card->p_dev; 161 struct pcmcia_device *link = card->p_dev;
283 int err;
284 162
285 if (!hermes_present(&priv->hw)) { 163 return spectrum_reset(link, idle);
286 /* The firmware needs to be reloaded */
287 if (spectrum_dl_firmware(&priv->hw, link) != 0) {
288 printk(KERN_ERR PFX "Firmware download failed\n");
289 err = -ENODEV;
290 }
291 } else {
292 /* Soft reset using COR and HCR */
293 spectrum_reset(link, 0);
294 }
295
296 return 0;
297} 164}
298 165
299/********************************************************************/ 166/********************************************************************/
@@ -315,7 +182,9 @@ spectrum_cs_probe(struct pcmcia_device *link)
315 struct orinoco_private *priv; 182 struct orinoco_private *priv;
316 struct orinoco_pccard *card; 183 struct orinoco_pccard *card;
317 184
318 dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); 185 dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
186 spectrum_cs_hard_reset,
187 spectrum_cs_stop_firmware);
319 if (! dev) 188 if (! dev)
320 return -ENOMEM; 189 return -ENOMEM;
321 priv = netdev_priv(dev); 190 priv = netdev_priv(dev);
@@ -517,7 +386,7 @@ spectrum_cs_config(struct pcmcia_device *link)
517 dev->irq = link->irq.AssignedIRQ; 386 dev->irq = link->irq.AssignedIRQ;
518 card->node.major = card->node.minor = 0; 387 card->node.major = card->node.minor = 0;
519 388
520 /* Reset card and download firmware */ 389 /* Reset card */
521 if (spectrum_cs_hard_reset(priv) != 0) { 390 if (spectrum_cs_hard_reset(priv) != 0) {
522 goto failed; 391 goto failed;
523 } 392 }