Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #define PRISM2_PCI
0003 
0004 /* Host AP driver's support for Intersil Prism2.5 PCI cards is based on
0005  * driver patches from Reyk Floeter <reyk@vantronix.net> and
0006  * Andy Warner <andyw@pobox.com> */
0007 
0008 #include <linux/module.h>
0009 #include <linux/if.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/netdevice.h>
0012 #include <linux/slab.h>
0013 #include <linux/workqueue.h>
0014 #include <linux/wireless.h>
0015 #include <net/iw_handler.h>
0016 
0017 #include <linux/ioport.h>
0018 #include <linux/pci.h>
0019 #include <asm/io.h>
0020 
0021 #include "hostap_wlan.h"
0022 
0023 
0024 static char *dev_info = "hostap_pci";
0025 
0026 
0027 MODULE_AUTHOR("Jouni Malinen");
0028 MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
0029            "PCI cards.");
0030 MODULE_LICENSE("GPL");
0031 
0032 
0033 /* struct local_info::hw_priv */
0034 struct hostap_pci_priv {
0035     void __iomem *mem_start;
0036 };
0037 
0038 
0039 /* FIX: do we need mb/wmb/rmb with memory operations? */
0040 
0041 
0042 static const struct pci_device_id prism2_pci_id_table[] = {
0043     /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
0044     { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
0045     /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
0046     { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
0047     /* Samsung MagicLAN SWL-2210P */
0048     { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
0049     { 0 }
0050 };
0051 
0052 
0053 #ifdef PRISM2_IO_DEBUG
0054 
0055 static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
0056 {
0057     struct hostap_interface *iface;
0058     struct hostap_pci_priv *hw_priv;
0059     local_info_t *local;
0060     unsigned long flags;
0061 
0062     iface = netdev_priv(dev);
0063     local = iface->local;
0064     hw_priv = local->hw_priv;
0065 
0066     spin_lock_irqsave(&local->lock, flags);
0067     prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
0068     writeb(v, hw_priv->mem_start + a);
0069     spin_unlock_irqrestore(&local->lock, flags);
0070 }
0071 
0072 static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
0073 {
0074     struct hostap_interface *iface;
0075     struct hostap_pci_priv *hw_priv;
0076     local_info_t *local;
0077     unsigned long flags;
0078     u8 v;
0079 
0080     iface = netdev_priv(dev);
0081     local = iface->local;
0082     hw_priv = local->hw_priv;
0083 
0084     spin_lock_irqsave(&local->lock, flags);
0085     v = readb(hw_priv->mem_start + a);
0086     prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
0087     spin_unlock_irqrestore(&local->lock, flags);
0088     return v;
0089 }
0090 
0091 static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
0092 {
0093     struct hostap_interface *iface;
0094     struct hostap_pci_priv *hw_priv;
0095     local_info_t *local;
0096     unsigned long flags;
0097 
0098     iface = netdev_priv(dev);
0099     local = iface->local;
0100     hw_priv = local->hw_priv;
0101 
0102     spin_lock_irqsave(&local->lock, flags);
0103     prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
0104     writew(v, hw_priv->mem_start + a);
0105     spin_unlock_irqrestore(&local->lock, flags);
0106 }
0107 
0108 static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
0109 {
0110     struct hostap_interface *iface;
0111     struct hostap_pci_priv *hw_priv;
0112     local_info_t *local;
0113     unsigned long flags;
0114     u16 v;
0115 
0116     iface = netdev_priv(dev);
0117     local = iface->local;
0118     hw_priv = local->hw_priv;
0119 
0120     spin_lock_irqsave(&local->lock, flags);
0121     v = readw(hw_priv->mem_start + a);
0122     prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
0123     spin_unlock_irqrestore(&local->lock, flags);
0124     return v;
0125 }
0126 
0127 #define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
0128 #define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
0129 #define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
0130 #define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
0131 #define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), le16_to_cpu((v)))
0132 #define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw_debug(dev, (a)))
0133 
0134 #else /* PRISM2_IO_DEBUG */
0135 
0136 static inline void hfa384x_outb(struct net_device *dev, int a, u8 v)
0137 {
0138     struct hostap_interface *iface;
0139     struct hostap_pci_priv *hw_priv;
0140     iface = netdev_priv(dev);
0141     hw_priv = iface->local->hw_priv;
0142     writeb(v, hw_priv->mem_start + a);
0143 }
0144 
0145 static inline u8 hfa384x_inb(struct net_device *dev, int a)
0146 {
0147     struct hostap_interface *iface;
0148     struct hostap_pci_priv *hw_priv;
0149     iface = netdev_priv(dev);
0150     hw_priv = iface->local->hw_priv;
0151     return readb(hw_priv->mem_start + a);
0152 }
0153 
0154 static inline void hfa384x_outw(struct net_device *dev, int a, u16 v)
0155 {
0156     struct hostap_interface *iface;
0157     struct hostap_pci_priv *hw_priv;
0158     iface = netdev_priv(dev);
0159     hw_priv = iface->local->hw_priv;
0160     writew(v, hw_priv->mem_start + a);
0161 }
0162 
0163 static inline u16 hfa384x_inw(struct net_device *dev, int a)
0164 {
0165     struct hostap_interface *iface;
0166     struct hostap_pci_priv *hw_priv;
0167     iface = netdev_priv(dev);
0168     hw_priv = iface->local->hw_priv;
0169     return readw(hw_priv->mem_start + a);
0170 }
0171 
0172 #define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v))
0173 #define HFA384X_INB(a) hfa384x_inb(dev, (a))
0174 #define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
0175 #define HFA384X_INW(a) hfa384x_inw(dev, (a))
0176 #define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), le16_to_cpu((v)))
0177 #define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw(dev, (a)))
0178 
0179 #endif /* PRISM2_IO_DEBUG */
0180 
0181 
0182 static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
0183                 int len)
0184 {
0185     u16 d_off;
0186     __le16 *pos;
0187 
0188     d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
0189     pos = (__le16 *) buf;
0190 
0191     for ( ; len > 1; len -= 2)
0192         *pos++ = HFA384X_INW_DATA(d_off);
0193 
0194     if (len & 1)
0195         *((char *) pos) = HFA384X_INB(d_off);
0196 
0197     return 0;
0198 }
0199 
0200 
0201 static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
0202 {
0203     u16 d_off;
0204     __le16 *pos;
0205 
0206     d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
0207     pos = (__le16 *) buf;
0208 
0209     for ( ; len > 1; len -= 2)
0210         HFA384X_OUTW_DATA(*pos++, d_off);
0211 
0212     if (len & 1)
0213         HFA384X_OUTB(*((char *) pos), d_off);
0214 
0215     return 0;
0216 }
0217 
0218 
0219 /* FIX: This might change at some point.. */
0220 #include "hostap_hw.c"
0221 
0222 static void prism2_pci_cor_sreset(local_info_t *local)
0223 {
0224     struct net_device *dev = local->dev;
0225     u16 reg;
0226 
0227     reg = HFA384X_INB(HFA384X_PCICOR_OFF);
0228     printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg);
0229 
0230     /* linux-wlan-ng uses extremely long hold and settle times for
0231      * COR sreset. A comment in the driver code mentions that the long
0232      * delays appear to be necessary. However, at least IBM 22P6901 seems
0233      * to work fine with shorter delays.
0234      *
0235      * Longer delays can be configured by uncommenting following line: */
0236 /* #define PRISM2_PCI_USE_LONG_DELAYS */
0237 
0238 #ifdef PRISM2_PCI_USE_LONG_DELAYS
0239     int i;
0240 
0241     HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
0242     mdelay(250);
0243 
0244     HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
0245     mdelay(500);
0246 
0247     /* Wait for f/w to complete initialization (CMD:BUSY == 0) */
0248     i = 2000000 / 10;
0249     while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i)
0250         udelay(10);
0251 
0252 #else /* PRISM2_PCI_USE_LONG_DELAYS */
0253 
0254     HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
0255     mdelay(2);
0256     HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
0257     mdelay(2);
0258 
0259 #endif /* PRISM2_PCI_USE_LONG_DELAYS */
0260 
0261     if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) {
0262         printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name);
0263     }
0264 }
0265 
0266 
0267 static void prism2_pci_genesis_reset(local_info_t *local, int hcr)
0268 {
0269     struct net_device *dev = local->dev;
0270 
0271     HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF);
0272     mdelay(10);
0273     HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF);
0274     mdelay(10);
0275     HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF);
0276     mdelay(10);
0277 }
0278 
0279 
0280 static struct prism2_helper_functions prism2_pci_funcs =
0281 {
0282     .card_present   = NULL,
0283     .cor_sreset = prism2_pci_cor_sreset,
0284     .genesis_reset  = prism2_pci_genesis_reset,
0285     .hw_type    = HOSTAP_HW_PCI,
0286 };
0287 
0288 
0289 static int prism2_pci_probe(struct pci_dev *pdev,
0290                 const struct pci_device_id *id)
0291 {
0292     unsigned long phymem;
0293     void __iomem *mem = NULL;
0294     local_info_t *local = NULL;
0295     struct net_device *dev = NULL;
0296     static int cards_found /* = 0 */;
0297     int irq_registered = 0;
0298     struct hostap_interface *iface;
0299     struct hostap_pci_priv *hw_priv;
0300 
0301     hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
0302     if (hw_priv == NULL)
0303         return -ENOMEM;
0304 
0305     if (pci_enable_device(pdev))
0306         goto err_out_free;
0307 
0308     phymem = pci_resource_start(pdev, 0);
0309 
0310     if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
0311         printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
0312         goto err_out_disable;
0313     }
0314 
0315     mem = pci_ioremap_bar(pdev, 0);
0316     if (mem == NULL) {
0317         printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
0318         goto fail;
0319     }
0320 
0321     dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
0322                      &pdev->dev);
0323     if (dev == NULL)
0324         goto fail;
0325     iface = netdev_priv(dev);
0326     local = iface->local;
0327     local->hw_priv = hw_priv;
0328     cards_found++;
0329 
0330         dev->irq = pdev->irq;
0331         hw_priv->mem_start = mem;
0332     dev->base_addr = (unsigned long) mem;
0333 
0334     prism2_pci_cor_sreset(local);
0335 
0336     pci_set_drvdata(pdev, dev);
0337 
0338     if (request_irq(dev->irq, prism2_interrupt, IRQF_SHARED, dev->name,
0339             dev)) {
0340         printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
0341         goto fail;
0342     } else
0343         irq_registered = 1;
0344 
0345     if (!local->pri_only && prism2_hw_config(dev, 1)) {
0346         printk(KERN_DEBUG "%s: hardware initialization failed\n",
0347                dev_info);
0348         goto fail;
0349     }
0350 
0351     printk(KERN_INFO "%s: Intersil Prism2.5 PCI: "
0352            "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq);
0353 
0354     return hostap_hw_ready(dev);
0355 
0356  fail:
0357     if (irq_registered && dev)
0358         free_irq(dev->irq, dev);
0359 
0360     if (mem)
0361         iounmap(mem);
0362 
0363     release_mem_region(phymem, pci_resource_len(pdev, 0));
0364 
0365  err_out_disable:
0366     pci_disable_device(pdev);
0367     prism2_free_local_data(dev);
0368 
0369  err_out_free:
0370     kfree(hw_priv);
0371 
0372     return -ENODEV;
0373 }
0374 
0375 
0376 static void prism2_pci_remove(struct pci_dev *pdev)
0377 {
0378     struct net_device *dev;
0379     struct hostap_interface *iface;
0380     void __iomem *mem_start;
0381     struct hostap_pci_priv *hw_priv;
0382 
0383     dev = pci_get_drvdata(pdev);
0384     iface = netdev_priv(dev);
0385     hw_priv = iface->local->hw_priv;
0386 
0387     /* Reset the hardware, and ensure interrupts are disabled. */
0388     prism2_pci_cor_sreset(iface->local);
0389     hfa384x_disable_interrupts(dev);
0390 
0391     if (dev->irq)
0392         free_irq(dev->irq, dev);
0393 
0394     mem_start = hw_priv->mem_start;
0395     prism2_free_local_data(dev);
0396     kfree(hw_priv);
0397 
0398     iounmap(mem_start);
0399 
0400     release_mem_region(pci_resource_start(pdev, 0),
0401                pci_resource_len(pdev, 0));
0402     pci_disable_device(pdev);
0403 }
0404 
0405 static int __maybe_unused prism2_pci_suspend(struct device *dev_d)
0406 {
0407     struct net_device *dev = dev_get_drvdata(dev_d);
0408 
0409     if (netif_running(dev)) {
0410         netif_stop_queue(dev);
0411         netif_device_detach(dev);
0412     }
0413     prism2_suspend(dev);
0414 
0415     return 0;
0416 }
0417 
0418 static int __maybe_unused prism2_pci_resume(struct device *dev_d)
0419 {
0420     struct net_device *dev = dev_get_drvdata(dev_d);
0421 
0422     prism2_hw_config(dev, 0);
0423     if (netif_running(dev)) {
0424         netif_device_attach(dev);
0425         netif_start_queue(dev);
0426     }
0427 
0428     return 0;
0429 }
0430 
0431 MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
0432 
0433 static SIMPLE_DEV_PM_OPS(prism2_pci_pm_ops,
0434              prism2_pci_suspend,
0435              prism2_pci_resume);
0436 
0437 static struct pci_driver prism2_pci_driver = {
0438     .name       = "hostap_pci",
0439     .id_table   = prism2_pci_id_table,
0440     .probe      = prism2_pci_probe,
0441     .remove     = prism2_pci_remove,
0442     .driver.pm  = &prism2_pci_pm_ops,
0443 };
0444 
0445 module_pci_driver(prism2_pci_driver);