diff options
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r-- | drivers/net/wireless/libertas/if_cs.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index f658fd6a2c0c..62381768f2d5 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -59,6 +59,7 @@ struct if_cs_card { | |||
59 | struct pcmcia_device *p_dev; | 59 | struct pcmcia_device *p_dev; |
60 | struct lbs_private *priv; | 60 | struct lbs_private *priv; |
61 | void __iomem *iobase; | 61 | void __iomem *iobase; |
62 | bool align_regs; | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | 65 | ||
@@ -274,16 +275,25 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
274 | #define IF_CS_PRODUCT_ID 0x0000001C | 275 | #define IF_CS_PRODUCT_ID 0x0000001C |
275 | #define IF_CS_CF8385_B1_REV 0x12 | 276 | #define IF_CS_CF8385_B1_REV 0x12 |
276 | #define IF_CS_CF8381_B3_REV 0x04 | 277 | #define IF_CS_CF8381_B3_REV 0x04 |
278 | #define IF_CS_CF8305_B1_REV 0x03 | ||
277 | 279 | ||
278 | /* | 280 | /* |
279 | * Used to detect other cards than CF8385 since their revisions of silicon | 281 | * Used to detect other cards than CF8385 since their revisions of silicon |
280 | * doesn't match those from CF8385, eg. CF8381 B3 works with this driver. | 282 | * doesn't match those from CF8385, eg. CF8381 B3 works with this driver. |
281 | */ | 283 | */ |
284 | #define CF8305_MANFID 0x02db | ||
285 | #define CF8305_CARDID 0x8103 | ||
282 | #define CF8381_MANFID 0x02db | 286 | #define CF8381_MANFID 0x02db |
283 | #define CF8381_CARDID 0x6064 | 287 | #define CF8381_CARDID 0x6064 |
284 | #define CF8385_MANFID 0x02df | 288 | #define CF8385_MANFID 0x02df |
285 | #define CF8385_CARDID 0x8103 | 289 | #define CF8385_CARDID 0x8103 |
286 | 290 | ||
291 | static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) | ||
292 | { | ||
293 | return (p_dev->manf_id == CF8305_MANFID && | ||
294 | p_dev->card_id == CF8305_CARDID); | ||
295 | } | ||
296 | |||
287 | static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) | 297 | static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) |
288 | { | 298 | { |
289 | return (p_dev->manf_id == CF8381_MANFID && | 299 | return (p_dev->manf_id == CF8381_MANFID && |
@@ -556,7 +566,15 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
556 | 566 | ||
557 | lbs_deb_enter(LBS_DEB_CS); | 567 | lbs_deb_enter(LBS_DEB_CS); |
558 | 568 | ||
559 | scratch = if_cs_read8(card, IF_CS_SCRATCH); | 569 | /* |
570 | * This is the only place where an unaligned register access happens on | ||
571 | * the CF8305 card, therefore for the sake of speed of the driver, we do | ||
572 | * the alignment correction here. | ||
573 | */ | ||
574 | if (card->align_regs) | ||
575 | scratch = if_cs_read16(card, IF_CS_SCRATCH) >> 8; | ||
576 | else | ||
577 | scratch = if_cs_read8(card, IF_CS_SCRATCH); | ||
560 | 578 | ||
561 | /* "If the value is 0x5a, the firmware is already | 579 | /* "If the value is 0x5a, the firmware is already |
562 | * downloaded successfully" | 580 | * downloaded successfully" |
@@ -880,8 +898,24 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
880 | p_dev->irq.AssignedIRQ, p_dev->io.BasePort1, | 898 | p_dev->irq.AssignedIRQ, p_dev->io.BasePort1, |
881 | p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); | 899 | p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); |
882 | 900 | ||
901 | /* | ||
902 | * Most of the libertas cards can do unaligned register access, but some | ||
903 | * weird ones can not. That's especially true for the CF8305 card. | ||
904 | */ | ||
905 | card->align_regs = 0; | ||
906 | |||
883 | /* Check if we have a current silicon */ | 907 | /* Check if we have a current silicon */ |
884 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); | 908 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); |
909 | if (if_cs_hw_is_cf8305(p_dev)) { | ||
910 | card->align_regs = 1; | ||
911 | if (prod_id < IF_CS_CF8305_B1_REV) { | ||
912 | lbs_pr_err("old chips like 8305 rev B3 " | ||
913 | "aren't supported\n"); | ||
914 | ret = -ENODEV; | ||
915 | goto out2; | ||
916 | } | ||
917 | } | ||
918 | |||
885 | if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { | 919 | if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { |
886 | lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); | 920 | lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); |
887 | ret = -ENODEV; | 921 | ret = -ENODEV; |
@@ -896,7 +930,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
896 | 930 | ||
897 | /* Load the firmware early, before calling into libertas.ko */ | 931 | /* Load the firmware early, before calling into libertas.ko */ |
898 | ret = if_cs_prog_helper(card); | 932 | ret = if_cs_prog_helper(card); |
899 | if (ret == 0) | 933 | if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) |
900 | ret = if_cs_prog_real(card); | 934 | ret = if_cs_prog_real(card); |
901 | if (ret) | 935 | if (ret) |
902 | goto out2; | 936 | goto out2; |
@@ -976,6 +1010,7 @@ static void if_cs_detach(struct pcmcia_device *p_dev) | |||
976 | /********************************************************************/ | 1010 | /********************************************************************/ |
977 | 1011 | ||
978 | static struct pcmcia_device_id if_cs_ids[] = { | 1012 | static struct pcmcia_device_id if_cs_ids[] = { |
1013 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), | ||
979 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), | 1014 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), |
980 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), | 1015 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), |
981 | PCMCIA_DEVICE_NULL, | 1016 | PCMCIA_DEVICE_NULL, |