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
14 A driver for Marvell Libertas 8388 USB devices.
17 + tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
18 + depends on LIBERTAS && PCMCIA && HAS_IOPORT_MAP
20 + A driver for Marvell Libertas 8385 CompactFlash devices.
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
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
35 +++ a/drivers/net/wireless/marvell/libertas/if_cs.c
37 +// SPDX-License-Identifier: GPL-2.0-or-later
40 + Driver for the Marvell 8385 based compact flash WLAN cards.
42 + (C) 2007 by Holger Schurig <hs4233@mail.mn-solutions.de>
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"
68 +/********************************************************************/
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 +/********************************************************************/
83 + struct pcmcia_device *p_dev;
84 + struct lbs_private *priv;
85 + void __iomem *iobase;
92 + MODEL_UNKNOWN = 0x00,
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" },
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 */
126 +static int debug_output = 0;
128 +/* This way the compiler optimizes the printk's away */
129 +#define debug_output 0
132 +static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
134 + unsigned int val = ioread8(card->iobase + reg);
136 + printk(KERN_INFO "inb %08x<%02x\n", reg, val);
139 +static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
141 + unsigned int val = ioread16(card->iobase + reg);
143 + printk(KERN_INFO "inw %08x<%04x\n", reg, val);
146 +static inline void if_cs_read16_rep(
147 + struct if_cs_card *card,
150 + unsigned long count)
153 + printk(KERN_INFO "insw %08x<(0x%lx words)\n",
155 + ioread16_rep(card->iobase + reg, buf, count);
158 +static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
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)
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,
176 + unsigned long count)
179 + printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
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
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.
197 +static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 reg)
201 + for (i = 0; i < 100000; i++) {
202 + u8 val = if_cs_read8(card, addr);
213 + * First the bitmasks for the host/card interrupt/status registers:
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
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
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.
253 +#define IF_CS_HOST_INT_MASK 0x00000004
256 + * Used to send or receive data packets:
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:
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
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
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.
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)
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.
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
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:
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.
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.
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)
349 + else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID)
351 + else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID)
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
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;
379 + if_cs_disable_ints(card);
381 + /* Is hardware ready? */
383 + u16 status = if_cs_read16(card, IF_CS_CARD_STATUS);
384 + if (status & IF_CS_BIT_COMMAND)
386 + if (++loops > 100) {
387 + netdev_err(priv->dev, "card not ready for commands\n");
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? */
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);
410 + if_cs_enable_ints(card);
415 + * Called from if_cs_host_to_card to send a data to the hardware
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;
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);
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.
442 +static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
444 + unsigned long flags;
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");
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",
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));
467 + data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP);
469 + /* This is a workaround for a firmware that reports too much
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);
483 +static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
485 + struct sk_buff *skb = NULL;
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",
494 + priv->dev->stats.rx_dropped++;
498 + skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
502 + skb_reserve(skb, 2);/* 16 byte align */
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));
508 + data[len-1] = if_cs_read8(priv->card, IF_CS_READ);
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);
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;
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);
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);
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;
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,
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 +/********************************************************************/
588 +/********************************************************************/
591 + * Tries to program the helper firmware.
593 + * Return 0 on success
595 +static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
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.
606 + if (card->align_regs)
607 + scratch = if_cs_read16(card, IF_CS_SCRATCH) >> 8;
609 + scratch = if_cs_read8(card, IF_CS_SCRATCH);
611 + /* "If the value is 0x5a, the firmware is already
612 + * downloaded successfully"
614 + if (scratch == IF_CS_SCRATCH_HELPER_OK)
617 + /* "If the value is != 00, it is invalid value of register */
618 + if (scratch != IF_CS_SCRATCH_BOOT_OK) {
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 */
629 + /* "the number of bytes to send is 256" */
631 + int remain = fw->size - sent;
633 + if (remain < count)
637 + * "write the number of bytes to be sent to the I/O Command
638 + * write length register"
640 + if_cs_write16(card, IF_CS_CMD_LEN, count);
642 + /* "write this to I/O Command port register as 16 bit writes */
644 + if_cs_write16_rep(card, IF_CS_CMD,
649 + * "Assert the download over interrupt command in the Host
652 + if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
655 + * "Assert the download over interrupt command in the Card
656 + * interrupt case register"
658 + if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
661 + * "The host polls the Card Status register ... for 50 ms before
662 + * declaring a failure"
664 + ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
665 + IF_CS_BIT_COMMAND);
667 + pr_err("can't download helper at 0x%x, ret %d\n",
683 +static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
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);
695 + pr_err("helper firmware doesn't answer\n");
699 + for (sent = 0; sent < fw->size; sent += len) {
700 + len = if_cs_read16(card, IF_CS_SQ_READ_LOW);
703 + pr_info("odd, need to retry this firmware block\n");
709 + pr_err("could not download firmware\n");
718 + if_cs_write16(card, IF_CS_CMD_LEN, len);
720 + if_cs_write16_rep(card, IF_CS_CMD,
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);
729 + pr_err("can't download firmware at 0x%x\n", sent);
734 + ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
736 + pr_err("firmware download failed\n");
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;
749 + pr_err("failed to find firmware (%d)\n", ret);
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);
760 + /* Now actually get the IRQ */
761 + ret = request_irq(card->p_dev->irq, if_cs_interrupt,
762 + IRQF_SHARED, DRV_NAME, card);
764 + pr_err("error in request_irq\n");
769 + * Clear any interrupt cause that happened while sending
770 + * firmware/initializing card
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,
798 + priv->dnld_sent = DNLD_DATA_SENT;
799 + if_cs_send_data(priv, buf, nb);
803 + priv->dnld_sent = DNLD_CMD_SENT;
804 + ret = if_cs_send_cmd(priv, buf, nb);
807 + netdev_err(priv->dev, "%s: unsupported type %d\n",
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);
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");
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)
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);
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");
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.
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");
878 + ret = pcmcia_enable_device(p_dev);
880 + pr_err("error in pcmcia_enable_device\n");
884 + /* Finally, report what we've done */
885 + lbs_deb_cs("irq %d, io %pR", p_dev->irq, p_dev->resource[0]);
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.
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);
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");
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");
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");
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);
931 + /* Set up fields in lbs_private */
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;
940 + ret = lbs_get_firmware_async(priv, &p_dev->dev, card->model, fw_table,
941 + if_cs_prog_firmware);
943 + pr_err("failed to find firmware (%d)\n", ret);
950 + lbs_remove_card(priv);
952 + ioport_unmap(card->iobase);
954 + pcmcia_disable_device(p_dev);
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);
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,
989 + .probe = if_cs_probe,
990 + .remove = if_cs_detach,
991 + .id_table = if_cs_ids,
993 +module_pcmcia_driver(lbs_driver);