1*ca47d344SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f988d640SKalle Valo /*
3f988d640SKalle Valo
4f988d640SKalle Valo Driver for the Marvell 8385 based compact flash WLAN cards.
5f988d640SKalle Valo
6f988d640SKalle Valo (C) 2007 by Holger Schurig <hs4233@mail.mn-solutions.de>
7f988d640SKalle Valo
8f988d640SKalle Valo
9f988d640SKalle Valo */
10f988d640SKalle Valo
11f988d640SKalle Valo #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12f988d640SKalle Valo
13f988d640SKalle Valo #include <linux/module.h>
14f988d640SKalle Valo #include <linux/slab.h>
15f988d640SKalle Valo #include <linux/delay.h>
16f988d640SKalle Valo #include <linux/moduleparam.h>
17f988d640SKalle Valo #include <linux/firmware.h>
18f988d640SKalle Valo #include <linux/netdevice.h>
19f988d640SKalle Valo
20f988d640SKalle Valo #include <pcmcia/cistpl.h>
21f988d640SKalle Valo #include <pcmcia/ds.h>
22f988d640SKalle Valo
23f988d640SKalle Valo #include <linux/io.h>
24f988d640SKalle Valo
25f988d640SKalle Valo #define DRV_NAME "libertas_cs"
26f988d640SKalle Valo
27f988d640SKalle Valo #include "decl.h"
28f988d640SKalle Valo #include "defs.h"
29f988d640SKalle Valo #include "dev.h"
30f988d640SKalle Valo
31f988d640SKalle Valo
32f988d640SKalle Valo /********************************************************************/
33f988d640SKalle Valo /* Module stuff */
34f988d640SKalle Valo /********************************************************************/
35f988d640SKalle Valo
36f988d640SKalle Valo MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
37f988d640SKalle Valo MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
38f988d640SKalle Valo MODULE_LICENSE("GPL");
39f988d640SKalle Valo
40f988d640SKalle Valo
41f988d640SKalle Valo
42f988d640SKalle Valo /********************************************************************/
43f988d640SKalle Valo /* Data structures */
44f988d640SKalle Valo /********************************************************************/
45f988d640SKalle Valo
46f988d640SKalle Valo struct if_cs_card {
47f988d640SKalle Valo struct pcmcia_device *p_dev;
48f988d640SKalle Valo struct lbs_private *priv;
49f988d640SKalle Valo void __iomem *iobase;
50f988d640SKalle Valo bool align_regs;
51f988d640SKalle Valo u32 model;
52f988d640SKalle Valo };
53f988d640SKalle Valo
54f988d640SKalle Valo
55f988d640SKalle Valo enum {
56f988d640SKalle Valo MODEL_UNKNOWN = 0x00,
57f988d640SKalle Valo MODEL_8305 = 0x01,
58f988d640SKalle Valo MODEL_8381 = 0x02,
59f988d640SKalle Valo MODEL_8385 = 0x03
60f988d640SKalle Valo };
61f988d640SKalle Valo
62f988d640SKalle Valo static const struct lbs_fw_table fw_table[] = {
63f988d640SKalle Valo { MODEL_8305, "libertas/cf8305.bin", NULL },
64f988d640SKalle Valo { MODEL_8305, "libertas_cs_helper.fw", NULL },
65f988d640SKalle Valo { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" },
66f988d640SKalle Valo { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" },
67f988d640SKalle Valo { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" },
68f988d640SKalle Valo { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" },
69f988d640SKalle Valo { 0, NULL, NULL }
70f988d640SKalle Valo };
71f988d640SKalle Valo MODULE_FIRMWARE("libertas/cf8305.bin");
72f988d640SKalle Valo MODULE_FIRMWARE("libertas/cf8381_helper.bin");
73f988d640SKalle Valo MODULE_FIRMWARE("libertas/cf8381.bin");
74f988d640SKalle Valo MODULE_FIRMWARE("libertas/cf8385_helper.bin");
75f988d640SKalle Valo MODULE_FIRMWARE("libertas/cf8385.bin");
76f988d640SKalle Valo MODULE_FIRMWARE("libertas_cs_helper.fw");
77f988d640SKalle Valo MODULE_FIRMWARE("libertas_cs.fw");
78f988d640SKalle Valo
79f988d640SKalle Valo
80f988d640SKalle Valo /********************************************************************/
81f988d640SKalle Valo /* Hardware access */
82f988d640SKalle Valo /********************************************************************/
83f988d640SKalle Valo
84f988d640SKalle Valo /* This define enables wrapper functions which allow you
85f988d640SKalle Valo to dump all register accesses. You normally won't this,
86f988d640SKalle Valo except for development */
87f988d640SKalle Valo /* #define DEBUG_IO */
88f988d640SKalle Valo
89f988d640SKalle Valo #ifdef DEBUG_IO
90f988d640SKalle Valo static int debug_output = 0;
91f988d640SKalle Valo #else
92f988d640SKalle Valo /* This way the compiler optimizes the printk's away */
93f988d640SKalle Valo #define debug_output 0
94f988d640SKalle Valo #endif
95f988d640SKalle Valo
if_cs_read8(struct if_cs_card * card,uint reg)96f988d640SKalle Valo static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
97f988d640SKalle Valo {
98f988d640SKalle Valo unsigned int val = ioread8(card->iobase + reg);
99f988d640SKalle Valo if (debug_output)
100f988d640SKalle Valo printk(KERN_INFO "inb %08x<%02x\n", reg, val);
101f988d640SKalle Valo return val;
102f988d640SKalle Valo }
if_cs_read16(struct if_cs_card * card,uint reg)103f988d640SKalle Valo static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
104f988d640SKalle Valo {
105f988d640SKalle Valo unsigned int val = ioread16(card->iobase + reg);
106f988d640SKalle Valo if (debug_output)
107f988d640SKalle Valo printk(KERN_INFO "inw %08x<%04x\n", reg, val);
108f988d640SKalle Valo return val;
109f988d640SKalle Valo }
if_cs_read16_rep(struct if_cs_card * card,uint reg,void * buf,unsigned long count)110f988d640SKalle Valo static inline void if_cs_read16_rep(
111f988d640SKalle Valo struct if_cs_card *card,
112f988d640SKalle Valo uint reg,
113f988d640SKalle Valo void *buf,
114f988d640SKalle Valo unsigned long count)
115f988d640SKalle Valo {
116f988d640SKalle Valo if (debug_output)
117f988d640SKalle Valo printk(KERN_INFO "insw %08x<(0x%lx words)\n",
118f988d640SKalle Valo reg, count);
119f988d640SKalle Valo ioread16_rep(card->iobase + reg, buf, count);
120f988d640SKalle Valo }
121f988d640SKalle Valo
if_cs_write8(struct if_cs_card * card,uint reg,u8 val)122f988d640SKalle Valo static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
123f988d640SKalle Valo {
124f988d640SKalle Valo if (debug_output)
125f988d640SKalle Valo printk(KERN_INFO "outb %08x>%02x\n", reg, val);
126f988d640SKalle Valo iowrite8(val, card->iobase + reg);
127f988d640SKalle Valo }
128f988d640SKalle Valo
if_cs_write16(struct if_cs_card * card,uint reg,u16 val)129f988d640SKalle Valo static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
130f988d640SKalle Valo {
131f988d640SKalle Valo if (debug_output)
132f988d640SKalle Valo printk(KERN_INFO "outw %08x>%04x\n", reg, val);
133f988d640SKalle Valo iowrite16(val, card->iobase + reg);
134f988d640SKalle Valo }
135f988d640SKalle Valo
if_cs_write16_rep(struct if_cs_card * card,uint reg,const void * buf,unsigned long count)136f988d640SKalle Valo static inline void if_cs_write16_rep(
137f988d640SKalle Valo struct if_cs_card *card,
138f988d640SKalle Valo uint reg,
139f988d640SKalle Valo const void *buf,
140f988d640SKalle Valo unsigned long count)
141f988d640SKalle Valo {
142f988d640SKalle Valo if (debug_output)
143f988d640SKalle Valo printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
144f988d640SKalle Valo reg, count);
145f988d640SKalle Valo iowrite16_rep(card->iobase + reg, buf, count);
146f988d640SKalle Valo }
147f988d640SKalle Valo
148f988d640SKalle Valo
149f988d640SKalle Valo /*
150f988d640SKalle Valo * I know that polling/delaying is frowned upon. However, this procedure
151f988d640SKalle Valo * with polling is needed while downloading the firmware. At this stage,
152f988d640SKalle Valo * the hardware does unfortunately not create any interrupts.
153f988d640SKalle Valo *
154f988d640SKalle Valo * Fortunately, this function is never used once the firmware is in
155f988d640SKalle Valo * the card. :-)
156f988d640SKalle Valo *
157f988d640SKalle Valo * As a reference, see the "Firmware Specification v5.1", page 18
158f988d640SKalle Valo * and 19. I did not follow their suggested timing to the word,
159f988d640SKalle Valo * but this works nice & fast anyway.
160f988d640SKalle Valo */
if_cs_poll_while_fw_download(struct if_cs_card * card,uint addr,u8 reg)161f988d640SKalle Valo static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 reg)
162f988d640SKalle Valo {
163f988d640SKalle Valo int i;
164f988d640SKalle Valo
165f988d640SKalle Valo for (i = 0; i < 100000; i++) {
166f988d640SKalle Valo u8 val = if_cs_read8(card, addr);
167f988d640SKalle Valo if (val == reg)
168f988d640SKalle Valo return 0;
169f988d640SKalle Valo udelay(5);
170f988d640SKalle Valo }
171f988d640SKalle Valo return -ETIME;
172f988d640SKalle Valo }
173f988d640SKalle Valo
174f988d640SKalle Valo
175f988d640SKalle Valo
176f988d640SKalle Valo /*
177f988d640SKalle Valo * First the bitmasks for the host/card interrupt/status registers:
178f988d640SKalle Valo */
179f988d640SKalle Valo #define IF_CS_BIT_TX 0x0001
180f988d640SKalle Valo #define IF_CS_BIT_RX 0x0002
181f988d640SKalle Valo #define IF_CS_BIT_COMMAND 0x0004
182f988d640SKalle Valo #define IF_CS_BIT_RESP 0x0008
183f988d640SKalle Valo #define IF_CS_BIT_EVENT 0x0010
184f988d640SKalle Valo #define IF_CS_BIT_MASK 0x001f
185f988d640SKalle Valo
186f988d640SKalle Valo
187f988d640SKalle Valo
188f988d640SKalle Valo /*
189f988d640SKalle Valo * It's not really clear to me what the host status register is for. It
190f988d640SKalle Valo * needs to be set almost in union with "host int cause". The following
191f988d640SKalle Valo * bits from above are used:
192f988d640SKalle Valo *
193f988d640SKalle Valo * IF_CS_BIT_TX driver downloaded a data packet
194f988d640SKalle Valo * IF_CS_BIT_RX driver got a data packet
195f988d640SKalle Valo * IF_CS_BIT_COMMAND driver downloaded a command
196f988d640SKalle Valo * IF_CS_BIT_RESP not used (has some meaning with powerdown)
197f988d640SKalle Valo * IF_CS_BIT_EVENT driver read a host event
198f988d640SKalle Valo */
199f988d640SKalle Valo #define IF_CS_HOST_STATUS 0x00000000
200f988d640SKalle Valo
201f988d640SKalle Valo /*
202f988d640SKalle Valo * With the host int cause register can the host (that is, Linux) cause
203f988d640SKalle Valo * an interrupt in the firmware, to tell the firmware about those events:
204f988d640SKalle Valo *
205f988d640SKalle Valo * IF_CS_BIT_TX a data packet has been downloaded
206f988d640SKalle Valo * IF_CS_BIT_RX a received data packet has retrieved
207f988d640SKalle Valo * IF_CS_BIT_COMMAND a firmware block or a command has been downloaded
208f988d640SKalle Valo * IF_CS_BIT_RESP not used (has some meaning with powerdown)
209f988d640SKalle Valo * IF_CS_BIT_EVENT a host event (link lost etc) has been retrieved
210f988d640SKalle Valo */
211f988d640SKalle Valo #define IF_CS_HOST_INT_CAUSE 0x00000002
212f988d640SKalle Valo
213f988d640SKalle Valo /*
214f988d640SKalle Valo * The host int mask register is used to enable/disable interrupt. However,
215f988d640SKalle Valo * I have the suspicion that disabled interrupts are lost.
216f988d640SKalle Valo */
217f988d640SKalle Valo #define IF_CS_HOST_INT_MASK 0x00000004
218f988d640SKalle Valo
219f988d640SKalle Valo /*
220f988d640SKalle Valo * Used to send or receive data packets:
221f988d640SKalle Valo */
222f988d640SKalle Valo #define IF_CS_WRITE 0x00000016
223f988d640SKalle Valo #define IF_CS_WRITE_LEN 0x00000014
224f988d640SKalle Valo #define IF_CS_READ 0x00000010
225f988d640SKalle Valo #define IF_CS_READ_LEN 0x00000024
226f988d640SKalle Valo
227f988d640SKalle Valo /*
228f988d640SKalle Valo * Used to send commands (and to send firmware block) and to
229f988d640SKalle Valo * receive command responses:
230f988d640SKalle Valo */
231f988d640SKalle Valo #define IF_CS_CMD 0x0000001A
232f988d640SKalle Valo #define IF_CS_CMD_LEN 0x00000018
233f988d640SKalle Valo #define IF_CS_RESP 0x00000012
234f988d640SKalle Valo #define IF_CS_RESP_LEN 0x00000030
235f988d640SKalle Valo
236f988d640SKalle Valo /*
237f988d640SKalle Valo * The card status registers shows what the card/firmware actually
238f988d640SKalle Valo * accepts:
239f988d640SKalle Valo *
240f988d640SKalle Valo * IF_CS_BIT_TX you may send a data packet
241f988d640SKalle Valo * IF_CS_BIT_RX you may retrieve a data packet
242f988d640SKalle Valo * IF_CS_BIT_COMMAND you may send a command
243f988d640SKalle Valo * IF_CS_BIT_RESP you may retrieve a command response
244f988d640SKalle Valo * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc)
245f988d640SKalle Valo *
246f988d640SKalle Valo * When reading this register several times, you will get back the same
247f988d640SKalle Valo * results --- with one exception: the IF_CS_BIT_EVENT clear itself
248f988d640SKalle Valo * automatically.
249f988d640SKalle Valo *
250f988d640SKalle Valo * Not that we don't rely on BIT_RX,_BIT_RESP or BIT_EVENT because
251f988d640SKalle Valo * we handle this via the card int cause register.
252f988d640SKalle Valo */
253f988d640SKalle Valo #define IF_CS_CARD_STATUS 0x00000020
254f988d640SKalle Valo #define IF_CS_CARD_STATUS_MASK 0x7f00
255f988d640SKalle Valo
256f988d640SKalle Valo /*
257f988d640SKalle Valo * The card int cause register is used by the card/firmware to notify us
258f988d640SKalle Valo * about the following events:
259f988d640SKalle Valo *
260f988d640SKalle Valo * IF_CS_BIT_TX a data packet has successfully been sentx
261f988d640SKalle Valo * IF_CS_BIT_RX a data packet has been received and can be retrieved
262f988d640SKalle Valo * IF_CS_BIT_COMMAND not used
263f988d640SKalle Valo * IF_CS_BIT_RESP the firmware has a command response for us
264f988d640SKalle Valo * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc)
265f988d640SKalle Valo */
266f988d640SKalle Valo #define IF_CS_CARD_INT_CAUSE 0x00000022
267f988d640SKalle Valo
268f988d640SKalle Valo /*
269f988d640SKalle Valo * This is used to for handshaking with the card's bootloader/helper image
270f988d640SKalle Valo * to synchronize downloading of firmware blocks.
271f988d640SKalle Valo */
272f988d640SKalle Valo #define IF_CS_SQ_READ_LOW 0x00000028
273f988d640SKalle Valo #define IF_CS_SQ_HELPER_OK 0x10
274f988d640SKalle Valo
275f988d640SKalle Valo /*
276f988d640SKalle Valo * The scratch register tells us ...
277f988d640SKalle Valo *
278f988d640SKalle Valo * IF_CS_SCRATCH_BOOT_OK the bootloader runs
279f988d640SKalle Valo * IF_CS_SCRATCH_HELPER_OK the helper firmware already runs
280f988d640SKalle Valo */
281f988d640SKalle Valo #define IF_CS_SCRATCH 0x0000003F
282f988d640SKalle Valo #define IF_CS_SCRATCH_BOOT_OK 0x00
283f988d640SKalle Valo #define IF_CS_SCRATCH_HELPER_OK 0x5a
284f988d640SKalle Valo
285f988d640SKalle Valo /*
286f988d640SKalle Valo * Used to detect ancient chips:
287f988d640SKalle Valo */
288f988d640SKalle Valo #define IF_CS_PRODUCT_ID 0x0000001C
289f988d640SKalle Valo #define IF_CS_CF8385_B1_REV 0x12
290f988d640SKalle Valo #define IF_CS_CF8381_B3_REV 0x04
291f988d640SKalle Valo #define IF_CS_CF8305_B1_REV 0x03
292f988d640SKalle Valo
293f988d640SKalle Valo /*
294f988d640SKalle Valo * Used to detect other cards than CF8385 since their revisions of silicon
295f988d640SKalle Valo * doesn't match those from CF8385, eg. CF8381 B3 works with this driver.
296f988d640SKalle Valo */
297f988d640SKalle Valo #define CF8305_MANFID 0x02db
298f988d640SKalle Valo #define CF8305_CARDID 0x8103
299f988d640SKalle Valo #define CF8381_MANFID 0x02db
300f988d640SKalle Valo #define CF8381_CARDID 0x6064
301f988d640SKalle Valo #define CF8385_MANFID 0x02df
302f988d640SKalle Valo #define CF8385_CARDID 0x8103
303f988d640SKalle Valo
304f988d640SKalle Valo /*
305f988d640SKalle Valo * FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when
306f988d640SKalle Valo * that gets fixed. Currently there's no way to access it from the probe hook.
307f988d640SKalle Valo */
get_model(u16 manf_id,u16 card_id)308f988d640SKalle Valo static inline u32 get_model(u16 manf_id, u16 card_id)
309f988d640SKalle Valo {
310f988d640SKalle Valo /* NOTE: keep in sync with if_cs_ids */
311f988d640SKalle Valo if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID)
312f988d640SKalle Valo return MODEL_8305;
313f988d640SKalle Valo else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID)
314f988d640SKalle Valo return MODEL_8381;
315f988d640SKalle Valo else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID)
316f988d640SKalle Valo return MODEL_8385;
317f988d640SKalle Valo return MODEL_UNKNOWN;
318f988d640SKalle Valo }
319f988d640SKalle Valo
320f988d640SKalle Valo /********************************************************************/
321f988d640SKalle Valo /* I/O and interrupt handling */
322f988d640SKalle Valo /********************************************************************/
323f988d640SKalle Valo
if_cs_enable_ints(struct if_cs_card * card)324f988d640SKalle Valo static inline void if_cs_enable_ints(struct if_cs_card *card)
325f988d640SKalle Valo {
326f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_INT_MASK, 0);
327f988d640SKalle Valo }
328f988d640SKalle Valo
if_cs_disable_ints(struct if_cs_card * card)329f988d640SKalle Valo static inline void if_cs_disable_ints(struct if_cs_card *card)
330f988d640SKalle Valo {
331f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK);
332f988d640SKalle Valo }
333f988d640SKalle Valo
334f988d640SKalle Valo /*
335f988d640SKalle Valo * Called from if_cs_host_to_card to send a command to the hardware
336f988d640SKalle Valo */
if_cs_send_cmd(struct lbs_private * priv,u8 * buf,u16 nb)337f988d640SKalle Valo static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
338f988d640SKalle Valo {
339f988d640SKalle Valo struct if_cs_card *card = (struct if_cs_card *)priv->card;
340f988d640SKalle Valo int ret = -1;
341f988d640SKalle Valo int loops = 0;
342f988d640SKalle Valo
343f988d640SKalle Valo if_cs_disable_ints(card);
344f988d640SKalle Valo
345f988d640SKalle Valo /* Is hardware ready? */
346f988d640SKalle Valo while (1) {
347f988d640SKalle Valo u16 status = if_cs_read16(card, IF_CS_CARD_STATUS);
348f988d640SKalle Valo if (status & IF_CS_BIT_COMMAND)
349f988d640SKalle Valo break;
350f988d640SKalle Valo if (++loops > 100) {
351f988d640SKalle Valo netdev_err(priv->dev, "card not ready for commands\n");
352f988d640SKalle Valo goto done;
353f988d640SKalle Valo }
354f988d640SKalle Valo mdelay(1);
355f988d640SKalle Valo }
356f988d640SKalle Valo
357f988d640SKalle Valo if_cs_write16(card, IF_CS_CMD_LEN, nb);
358f988d640SKalle Valo
359f988d640SKalle Valo if_cs_write16_rep(card, IF_CS_CMD, buf, nb / 2);
360f988d640SKalle Valo /* Are we supposed to transfer an odd amount of bytes? */
361f988d640SKalle Valo if (nb & 1)
362f988d640SKalle Valo if_cs_write8(card, IF_CS_CMD, buf[nb-1]);
363f988d640SKalle Valo
364f988d640SKalle Valo /* "Assert the download over interrupt command in the Host
365f988d640SKalle Valo * status register" */
366f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
367f988d640SKalle Valo
368f988d640SKalle Valo /* "Assert the download over interrupt command in the Card
369f988d640SKalle Valo * interrupt case register" */
370f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
371f988d640SKalle Valo ret = 0;
372f988d640SKalle Valo
373f988d640SKalle Valo done:
374f988d640SKalle Valo if_cs_enable_ints(card);
375f988d640SKalle Valo return ret;
376f988d640SKalle Valo }
377f988d640SKalle Valo
378f988d640SKalle Valo /*
379f988d640SKalle Valo * Called from if_cs_host_to_card to send a data to the hardware
380f988d640SKalle Valo */
if_cs_send_data(struct lbs_private * priv,u8 * buf,u16 nb)381f988d640SKalle Valo static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
382f988d640SKalle Valo {
383f988d640SKalle Valo struct if_cs_card *card = (struct if_cs_card *)priv->card;
384f988d640SKalle Valo u16 status;
385f988d640SKalle Valo
386f988d640SKalle Valo if_cs_disable_ints(card);
387f988d640SKalle Valo
388f988d640SKalle Valo status = if_cs_read16(card, IF_CS_CARD_STATUS);
389f988d640SKalle Valo BUG_ON((status & IF_CS_BIT_TX) == 0);
390f988d640SKalle Valo
391f988d640SKalle Valo if_cs_write16(card, IF_CS_WRITE_LEN, nb);
392f988d640SKalle Valo
393f988d640SKalle Valo /* write even number of bytes, then odd byte if necessary */
394f988d640SKalle Valo if_cs_write16_rep(card, IF_CS_WRITE, buf, nb / 2);
395f988d640SKalle Valo if (nb & 1)
396f988d640SKalle Valo if_cs_write8(card, IF_CS_WRITE, buf[nb-1]);
397f988d640SKalle Valo
398f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX);
399f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX);
400f988d640SKalle Valo if_cs_enable_ints(card);
401f988d640SKalle Valo }
402f988d640SKalle Valo
403f988d640SKalle Valo /*
404f988d640SKalle Valo * Get the command result out of the card.
405f988d640SKalle Valo */
if_cs_receive_cmdres(struct lbs_private * priv,u8 * data,u32 * len)406f988d640SKalle Valo static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
407f988d640SKalle Valo {
408f988d640SKalle Valo unsigned long flags;
409f988d640SKalle Valo int ret = -1;
410f988d640SKalle Valo u16 status;
411f988d640SKalle Valo
412f988d640SKalle Valo /* is hardware ready? */
413f988d640SKalle Valo status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
414f988d640SKalle Valo if ((status & IF_CS_BIT_RESP) == 0) {
415f988d640SKalle Valo netdev_err(priv->dev, "no cmd response in card\n");
416f988d640SKalle Valo *len = 0;
417f988d640SKalle Valo goto out;
418f988d640SKalle Valo }
419f988d640SKalle Valo
420f988d640SKalle Valo *len = if_cs_read16(priv->card, IF_CS_RESP_LEN);
421f988d640SKalle Valo if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) {
422f988d640SKalle Valo netdev_err(priv->dev,
423f988d640SKalle Valo "card cmd buffer has invalid # of bytes (%d)\n",
424f988d640SKalle Valo *len);
425f988d640SKalle Valo goto out;
426f988d640SKalle Valo }
427f988d640SKalle Valo
428f988d640SKalle Valo /* read even number of bytes, then odd byte if necessary */
429f988d640SKalle Valo if_cs_read16_rep(priv->card, IF_CS_RESP, data, *len/sizeof(u16));
430f988d640SKalle Valo if (*len & 1)
431f988d640SKalle Valo data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP);
432f988d640SKalle Valo
433f988d640SKalle Valo /* This is a workaround for a firmware that reports too much
434f988d640SKalle Valo * bytes */
435f988d640SKalle Valo *len -= 8;
436f988d640SKalle Valo ret = 0;
437f988d640SKalle Valo
438f988d640SKalle Valo /* Clear this flag again */
439f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags);
440f988d640SKalle Valo priv->dnld_sent = DNLD_RES_RECEIVED;
441f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags);
442f988d640SKalle Valo
443f988d640SKalle Valo out:
444f988d640SKalle Valo return ret;
445f988d640SKalle Valo }
446f988d640SKalle Valo
if_cs_receive_data(struct lbs_private * priv)447f988d640SKalle Valo static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
448f988d640SKalle Valo {
449f988d640SKalle Valo struct sk_buff *skb = NULL;
450f988d640SKalle Valo u16 len;
451f988d640SKalle Valo u8 *data;
452f988d640SKalle Valo
453f988d640SKalle Valo len = if_cs_read16(priv->card, IF_CS_READ_LEN);
454f988d640SKalle Valo if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
455f988d640SKalle Valo netdev_err(priv->dev,
456f988d640SKalle Valo "card data buffer has invalid # of bytes (%d)\n",
457f988d640SKalle Valo len);
458f988d640SKalle Valo priv->dev->stats.rx_dropped++;
459f988d640SKalle Valo goto dat_err;
460f988d640SKalle Valo }
461f988d640SKalle Valo
462f988d640SKalle Valo skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
463f988d640SKalle Valo if (!skb)
464f988d640SKalle Valo goto out;
465f988d640SKalle Valo skb_put(skb, len);
466f988d640SKalle Valo skb_reserve(skb, 2);/* 16 byte align */
467f988d640SKalle Valo data = skb->data;
468f988d640SKalle Valo
469f988d640SKalle Valo /* read even number of bytes, then odd byte if necessary */
470f988d640SKalle Valo if_cs_read16_rep(priv->card, IF_CS_READ, data, len/sizeof(u16));
471f988d640SKalle Valo if (len & 1)
472f988d640SKalle Valo data[len-1] = if_cs_read8(priv->card, IF_CS_READ);
473f988d640SKalle Valo
474f988d640SKalle Valo dat_err:
475f988d640SKalle Valo if_cs_write16(priv->card, IF_CS_HOST_STATUS, IF_CS_BIT_RX);
476f988d640SKalle Valo if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX);
477f988d640SKalle Valo
478f988d640SKalle Valo out:
479f988d640SKalle Valo return skb;
480f988d640SKalle Valo }
481f988d640SKalle Valo
if_cs_interrupt(int irq,void * data)482f988d640SKalle Valo static irqreturn_t if_cs_interrupt(int irq, void *data)
483f988d640SKalle Valo {
484f988d640SKalle Valo struct if_cs_card *card = data;
485f988d640SKalle Valo struct lbs_private *priv = card->priv;
486f988d640SKalle Valo u16 cause;
487f988d640SKalle Valo
488f988d640SKalle Valo /* Ask card interrupt cause register if there is something for us */
489f988d640SKalle Valo cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE);
490f988d640SKalle Valo lbs_deb_cs("cause 0x%04x\n", cause);
491f988d640SKalle Valo
492f988d640SKalle Valo if (cause == 0) {
493f988d640SKalle Valo /* Not for us */
494f988d640SKalle Valo return IRQ_NONE;
495f988d640SKalle Valo }
496f988d640SKalle Valo
497f988d640SKalle Valo if (cause == 0xffff) {
498f988d640SKalle Valo /* Read in junk, the card has probably been removed */
499f988d640SKalle Valo card->priv->surpriseremoved = 1;
500f988d640SKalle Valo return IRQ_HANDLED;
501f988d640SKalle Valo }
502f988d640SKalle Valo
503f988d640SKalle Valo if (cause & IF_CS_BIT_RX) {
504f988d640SKalle Valo struct sk_buff *skb;
505f988d640SKalle Valo lbs_deb_cs("rx packet\n");
506f988d640SKalle Valo skb = if_cs_receive_data(priv);
507f988d640SKalle Valo if (skb)
508f988d640SKalle Valo lbs_process_rxed_packet(priv, skb);
509f988d640SKalle Valo }
510f988d640SKalle Valo
511f988d640SKalle Valo if (cause & IF_CS_BIT_TX) {
512f988d640SKalle Valo lbs_deb_cs("tx done\n");
513f988d640SKalle Valo lbs_host_to_card_done(priv);
514f988d640SKalle Valo }
515f988d640SKalle Valo
516f988d640SKalle Valo if (cause & IF_CS_BIT_RESP) {
517f988d640SKalle Valo unsigned long flags;
518f988d640SKalle Valo u8 i;
519f988d640SKalle Valo
520f988d640SKalle Valo lbs_deb_cs("cmd resp\n");
521f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags);
522f988d640SKalle Valo i = (priv->resp_idx == 0) ? 1 : 0;
523f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags);
524f988d640SKalle Valo
525f988d640SKalle Valo BUG_ON(priv->resp_len[i]);
526f988d640SKalle Valo if_cs_receive_cmdres(priv, priv->resp_buf[i],
527f988d640SKalle Valo &priv->resp_len[i]);
528f988d640SKalle Valo
529f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags);
530f988d640SKalle Valo lbs_notify_command_response(priv, i);
531f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags);
532f988d640SKalle Valo }
533f988d640SKalle Valo
534f988d640SKalle Valo if (cause & IF_CS_BIT_EVENT) {
535f988d640SKalle Valo u16 status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
536f988d640SKalle Valo if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE,
537f988d640SKalle Valo IF_CS_BIT_EVENT);
538f988d640SKalle Valo lbs_queue_event(priv, (status & IF_CS_CARD_STATUS_MASK) >> 8);
539f988d640SKalle Valo }
540f988d640SKalle Valo
541f988d640SKalle Valo /* Clear interrupt cause */
542f988d640SKalle Valo if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK);
543f988d640SKalle Valo
544f988d640SKalle Valo return IRQ_HANDLED;
545f988d640SKalle Valo }
546f988d640SKalle Valo
547f988d640SKalle Valo
548f988d640SKalle Valo
549f988d640SKalle Valo
550f988d640SKalle Valo /********************************************************************/
551f988d640SKalle Valo /* Firmware */
552f988d640SKalle Valo /********************************************************************/
553f988d640SKalle Valo
554f988d640SKalle Valo /*
555f988d640SKalle Valo * Tries to program the helper firmware.
556f988d640SKalle Valo *
557f988d640SKalle Valo * Return 0 on success
558f988d640SKalle Valo */
if_cs_prog_helper(struct if_cs_card * card,const struct firmware * fw)559f988d640SKalle Valo static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
560f988d640SKalle Valo {
561f988d640SKalle Valo int ret = 0;
562f988d640SKalle Valo int sent = 0;
563f988d640SKalle Valo u8 scratch;
564f988d640SKalle Valo
565f988d640SKalle Valo /*
566f988d640SKalle Valo * This is the only place where an unaligned register access happens on
567f988d640SKalle Valo * the CF8305 card, therefore for the sake of speed of the driver, we do
568f988d640SKalle Valo * the alignment correction here.
569f988d640SKalle Valo */
570f988d640SKalle Valo if (card->align_regs)
571f988d640SKalle Valo scratch = if_cs_read16(card, IF_CS_SCRATCH) >> 8;
572f988d640SKalle Valo else
573f988d640SKalle Valo scratch = if_cs_read8(card, IF_CS_SCRATCH);
574f988d640SKalle Valo
575f988d640SKalle Valo /* "If the value is 0x5a, the firmware is already
576f988d640SKalle Valo * downloaded successfully"
577f988d640SKalle Valo */
578f988d640SKalle Valo if (scratch == IF_CS_SCRATCH_HELPER_OK)
579f988d640SKalle Valo goto done;
580f988d640SKalle Valo
581f988d640SKalle Valo /* "If the value is != 00, it is invalid value of register */
582f988d640SKalle Valo if (scratch != IF_CS_SCRATCH_BOOT_OK) {
583f988d640SKalle Valo ret = -ENODEV;
584f988d640SKalle Valo goto done;
585f988d640SKalle Valo }
586f988d640SKalle Valo
587f988d640SKalle Valo lbs_deb_cs("helper size %td\n", fw->size);
588f988d640SKalle Valo
589f988d640SKalle Valo /* "Set the 5 bytes of the helper image to 0" */
590f988d640SKalle Valo /* Not needed, this contains an ARM branch instruction */
591f988d640SKalle Valo
592f988d640SKalle Valo for (;;) {
593f988d640SKalle Valo /* "the number of bytes to send is 256" */
594f988d640SKalle Valo int count = 256;
595f988d640SKalle Valo int remain = fw->size - sent;
596f988d640SKalle Valo
597f988d640SKalle Valo if (remain < count)
598f988d640SKalle Valo count = remain;
599f988d640SKalle Valo
600f988d640SKalle Valo /*
601f988d640SKalle Valo * "write the number of bytes to be sent to the I/O Command
602f988d640SKalle Valo * write length register"
603f988d640SKalle Valo */
604f988d640SKalle Valo if_cs_write16(card, IF_CS_CMD_LEN, count);
605f988d640SKalle Valo
606f988d640SKalle Valo /* "write this to I/O Command port register as 16 bit writes */
607f988d640SKalle Valo if (count)
608f988d640SKalle Valo if_cs_write16_rep(card, IF_CS_CMD,
609f988d640SKalle Valo &fw->data[sent],
610f988d640SKalle Valo count >> 1);
611f988d640SKalle Valo
612f988d640SKalle Valo /*
613f988d640SKalle Valo * "Assert the download over interrupt command in the Host
614f988d640SKalle Valo * status register"
615f988d640SKalle Valo */
616f988d640SKalle Valo if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
617f988d640SKalle Valo
618f988d640SKalle Valo /*
619f988d640SKalle Valo * "Assert the download over interrupt command in the Card
620f988d640SKalle Valo * interrupt case register"
621f988d640SKalle Valo */
622f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
623f988d640SKalle Valo
624f988d640SKalle Valo /*
625f988d640SKalle Valo * "The host polls the Card Status register ... for 50 ms before
626f988d640SKalle Valo * declaring a failure"
627f988d640SKalle Valo */
628f988d640SKalle Valo ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
629f988d640SKalle Valo IF_CS_BIT_COMMAND);
630f988d640SKalle Valo if (ret < 0) {
631f988d640SKalle Valo pr_err("can't download helper at 0x%x, ret %d\n",
632f988d640SKalle Valo sent, ret);
633f988d640SKalle Valo goto done;
634f988d640SKalle Valo }
635f988d640SKalle Valo
636f988d640SKalle Valo if (count == 0)
637f988d640SKalle Valo break;
638f988d640SKalle Valo
639f988d640SKalle Valo sent += count;
640f988d640SKalle Valo }
641f988d640SKalle Valo
642f988d640SKalle Valo done:
643f988d640SKalle Valo return ret;
644f988d640SKalle Valo }
645f988d640SKalle Valo
646f988d640SKalle Valo
if_cs_prog_real(struct if_cs_card * card,const struct firmware * fw)647f988d640SKalle Valo static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
648f988d640SKalle Valo {
649f988d640SKalle Valo int ret = 0;
650f988d640SKalle Valo int retry = 0;
651f988d640SKalle Valo int len = 0;
652f988d640SKalle Valo int sent;
653f988d640SKalle Valo
654f988d640SKalle Valo lbs_deb_cs("fw size %td\n", fw->size);
655f988d640SKalle Valo
656f988d640SKalle Valo ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
657f988d640SKalle Valo IF_CS_SQ_HELPER_OK);
658f988d640SKalle Valo if (ret < 0) {
659f988d640SKalle Valo pr_err("helper firmware doesn't answer\n");
660f988d640SKalle Valo goto done;
661f988d640SKalle Valo }
662f988d640SKalle Valo
663f988d640SKalle Valo for (sent = 0; sent < fw->size; sent += len) {
664f988d640SKalle Valo len = if_cs_read16(card, IF_CS_SQ_READ_LOW);
665f988d640SKalle Valo if (len & 1) {
666f988d640SKalle Valo retry++;
667f988d640SKalle Valo pr_info("odd, need to retry this firmware block\n");
668f988d640SKalle Valo } else {
669f988d640SKalle Valo retry = 0;
670f988d640SKalle Valo }
671f988d640SKalle Valo
672f988d640SKalle Valo if (retry > 20) {
673f988d640SKalle Valo pr_err("could not download firmware\n");
674f988d640SKalle Valo ret = -ENODEV;
675f988d640SKalle Valo goto done;
676f988d640SKalle Valo }
677f988d640SKalle Valo if (retry) {
678f988d640SKalle Valo sent -= len;
679f988d640SKalle Valo }
680f988d640SKalle Valo
681f988d640SKalle Valo
682f988d640SKalle Valo if_cs_write16(card, IF_CS_CMD_LEN, len);
683f988d640SKalle Valo
684f988d640SKalle Valo if_cs_write16_rep(card, IF_CS_CMD,
685f988d640SKalle Valo &fw->data[sent],
686f988d640SKalle Valo (len+1) >> 1);
687f988d640SKalle Valo if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND);
688f988d640SKalle Valo if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND);
689f988d640SKalle Valo
690f988d640SKalle Valo ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS,
691f988d640SKalle Valo IF_CS_BIT_COMMAND);
692f988d640SKalle Valo if (ret < 0) {
693f988d640SKalle Valo pr_err("can't download firmware at 0x%x\n", sent);
694f988d640SKalle Valo goto done;
695f988d640SKalle Valo }
696f988d640SKalle Valo }
697f988d640SKalle Valo
698f988d640SKalle Valo ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
699f988d640SKalle Valo if (ret < 0)
700f988d640SKalle Valo pr_err("firmware download failed\n");
701f988d640SKalle Valo
702f988d640SKalle Valo done:
703f988d640SKalle Valo return ret;
704f988d640SKalle Valo }
705f988d640SKalle Valo
if_cs_prog_firmware(struct lbs_private * priv,int ret,const struct firmware * helper,const struct firmware * mainfw)706f988d640SKalle Valo static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
707f988d640SKalle Valo const struct firmware *helper,
708f988d640SKalle Valo const struct firmware *mainfw)
709f988d640SKalle Valo {
710f988d640SKalle Valo struct if_cs_card *card = priv->card;
711f988d640SKalle Valo
712f988d640SKalle Valo if (ret) {
713f988d640SKalle Valo pr_err("failed to find firmware (%d)\n", ret);
714f988d640SKalle Valo return;
715f988d640SKalle Valo }
716f988d640SKalle Valo
717f988d640SKalle Valo /* Load the firmware */
718f988d640SKalle Valo ret = if_cs_prog_helper(card, helper);
719f988d640SKalle Valo if (ret == 0 && (card->model != MODEL_8305))
720f988d640SKalle Valo ret = if_cs_prog_real(card, mainfw);
721f988d640SKalle Valo if (ret)
722f988d640SKalle Valo return;
723f988d640SKalle Valo
724f988d640SKalle Valo /* Now actually get the IRQ */
725f988d640SKalle Valo ret = request_irq(card->p_dev->irq, if_cs_interrupt,
726f988d640SKalle Valo IRQF_SHARED, DRV_NAME, card);
727f988d640SKalle Valo if (ret) {
728f988d640SKalle Valo pr_err("error in request_irq\n");
729f988d640SKalle Valo return;
730f988d640SKalle Valo }
731f988d640SKalle Valo
732f988d640SKalle Valo /*
733f988d640SKalle Valo * Clear any interrupt cause that happened while sending
734f988d640SKalle Valo * firmware/initializing card
735f988d640SKalle Valo */
736f988d640SKalle Valo if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
737f988d640SKalle Valo if_cs_enable_ints(card);
738f988d640SKalle Valo
739f988d640SKalle Valo /* And finally bring the card up */
740f988d640SKalle Valo priv->fw_ready = 1;
741f988d640SKalle Valo if (lbs_start_card(priv) != 0) {
742f988d640SKalle Valo pr_err("could not activate card\n");
743f988d640SKalle Valo free_irq(card->p_dev->irq, card);
744f988d640SKalle Valo }
745f988d640SKalle Valo }
746f988d640SKalle Valo
747f988d640SKalle Valo
748f988d640SKalle Valo /********************************************************************/
749f988d640SKalle Valo /* Callback functions for libertas.ko */
750f988d640SKalle Valo /********************************************************************/
751f988d640SKalle Valo
752f988d640SKalle Valo /* Send commands or data packets to the card */
if_cs_host_to_card(struct lbs_private * priv,u8 type,u8 * buf,u16 nb)753f988d640SKalle Valo static int if_cs_host_to_card(struct lbs_private *priv,
754f988d640SKalle Valo u8 type,
755f988d640SKalle Valo u8 *buf,
756f988d640SKalle Valo u16 nb)
757f988d640SKalle Valo {
758f988d640SKalle Valo int ret = -1;
759f988d640SKalle Valo
760f988d640SKalle Valo switch (type) {
761f988d640SKalle Valo case MVMS_DAT:
762f988d640SKalle Valo priv->dnld_sent = DNLD_DATA_SENT;
763f988d640SKalle Valo if_cs_send_data(priv, buf, nb);
764f988d640SKalle Valo ret = 0;
765f988d640SKalle Valo break;
766f988d640SKalle Valo case MVMS_CMD:
767f988d640SKalle Valo priv->dnld_sent = DNLD_CMD_SENT;
768f988d640SKalle Valo ret = if_cs_send_cmd(priv, buf, nb);
769f988d640SKalle Valo break;
770f988d640SKalle Valo default:
771f988d640SKalle Valo netdev_err(priv->dev, "%s: unsupported type %d\n",
772f988d640SKalle Valo __func__, type);
773f988d640SKalle Valo }
774f988d640SKalle Valo
775f988d640SKalle Valo return ret;
776f988d640SKalle Valo }
777f988d640SKalle Valo
778f988d640SKalle Valo
if_cs_release(struct pcmcia_device * p_dev)779f988d640SKalle Valo static void if_cs_release(struct pcmcia_device *p_dev)
780f988d640SKalle Valo {
781f988d640SKalle Valo struct if_cs_card *card = p_dev->priv;
782f988d640SKalle Valo
783f988d640SKalle Valo free_irq(p_dev->irq, card);
784f988d640SKalle Valo pcmcia_disable_device(p_dev);
785f988d640SKalle Valo if (card->iobase)
786f988d640SKalle Valo ioport_unmap(card->iobase);
787f988d640SKalle Valo }
788f988d640SKalle Valo
789f988d640SKalle Valo
if_cs_ioprobe(struct pcmcia_device * p_dev,void * priv_data)790f988d640SKalle Valo static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
791f988d640SKalle Valo {
792f988d640SKalle Valo p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
793f988d640SKalle Valo p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
794f988d640SKalle Valo
795f988d640SKalle Valo if (p_dev->resource[1]->end) {
796f988d640SKalle Valo pr_err("wrong CIS (check number of IO windows)\n");
797f988d640SKalle Valo return -ENODEV;
798f988d640SKalle Valo }
799f988d640SKalle Valo
800f988d640SKalle Valo /* This reserves IO space but doesn't actually enable it */
801f988d640SKalle Valo return pcmcia_request_io(p_dev);
802f988d640SKalle Valo }
803f988d640SKalle Valo
if_cs_probe(struct pcmcia_device * p_dev)804f988d640SKalle Valo static int if_cs_probe(struct pcmcia_device *p_dev)
805f988d640SKalle Valo {
806f988d640SKalle Valo int ret = -ENOMEM;
807f988d640SKalle Valo unsigned int prod_id;
808f988d640SKalle Valo struct lbs_private *priv;
809f988d640SKalle Valo struct if_cs_card *card;
810f988d640SKalle Valo
811f988d640SKalle Valo card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL);
812f988d640SKalle Valo if (!card)
813f988d640SKalle Valo goto out;
814f988d640SKalle Valo
815f988d640SKalle Valo card->p_dev = p_dev;
816f988d640SKalle Valo p_dev->priv = card;
817f988d640SKalle Valo
818f988d640SKalle Valo p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
819f988d640SKalle Valo
820f988d640SKalle Valo if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
821f988d640SKalle Valo pr_err("error in pcmcia_loop_config\n");
822f988d640SKalle Valo goto out1;
823f988d640SKalle Valo }
824f988d640SKalle Valo
825f988d640SKalle Valo /*
826f988d640SKalle Valo * Allocate an interrupt line. Note that this does not assign
827f988d640SKalle Valo * a handler to the interrupt, unless the 'Handler' member of
828f988d640SKalle Valo * the irq structure is initialized.
829f988d640SKalle Valo */
830f988d640SKalle Valo if (!p_dev->irq)
831f988d640SKalle Valo goto out1;
832f988d640SKalle Valo
833f988d640SKalle Valo /* Initialize io access */
834f988d640SKalle Valo card->iobase = ioport_map(p_dev->resource[0]->start,
835f988d640SKalle Valo resource_size(p_dev->resource[0]));
836f988d640SKalle Valo if (!card->iobase) {
837f988d640SKalle Valo pr_err("error in ioport_map\n");
838f988d640SKalle Valo ret = -EIO;
839f988d640SKalle Valo goto out1;
840f988d640SKalle Valo }
841f988d640SKalle Valo
842f988d640SKalle Valo ret = pcmcia_enable_device(p_dev);
843f988d640SKalle Valo if (ret) {
844f988d640SKalle Valo pr_err("error in pcmcia_enable_device\n");
845f988d640SKalle Valo goto out2;
846f988d640SKalle Valo }
847f988d640SKalle Valo
848f988d640SKalle Valo /* Finally, report what we've done */
849f988d640SKalle Valo lbs_deb_cs("irq %d, io %pR", p_dev->irq, p_dev->resource[0]);
850f988d640SKalle Valo
851f988d640SKalle Valo /*
852f988d640SKalle Valo * Most of the libertas cards can do unaligned register access, but some
853f988d640SKalle Valo * weird ones cannot. That's especially true for the CF8305 card.
854f988d640SKalle Valo */
855f988d640SKalle Valo card->align_regs = false;
856f988d640SKalle Valo
857f988d640SKalle Valo card->model = get_model(p_dev->manf_id, p_dev->card_id);
858f988d640SKalle Valo if (card->model == MODEL_UNKNOWN) {
859f988d640SKalle Valo pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n",
860f988d640SKalle Valo p_dev->manf_id, p_dev->card_id);
861f988d640SKalle Valo ret = -ENODEV;
862f988d640SKalle Valo goto out2;
863f988d640SKalle Valo }
864f988d640SKalle Valo
865f988d640SKalle Valo /* Check if we have a current silicon */
866f988d640SKalle Valo prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
867f988d640SKalle Valo if (card->model == MODEL_8305) {
868f988d640SKalle Valo card->align_regs = true;
869f988d640SKalle Valo if (prod_id < IF_CS_CF8305_B1_REV) {
870f988d640SKalle Valo pr_err("8305 rev B0 and older are not supported\n");
871f988d640SKalle Valo ret = -ENODEV;
872f988d640SKalle Valo goto out2;
873f988d640SKalle Valo }
874f988d640SKalle Valo }
875f988d640SKalle Valo
876f988d640SKalle Valo if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) {
877f988d640SKalle Valo pr_err("8381 rev B2 and older are not supported\n");
878f988d640SKalle Valo ret = -ENODEV;
879f988d640SKalle Valo goto out2;
880f988d640SKalle Valo }
881f988d640SKalle Valo
882f988d640SKalle Valo if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) {
883f988d640SKalle Valo pr_err("8385 rev B0 and older are not supported\n");
884f988d640SKalle Valo ret = -ENODEV;
885f988d640SKalle Valo goto out2;
886f988d640SKalle Valo }
887f988d640SKalle Valo
888f988d640SKalle Valo /* Make this card known to the libertas driver */
889f988d640SKalle Valo priv = lbs_add_card(card, &p_dev->dev);
890bbc2a101SLubomir Rintel if (IS_ERR(priv)) {
891bbc2a101SLubomir Rintel ret = PTR_ERR(priv);
892f988d640SKalle Valo goto out2;
893f988d640SKalle Valo }
894f988d640SKalle Valo
895f988d640SKalle Valo /* Set up fields in lbs_private */
896f988d640SKalle Valo card->priv = priv;
897f988d640SKalle Valo priv->card = card;
898f988d640SKalle Valo priv->hw_host_to_card = if_cs_host_to_card;
899f988d640SKalle Valo priv->enter_deep_sleep = NULL;
900f988d640SKalle Valo priv->exit_deep_sleep = NULL;
901f988d640SKalle Valo priv->reset_deep_sleep_wakeup = NULL;
902f988d640SKalle Valo
903f988d640SKalle Valo /* Get firmware */
904f988d640SKalle Valo ret = lbs_get_firmware_async(priv, &p_dev->dev, card->model, fw_table,
905f988d640SKalle Valo if_cs_prog_firmware);
906f988d640SKalle Valo if (ret) {
907f988d640SKalle Valo pr_err("failed to find firmware (%d)\n", ret);
908f988d640SKalle Valo goto out3;
909f988d640SKalle Valo }
910f988d640SKalle Valo
911f988d640SKalle Valo goto out;
912f988d640SKalle Valo
913f988d640SKalle Valo out3:
914f988d640SKalle Valo lbs_remove_card(priv);
915f988d640SKalle Valo out2:
916f988d640SKalle Valo ioport_unmap(card->iobase);
917f988d640SKalle Valo out1:
918f988d640SKalle Valo pcmcia_disable_device(p_dev);
919f988d640SKalle Valo out:
920f988d640SKalle Valo return ret;
921f988d640SKalle Valo }
922f988d640SKalle Valo
923f988d640SKalle Valo
if_cs_detach(struct pcmcia_device * p_dev)924f988d640SKalle Valo static void if_cs_detach(struct pcmcia_device *p_dev)
925f988d640SKalle Valo {
926f988d640SKalle Valo struct if_cs_card *card = p_dev->priv;
927f988d640SKalle Valo
928f988d640SKalle Valo lbs_stop_card(card->priv);
929f988d640SKalle Valo lbs_remove_card(card->priv);
930f988d640SKalle Valo if_cs_disable_ints(card);
931f988d640SKalle Valo if_cs_release(p_dev);
932f988d640SKalle Valo kfree(card);
933f988d640SKalle Valo }
934f988d640SKalle Valo
935f988d640SKalle Valo
936f988d640SKalle Valo
937f988d640SKalle Valo /********************************************************************/
938f988d640SKalle Valo /* Module initialization */
939f988d640SKalle Valo /********************************************************************/
940f988d640SKalle Valo
941f988d640SKalle Valo static const struct pcmcia_device_id if_cs_ids[] = {
942f988d640SKalle Valo PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID),
943f988d640SKalle Valo PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
944f988d640SKalle Valo PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
945f988d640SKalle Valo /* NOTE: keep in sync with get_model() */
946f988d640SKalle Valo PCMCIA_DEVICE_NULL,
947f988d640SKalle Valo };
948f988d640SKalle Valo MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
949f988d640SKalle Valo
950f988d640SKalle Valo static struct pcmcia_driver lbs_driver = {
951f988d640SKalle Valo .owner = THIS_MODULE,
952f988d640SKalle Valo .name = DRV_NAME,
953f988d640SKalle Valo .probe = if_cs_probe,
954f988d640SKalle Valo .remove = if_cs_detach,
955f988d640SKalle Valo .id_table = if_cs_ids,
956f988d640SKalle Valo };
957f988d640SKalle Valo module_pcmcia_driver(lbs_driver);
958