* fix qemu for m68k by just using tcg-interpreter, too
[t2sde.git] / package / kernel / linux / 0000-wifi-libertas.patch
blob0a68a46b21864c8f1ffadbc40ecfd4bbecf34725
1 From 4b478bf6bdd8901cb29742ec8a65c0b2b92a9e56 Mon Sep 17 00:00:00 2001
2 From: Arnd Bergmann <arnd@arndb.de>
3 Date: Mon, 23 Oct 2023 15:19:43 +0200
4 Subject: wifi: libertas: drop 16-bit PCMCIA support
6 With all the other PCMCIA WLAN adapters gone from the kernel, this is now
7 the last remaining device with this interface, but as far as I can tell,
8 all the actual libertas users were actually using either SDIO or USB.
10 --- b/drivers/net/wireless/marvell/libertas/Kconfig
11 +++ a/drivers/net/wireless/marvell/libertas/Kconfig
12 @@ -16,6 +15,12 @@
13 help
14 A driver for Marvell Libertas 8388 USB devices.
16 +config LIBERTAS_CS
17 + tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
18 + depends on LIBERTAS && PCMCIA && HAS_IOPORT_MAP
19 + help
20 + A driver for Marvell Libertas 8385 CompactFlash devices.
22 config LIBERTAS_SDIO
23 tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
24 depends on LIBERTAS && MMC
25 --- b/drivers/net/wireless/marvell/libertas/Makefile
26 +++ a/drivers/net/wireless/marvell/libertas/Makefile
27 @@ -17,5 +17,6 @@
29 obj-$(CONFIG_LIBERTAS) += libertas.o
30 obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
31 +obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o
32 obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
33 obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
34 --- /dev/null
35 +++ a/drivers/net/wireless/marvell/libertas/if_cs.c
36 @@ -0,0 +1,957 @@
37 +// SPDX-License-Identifier: GPL-2.0-or-later
38 +/*
40 + Driver for the Marvell 8385 based compact flash WLAN cards.
42 + (C) 2007 by Holger Schurig <hs4233@mail.mn-solutions.de>
45 +*/
47 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
49 +#include <linux/module.h>
50 +#include <linux/slab.h>
51 +#include <linux/delay.h>
52 +#include <linux/moduleparam.h>
53 +#include <linux/firmware.h>
54 +#include <linux/netdevice.h>
56 +#include <pcmcia/cistpl.h>
57 +#include <pcmcia/ds.h>
59 +#include <linux/io.h>
61 +#define DRV_NAME "libertas_cs"
63 +#include "decl.h"
64 +#include "defs.h"
65 +#include "dev.h"
68 +/********************************************************************/
69 +/* Module stuff */
70 +/********************************************************************/
72 +MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
73 +MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
74 +MODULE_LICENSE("GPL");
78 +/********************************************************************/
79 +/* Data structures */
80 +/********************************************************************/
82 +struct if_cs_card {
83 + struct pcmcia_device *p_dev;
84 + struct lbs_private *priv;
85 + void __iomem *iobase;
86 + bool align_regs;
87 + u32 model;
88 +};
91 +enum {
92 + MODEL_UNKNOWN = 0x00,
93 + MODEL_8305 = 0x01,
94 + MODEL_8381 = 0x02,
95 + MODEL_8385 = 0x03
96 +};
98 +static const struct lbs_fw_table fw_table[] = {
99 + { MODEL_8305, "libertas/cf8305.bin", NULL },
100 + { MODEL_8305, "libertas_cs_helper.fw", NULL },
101 + { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" },
102 + { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" },
103 + { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" },
104 + { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" },
105 + { 0, NULL, NULL }
107 +MODULE_FIRMWARE("libertas/cf8305.bin");
108 +MODULE_FIRMWARE("libertas/cf8381_helper.bin");
109 +MODULE_FIRMWARE("libertas/cf8381.bin");
110 +MODULE_FIRMWARE("libertas/cf8385_helper.bin");
111 +MODULE_FIRMWARE("libertas/cf8385.bin");
112 +MODULE_FIRMWARE("libertas_cs_helper.fw");
113 +MODULE_FIRMWARE("libertas_cs.fw");
116 +/********************************************************************/
117 +/* Hardware access */
118 +/********************************************************************/
120 +/* This define enables wrapper functions which allow you
121 + to dump all register accesses. You normally won't this,
122 + except for development */
123 +/* #define DEBUG_IO */
125 +#ifdef DEBUG_IO
126 +static int debug_output = 0;
127 +#else
128 +/* This way the compiler optimizes the printk's away */
129 +#define debug_output 0
130 +#endif
132 +static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
134 + unsigned int val = ioread8(card->iobase + reg);
135 + if (debug_output)
136 + printk(KERN_INFO "inb %08x<%02x\n", reg, val);
137 + return val;
139 +static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
141 + unsigned int val = ioread16(card->iobase + reg);
142 + if (debug_output)
143 + printk(KERN_INFO "inw %08x<%04x\n", reg, val);
144 + return val;
146 +static inline void if_cs_read16_rep(
147 + struct if_cs_card *card,
148 + uint reg,
149 + void *buf,
150 + unsigned long count)
152 + if (debug_output)
153 + printk(KERN_INFO "insw %08x<(0x%lx words)\n",
154 + reg, count);
155 + ioread16_rep(card->iobase + reg, buf, count);
158 +static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
160 + if (debug_output)
161 + printk(KERN_INFO "outb %08x>%02x\n", reg, val);
162 + iowrite8(val, card->iobase + reg);
165 +static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
167 + if (debug_output)
168 + printk(KERN_INFO "outw %08x>%04x\n", reg, val);
169 + iowrite16(val, card->iobase + reg);
172 +static inline void if_cs_write16_rep(
173 + struct if_cs_card *card,
174 + uint reg,
175 + const void *buf,
176 + unsigned long count)
178 + if (debug_output)
179 + printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
180 + reg, count);
181 + iowrite16_rep(card->iobase + reg, buf, count);
186 + * I know that polling/delaying is frowned upon. However, this procedure
187 + * with polling is needed while downloading the firmware. At this stage,
188 + * the hardware does unfortunately not create any interrupts.
190 + * Fortunately, this function is never used once the firmware is in
191 + * the card. :-)
193 + * As a reference, see the "Firmware Specification v5.1", page 18
194 + * and 19. I did not follow their suggested timing to the word,
195 + * but this works nice & fast anyway.
196 + */
197 +static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 reg)
199 + int i;
201 + for (i = 0; i < 100000; i++) {
202 + u8 val = if_cs_read8(card, addr);
203 + if (val == reg)
204 + return 0;
205 + udelay(5);
207 + return -ETIME;
213 + * First the bitmasks for the host/card interrupt/status registers:
214 + */
215 +#define IF_CS_BIT_TX 0x0001
216 +#define IF_CS_BIT_RX 0x0002
217 +#define IF_CS_BIT_COMMAND 0x0004
218 +#define IF_CS_BIT_RESP 0x0008
219 +#define IF_CS_BIT_EVENT 0x0010
220 +#define IF_CS_BIT_MASK 0x001f
225 + * It's not really clear to me what the host status register is for. It
226 + * needs to be set almost in union with "host int cause". The following
227 + * bits from above are used:
229 + * IF_CS_BIT_TX driver downloaded a data packet
230 + * IF_CS_BIT_RX driver got a data packet
231 + * IF_CS_BIT_COMMAND driver downloaded a command
232 + * IF_CS_BIT_RESP not used (has some meaning with powerdown)
233 + * IF_CS_BIT_EVENT driver read a host event
234 + */
235 +#define IF_CS_HOST_STATUS 0x00000000
238 + * With the host int cause register can the host (that is, Linux) cause
239 + * an interrupt in the firmware, to tell the firmware about those events:
241 + * IF_CS_BIT_TX a data packet has been downloaded
242 + * IF_CS_BIT_RX a received data packet has retrieved
243 + * IF_CS_BIT_COMMAND a firmware block or a command has been downloaded
244 + * IF_CS_BIT_RESP not used (has some meaning with powerdown)
245 + * IF_CS_BIT_EVENT a host event (link lost etc) has been retrieved
246 + */
247 +#define IF_CS_HOST_INT_CAUSE 0x00000002
250 + * The host int mask register is used to enable/disable interrupt. However,
251 + * I have the suspicion that disabled interrupts are lost.
252 + */
253 +#define IF_CS_HOST_INT_MASK 0x00000004
256 + * Used to send or receive data packets:
257 + */
258 +#define IF_CS_WRITE 0x00000016
259 +#define IF_CS_WRITE_LEN 0x00000014
260 +#define IF_CS_READ 0x00000010
261 +#define IF_CS_READ_LEN 0x00000024
264 + * Used to send commands (and to send firmware block) and to
265 + * receive command responses:
266 + */
267 +#define IF_CS_CMD 0x0000001A
268 +#define IF_CS_CMD_LEN 0x00000018
269 +#define IF_CS_RESP 0x00000012
270 +#define IF_CS_RESP_LEN 0x00000030
273 + * The card status registers shows what the card/firmware actually
274 + * accepts:
276 + * IF_CS_BIT_TX you may send a data packet
277 + * IF_CS_BIT_RX you may retrieve a data packet
278 + * IF_CS_BIT_COMMAND you may send a command
279 + * IF_CS_BIT_RESP you may retrieve a command response
280 + * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc)
282 + * When reading this register several times, you will get back the same
283 + * results --- with one exception: the IF_CS_BIT_EVENT clear itself
284 + * automatically.
286 + * Not that we don't rely on BIT_RX,_BIT_RESP or BIT_EVENT because
287 + * we handle this via the card int cause register.
288 + */
289 +#define IF_CS_CARD_STATUS 0x00000020
290 +#define IF_CS_CARD_STATUS_MASK 0x7f00
293 + * The card int cause register is used by the card/firmware to notify us
294 + * about the following events:
296 + * IF_CS_BIT_TX a data packet has successfully been sentx
297 + * IF_CS_BIT_RX a data packet has been received and can be retrieved
298 + * IF_CS_BIT_COMMAND not used
299 + * IF_CS_BIT_RESP the firmware has a command response for us
300 + * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc)
301 + */
302 +#define IF_CS_CARD_INT_CAUSE 0x00000022
305 + * This is used to for handshaking with the card's bootloader/helper image
306 + * to synchronize downloading of firmware blocks.
307 + */
308 +#define IF_CS_SQ_READ_LOW 0x00000028
309 +#define IF_CS_SQ_HELPER_OK 0x10
312 + * The scratch register tells us ...
314 + * IF_CS_SCRATCH_BOOT_OK the bootloader runs
315 + * IF_CS_SCRATCH_HELPER_OK the helper firmware already runs
316 + */
317 +#define IF_CS_SCRATCH 0x0000003F
318 +#define IF_CS_SCRATCH_BOOT_OK 0x00
319 +#define IF_CS_SCRATCH_HELPER_OK 0x5a
322 + * Used to detect ancient chips:
323 + */
324 +#define IF_CS_PRODUCT_ID 0x0000001C
325 +#define IF_CS_CF8385_B1_REV 0x12
326 +#define IF_CS_CF8381_B3_REV 0x04
327 +#define IF_CS_CF8305_B1_REV 0x03
330 + * Used to detect other cards than CF8385 since their revisions of silicon
331 + * doesn't match those from CF8385, eg. CF8381 B3 works with this driver.
332 + */
333 +#define CF8305_MANFID 0x02db
334 +#define CF8305_CARDID 0x8103
335 +#define CF8381_MANFID 0x02db
336 +#define CF8381_CARDID 0x6064
337 +#define CF8385_MANFID 0x02df
338 +#define CF8385_CARDID 0x8103
341 + * FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when
342 + * that gets fixed. Currently there's no way to access it from the probe hook.
343 + */
344 +static inline u32 get_model(u16 manf_id, u16 card_id)
346 + /* NOTE: keep in sync with if_cs_ids */
347 + if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID)
348 + return MODEL_8305;
349 + else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID)
350 + return MODEL_8381;
351 + else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID)
352 + return MODEL_8385;
353 + return MODEL_UNKNOWN;
356 +/********************************************************************/
357 +/* I/O and interrupt handling */
358 +/********************************************************************/
360 +static inline void if_cs_enable_ints(struct if_cs_card *card)
362 + if_cs_write16(card, IF_CS_HOST_INT_MASK, 0);
365 +static inline void if_cs_disable_ints(struct if_cs_card *card)
367 + if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK);
371 + * Called from if_cs_host_to_card to send a command to the hardware
372 + */
373 +static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
375 + struct if_cs_card *card = (struct if_cs_card *)priv->card;
376 + int ret = -1;
377 + int loops = 0;
379 + if_cs_disable_ints(card);
381 + /* Is hardware ready? */
382 + while (1) {
383 + u16 status = if_cs_read16(card, IF_CS_CARD_STATUS);
384 + if (status & IF_CS_BIT_COMMAND)
385 + break;
386 + if (++loops > 100) {
387 + netdev_err(priv->dev, "card not ready for commands\n");
388 + goto done;
390 + mdelay(1);
393 + if_cs_write16(card, IF_CS_CMD_LEN, nb);
395 + if_cs_write16_rep(card, IF_CS_CMD, buf, nb / 2);
396 + /* Are we supposed to transfer an odd amount of bytes? */
397 + if (nb & 1)
398 + if_cs_write8(card, IF_CS_CMD, buf[nb-1]);
400 + /* "Assert the download over interrupt command in the Host
401 + * status register" */
402 + if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
404 + /* "Assert the download over interrupt command in the Card
405 + * interrupt case register" */
406 + if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
407 + ret = 0;
409 +done:
410 + if_cs_enable_ints(card);
411 + return ret;
415 + * Called from if_cs_host_to_card to send a data to the hardware
416 + */
417 +static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
419 + struct if_cs_card *card = (struct if_cs_card *)priv->card;
420 + u16 status;
422 + if_cs_disable_ints(card);
424 + status = if_cs_read16(card, IF_CS_CARD_STATUS);
425 + BUG_ON((status & IF_CS_BIT_TX) == 0);
427 + if_cs_write16(card, IF_CS_WRITE_LEN, nb);
429 + /* write even number of bytes, then odd byte if necessary */
430 + if_cs_write16_rep(card, IF_CS_WRITE, buf, nb / 2);
431 + if (nb & 1)
432 + if_cs_write8(card, IF_CS_WRITE, buf[nb-1]);
434 + if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX);
435 + if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX);
436 + if_cs_enable_ints(card);
440 + * Get the command result out of the card.
441 + */
442 +static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
444 + unsigned long flags;
445 + int ret = -1;
446 + u16 status;
448 + /* is hardware ready? */
449 + status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
450 + if ((status & IF_CS_BIT_RESP) == 0) {
451 + netdev_err(priv->dev, "no cmd response in card\n");
452 + *len = 0;
453 + goto out;
456 + *len = if_cs_read16(priv->card, IF_CS_RESP_LEN);
457 + if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) {
458 + netdev_err(priv->dev,
459 + "card cmd buffer has invalid # of bytes (%d)\n",
460 + *len);
461 + goto out;
464 + /* read even number of bytes, then odd byte if necessary */
465 + if_cs_read16_rep(priv->card, IF_CS_RESP, data, *len/sizeof(u16));
466 + if (*len & 1)
467 + data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP);
469 + /* This is a workaround for a firmware that reports too much
470 + * bytes */
471 + *len -= 8;
472 + ret = 0;
474 + /* Clear this flag again */
475 + spin_lock_irqsave(&priv->driver_lock, flags);
476 + priv->dnld_sent = DNLD_RES_RECEIVED;
477 + spin_unlock_irqrestore(&priv->driver_lock, flags);
479 +out:
480 + return ret;
483 +static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
485 + struct sk_buff *skb = NULL;
486 + u16 len;
487 + u8 *data;
489 + len = if_cs_read16(priv->card, IF_CS_READ_LEN);
490 + if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
491 + netdev_err(priv->dev,
492 + "card data buffer has invalid # of bytes (%d)\n",
493 + len);
494 + priv->dev->stats.rx_dropped++;
495 + goto dat_err;
498 + skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
499 + if (!skb)
500 + goto out;
501 + skb_put(skb, len);
502 + skb_reserve(skb, 2);/* 16 byte align */
503 + data = skb->data;
505 + /* read even number of bytes, then odd byte if necessary */
506 + if_cs_read16_rep(priv->card, IF_CS_READ, data, len/sizeof(u16));
507 + if (len & 1)
508 + data[len-1] = if_cs_read8(priv->card, IF_CS_READ);
510 +dat_err:
511 + if_cs_write16(priv->card, IF_CS_HOST_STATUS, IF_CS_BIT_RX);
512 + if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX);
514 +out:
515 + return skb;
518 +static irqreturn_t if_cs_interrupt(int irq, void *data)
520 + struct if_cs_card *card = data;
521 + struct lbs_private *priv = card->priv;
522 + u16 cause;
524 + /* Ask card interrupt cause register if there is something for us */
525 + cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE);
526 + lbs_deb_cs("cause 0x%04x\n", cause);
528 + if (cause == 0) {
529 + /* Not for us */
530 + return IRQ_NONE;
533 + if (cause == 0xffff) {
534 + /* Read in junk, the card has probably been removed */
535 + card->priv->surpriseremoved = 1;
536 + return IRQ_HANDLED;
539 + if (cause & IF_CS_BIT_RX) {
540 + struct sk_buff *skb;
541 + lbs_deb_cs("rx packet\n");
542 + skb = if_cs_receive_data(priv);
543 + if (skb)
544 + lbs_process_rxed_packet(priv, skb);
547 + if (cause & IF_CS_BIT_TX) {
548 + lbs_deb_cs("tx done\n");
549 + lbs_host_to_card_done(priv);
552 + if (cause & IF_CS_BIT_RESP) {
553 + unsigned long flags;
554 + u8 i;
556 + lbs_deb_cs("cmd resp\n");
557 + spin_lock_irqsave(&priv->driver_lock, flags);
558 + i = (priv->resp_idx == 0) ? 1 : 0;
559 + spin_unlock_irqrestore(&priv->driver_lock, flags);
561 + BUG_ON(priv->resp_len[i]);
562 + if_cs_receive_cmdres(priv, priv->resp_buf[i],
563 + &priv->resp_len[i]);
565 + spin_lock_irqsave(&priv->driver_lock, flags);
566 + lbs_notify_command_response(priv, i);
567 + spin_unlock_irqrestore(&priv->driver_lock, flags);
570 + if (cause & IF_CS_BIT_EVENT) {
571 + u16 status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
572 + if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE,
573 + IF_CS_BIT_EVENT);
574 + lbs_queue_event(priv, (status & IF_CS_CARD_STATUS_MASK) >> 8);
577 + /* Clear interrupt cause */
578 + if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK);
580 + return IRQ_HANDLED;
586 +/********************************************************************/
587 +/* Firmware */
588 +/********************************************************************/
591 + * Tries to program the helper firmware.
593 + * Return 0 on success
594 + */
595 +static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
597 + int ret = 0;
598 + int sent = 0;
599 + u8 scratch;
601 + /*
602 + * This is the only place where an unaligned register access happens on
603 + * the CF8305 card, therefore for the sake of speed of the driver, we do
604 + * the alignment correction here.
605 + */
606 + if (card->align_regs)
607 + scratch = if_cs_read16(card, IF_CS_SCRATCH) >> 8;
608 + else
609 + scratch = if_cs_read8(card, IF_CS_SCRATCH);
611 + /* "If the value is 0x5a, the firmware is already
612 + * downloaded successfully"
613 + */
614 + if (scratch == IF_CS_SCRATCH_HELPER_OK)
615 + goto done;
617 + /* "If the value is != 00, it is invalid value of register */
618 + if (scratch != IF_CS_SCRATCH_BOOT_OK) {
619 + ret = -ENODEV;
620 + goto done;
623 + lbs_deb_cs("helper size %td\n", fw->size);
625 + /* "Set the 5 bytes of the helper image to 0" */
626 + /* Not needed, this contains an ARM branch instruction */
628 + for (;;) {
629 + /* "the number of bytes to send is 256" */
630 + int count = 256;
631 + int remain = fw->size - sent;
633 + if (remain < count)
634 + count = remain;
636 + /*
637 + * "write the number of bytes to be sent to the I/O Command
638 + * write length register"
639 + */
640 + if_cs_write16(card, IF_CS_CMD_LEN, count);
642 + /* "write this to I/O Command port register as 16 bit writes */
643 + if (count)
644 + if_cs_write16_rep(card, IF_CS_CMD,
645 + &fw->data[sent],
646 + count >> 1);
648 + /*
649 + * "Assert the download over interrupt command in the Host
650 + * status register"
651 + */
652 + if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
654 + /*
655 + * "Assert the download over interrupt command in the Card
656 + * interrupt case register"
657 + */
658 + if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
660 + /*
661 + * "The host polls the Card Status register ... for 50 ms before
662 + * declaring a failure"
663 + */
664 + ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
665 + IF_CS_BIT_COMMAND);
666 + if (ret < 0) {
667 + pr_err("can't download helper at 0x%x, ret %d\n",
668 + sent, ret);
669 + goto done;
672 + if (count == 0)
673 + break;
675 + sent += count;
678 +done:
679 + return ret;
683 +static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
685 + int ret = 0;
686 + int retry = 0;
687 + int len = 0;
688 + int sent;
690 + lbs_deb_cs("fw size %td\n", fw->size);
692 + ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
693 + IF_CS_SQ_HELPER_OK);
694 + if (ret < 0) {
695 + pr_err("helper firmware doesn't answer\n");
696 + goto done;
699 + for (sent = 0; sent < fw->size; sent += len) {
700 + len = if_cs_read16(card, IF_CS_SQ_READ_LOW);
701 + if (len & 1) {
702 + retry++;
703 + pr_info("odd, need to retry this firmware block\n");
704 + } else {
705 + retry = 0;
708 + if (retry > 20) {
709 + pr_err("could not download firmware\n");
710 + ret = -ENODEV;
711 + goto done;
713 + if (retry) {
714 + sent -= len;
718 + if_cs_write16(card, IF_CS_CMD_LEN, len);
720 + if_cs_write16_rep(card, IF_CS_CMD,
721 + &fw->data[sent],
722 + (len+1) >> 1);
723 + if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
724 + if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
726 + ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
727 + IF_CS_BIT_COMMAND);
728 + if (ret < 0) {
729 + pr_err("can't download firmware at 0x%x\n", sent);
730 + goto done;
734 + ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
735 + if (ret < 0)
736 + pr_err("firmware download failed\n");
738 +done:
739 + return ret;
742 +static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
743 + const struct firmware *helper,
744 + const struct firmware *mainfw)
746 + struct if_cs_card *card = priv->card;
748 + if (ret) {
749 + pr_err("failed to find firmware (%d)\n", ret);
750 + return;
753 + /* Load the firmware */
754 + ret = if_cs_prog_helper(card, helper);
755 + if (ret == 0 && (card->model != MODEL_8305))
756 + ret = if_cs_prog_real(card, mainfw);
757 + if (ret)
758 + return;
760 + /* Now actually get the IRQ */
761 + ret = request_irq(card->p_dev->irq, if_cs_interrupt,
762 + IRQF_SHARED, DRV_NAME, card);
763 + if (ret) {
764 + pr_err("error in request_irq\n");
765 + return;
768 + /*
769 + * Clear any interrupt cause that happened while sending
770 + * firmware/initializing card
771 + */
772 + if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
773 + if_cs_enable_ints(card);
775 + /* And finally bring the card up */
776 + priv->fw_ready = 1;
777 + if (lbs_start_card(priv) != 0) {
778 + pr_err("could not activate card\n");
779 + free_irq(card->p_dev->irq, card);
784 +/********************************************************************/
785 +/* Callback functions for libertas.ko */
786 +/********************************************************************/
788 +/* Send commands or data packets to the card */
789 +static int if_cs_host_to_card(struct lbs_private *priv,
790 + u8 type,
791 + u8 *buf,
792 + u16 nb)
794 + int ret = -1;
796 + switch (type) {
797 + case MVMS_DAT:
798 + priv->dnld_sent = DNLD_DATA_SENT;
799 + if_cs_send_data(priv, buf, nb);
800 + ret = 0;
801 + break;
802 + case MVMS_CMD:
803 + priv->dnld_sent = DNLD_CMD_SENT;
804 + ret = if_cs_send_cmd(priv, buf, nb);
805 + break;
806 + default:
807 + netdev_err(priv->dev, "%s: unsupported type %d\n",
808 + __func__, type);
811 + return ret;
815 +static void if_cs_release(struct pcmcia_device *p_dev)
817 + struct if_cs_card *card = p_dev->priv;
819 + free_irq(p_dev->irq, card);
820 + pcmcia_disable_device(p_dev);
821 + if (card->iobase)
822 + ioport_unmap(card->iobase);
826 +static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
828 + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
829 + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
831 + if (p_dev->resource[1]->end) {
832 + pr_err("wrong CIS (check number of IO windows)\n");
833 + return -ENODEV;
836 + /* This reserves IO space but doesn't actually enable it */
837 + return pcmcia_request_io(p_dev);
840 +static int if_cs_probe(struct pcmcia_device *p_dev)
842 + int ret = -ENOMEM;
843 + unsigned int prod_id;
844 + struct lbs_private *priv;
845 + struct if_cs_card *card;
847 + card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL);
848 + if (!card)
849 + goto out;
851 + card->p_dev = p_dev;
852 + p_dev->priv = card;
854 + p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
856 + if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
857 + pr_err("error in pcmcia_loop_config\n");
858 + goto out1;
861 + /*
862 + * Allocate an interrupt line. Note that this does not assign
863 + * a handler to the interrupt, unless the 'Handler' member of
864 + * the irq structure is initialized.
865 + */
866 + if (!p_dev->irq)
867 + goto out1;
869 + /* Initialize io access */
870 + card->iobase = ioport_map(p_dev->resource[0]->start,
871 + resource_size(p_dev->resource[0]));
872 + if (!card->iobase) {
873 + pr_err("error in ioport_map\n");
874 + ret = -EIO;
875 + goto out1;
878 + ret = pcmcia_enable_device(p_dev);
879 + if (ret) {
880 + pr_err("error in pcmcia_enable_device\n");
881 + goto out2;
884 + /* Finally, report what we've done */
885 + lbs_deb_cs("irq %d, io %pR", p_dev->irq, p_dev->resource[0]);
887 + /*
888 + * Most of the libertas cards can do unaligned register access, but some
889 + * weird ones cannot. That's especially true for the CF8305 card.
890 + */
891 + card->align_regs = false;
893 + card->model = get_model(p_dev->manf_id, p_dev->card_id);
894 + if (card->model == MODEL_UNKNOWN) {
895 + pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n",
896 + p_dev->manf_id, p_dev->card_id);
897 + ret = -ENODEV;
898 + goto out2;
901 + /* Check if we have a current silicon */
902 + prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
903 + if (card->model == MODEL_8305) {
904 + card->align_regs = true;
905 + if (prod_id < IF_CS_CF8305_B1_REV) {
906 + pr_err("8305 rev B0 and older are not supported\n");
907 + ret = -ENODEV;
908 + goto out2;
912 + if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) {
913 + pr_err("8381 rev B2 and older are not supported\n");
914 + ret = -ENODEV;
915 + goto out2;
918 + if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) {
919 + pr_err("8385 rev B0 and older are not supported\n");
920 + ret = -ENODEV;
921 + goto out2;
924 + /* Make this card known to the libertas driver */
925 + priv = lbs_add_card(card, &p_dev->dev);
926 + if (IS_ERR(priv)) {
927 + ret = PTR_ERR(priv);
928 + goto out2;
931 + /* Set up fields in lbs_private */
932 + card->priv = priv;
933 + priv->card = card;
934 + priv->hw_host_to_card = if_cs_host_to_card;
935 + priv->enter_deep_sleep = NULL;
936 + priv->exit_deep_sleep = NULL;
937 + priv->reset_deep_sleep_wakeup = NULL;
939 + /* Get firmware */
940 + ret = lbs_get_firmware_async(priv, &p_dev->dev, card->model, fw_table,
941 + if_cs_prog_firmware);
942 + if (ret) {
943 + pr_err("failed to find firmware (%d)\n", ret);
944 + goto out3;
947 + goto out;
949 +out3:
950 + lbs_remove_card(priv);
951 +out2:
952 + ioport_unmap(card->iobase);
953 +out1:
954 + pcmcia_disable_device(p_dev);
955 +out:
956 + return ret;
960 +static void if_cs_detach(struct pcmcia_device *p_dev)
962 + struct if_cs_card *card = p_dev->priv;
964 + lbs_stop_card(card->priv);
965 + lbs_remove_card(card->priv);
966 + if_cs_disable_ints(card);
967 + if_cs_release(p_dev);
968 + kfree(card);
973 +/********************************************************************/
974 +/* Module initialization */
975 +/********************************************************************/
977 +static const struct pcmcia_device_id if_cs_ids[] = {
978 + PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID),
979 + PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
980 + PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
981 + /* NOTE: keep in sync with get_model() */
982 + PCMCIA_DEVICE_NULL,
984 +MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
986 +static struct pcmcia_driver lbs_driver = {
987 + .owner = THIS_MODULE,
988 + .name = DRV_NAME,
989 + .probe = if_cs_probe,
990 + .remove = if_cs_detach,
991 + .id_table = if_cs_ids,
993 +module_pcmcia_driver(lbs_driver);