root/drivers/net/wireless/intersil/hostap/hostap_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hfa384x_outb_debug
  2. hfa384x_inb_debug
  3. hfa384x_outw_debug
  4. hfa384x_inw_debug
  5. hfa384x_outb
  6. hfa384x_inb
  7. hfa384x_outw
  8. hfa384x_inw
  9. hfa384x_from_bap
  10. hfa384x_to_bap
  11. prism2_pci_cor_sreset
  12. prism2_pci_genesis_reset
  13. prism2_pci_probe
  14. prism2_pci_remove
  15. prism2_pci_suspend
  16. prism2_pci_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 #define PRISM2_PCI
   3 
   4 /* Host AP driver's support for Intersil Prism2.5 PCI cards is based on
   5  * driver patches from Reyk Floeter <reyk@vantronix.net> and
   6  * Andy Warner <andyw@pobox.com> */
   7 
   8 #include <linux/module.h>
   9 #include <linux/if.h>
  10 #include <linux/skbuff.h>
  11 #include <linux/netdevice.h>
  12 #include <linux/slab.h>
  13 #include <linux/workqueue.h>
  14 #include <linux/wireless.h>
  15 #include <net/iw_handler.h>
  16 
  17 #include <linux/ioport.h>
  18 #include <linux/pci.h>
  19 #include <asm/io.h>
  20 
  21 #include "hostap_wlan.h"
  22 
  23 
  24 static char *dev_info = "hostap_pci";
  25 
  26 
  27 MODULE_AUTHOR("Jouni Malinen");
  28 MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
  29                    "PCI cards.");
  30 MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
  31 MODULE_LICENSE("GPL");
  32 
  33 
  34 /* struct local_info::hw_priv */
  35 struct hostap_pci_priv {
  36         void __iomem *mem_start;
  37 };
  38 
  39 
  40 /* FIX: do we need mb/wmb/rmb with memory operations? */
  41 
  42 
  43 static const struct pci_device_id prism2_pci_id_table[] = {
  44         /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
  45         { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
  46         /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
  47         { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
  48         /* Samsung MagicLAN SWL-2210P */
  49         { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
  50         { 0 }
  51 };
  52 
  53 
  54 #ifdef PRISM2_IO_DEBUG
  55 
  56 static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
  57 {
  58         struct hostap_interface *iface;
  59         struct hostap_pci_priv *hw_priv;
  60         local_info_t *local;
  61         unsigned long flags;
  62 
  63         iface = netdev_priv(dev);
  64         local = iface->local;
  65         hw_priv = local->hw_priv;
  66 
  67         spin_lock_irqsave(&local->lock, flags);
  68         prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
  69         writeb(v, hw_priv->mem_start + a);
  70         spin_unlock_irqrestore(&local->lock, flags);
  71 }
  72 
  73 static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
  74 {
  75         struct hostap_interface *iface;
  76         struct hostap_pci_priv *hw_priv;
  77         local_info_t *local;
  78         unsigned long flags;
  79         u8 v;
  80 
  81         iface = netdev_priv(dev);
  82         local = iface->local;
  83         hw_priv = local->hw_priv;
  84 
  85         spin_lock_irqsave(&local->lock, flags);
  86         v = readb(hw_priv->mem_start + a);
  87         prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
  88         spin_unlock_irqrestore(&local->lock, flags);
  89         return v;
  90 }
  91 
  92 static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
  93 {
  94         struct hostap_interface *iface;
  95         struct hostap_pci_priv *hw_priv;
  96         local_info_t *local;
  97         unsigned long flags;
  98 
  99         iface = netdev_priv(dev);
 100         local = iface->local;
 101         hw_priv = local->hw_priv;
 102 
 103         spin_lock_irqsave(&local->lock, flags);
 104         prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
 105         writew(v, hw_priv->mem_start + a);
 106         spin_unlock_irqrestore(&local->lock, flags);
 107 }
 108 
 109 static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
 110 {
 111         struct hostap_interface *iface;
 112         struct hostap_pci_priv *hw_priv;
 113         local_info_t *local;
 114         unsigned long flags;
 115         u16 v;
 116 
 117         iface = netdev_priv(dev);
 118         local = iface->local;
 119         hw_priv = local->hw_priv;
 120 
 121         spin_lock_irqsave(&local->lock, flags);
 122         v = readw(hw_priv->mem_start + a);
 123         prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
 124         spin_unlock_irqrestore(&local->lock, flags);
 125         return v;
 126 }
 127 
 128 #define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
 129 #define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
 130 #define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
 131 #define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
 132 #define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), le16_to_cpu((v)))
 133 #define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw_debug(dev, (a)))
 134 
 135 #else /* PRISM2_IO_DEBUG */
 136 
 137 static inline void hfa384x_outb(struct net_device *dev, int a, u8 v)
 138 {
 139         struct hostap_interface *iface;
 140         struct hostap_pci_priv *hw_priv;
 141         iface = netdev_priv(dev);
 142         hw_priv = iface->local->hw_priv;
 143         writeb(v, hw_priv->mem_start + a);
 144 }
 145 
 146 static inline u8 hfa384x_inb(struct net_device *dev, int a)
 147 {
 148         struct hostap_interface *iface;
 149         struct hostap_pci_priv *hw_priv;
 150         iface = netdev_priv(dev);
 151         hw_priv = iface->local->hw_priv;
 152         return readb(hw_priv->mem_start + a);
 153 }
 154 
 155 static inline void hfa384x_outw(struct net_device *dev, int a, u16 v)
 156 {
 157         struct hostap_interface *iface;
 158         struct hostap_pci_priv *hw_priv;
 159         iface = netdev_priv(dev);
 160         hw_priv = iface->local->hw_priv;
 161         writew(v, hw_priv->mem_start + a);
 162 }
 163 
 164 static inline u16 hfa384x_inw(struct net_device *dev, int a)
 165 {
 166         struct hostap_interface *iface;
 167         struct hostap_pci_priv *hw_priv;
 168         iface = netdev_priv(dev);
 169         hw_priv = iface->local->hw_priv;
 170         return readw(hw_priv->mem_start + a);
 171 }
 172 
 173 #define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v))
 174 #define HFA384X_INB(a) hfa384x_inb(dev, (a))
 175 #define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
 176 #define HFA384X_INW(a) hfa384x_inw(dev, (a))
 177 #define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), le16_to_cpu((v)))
 178 #define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw(dev, (a)))
 179 
 180 #endif /* PRISM2_IO_DEBUG */
 181 
 182 
 183 static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
 184                             int len)
 185 {
 186         u16 d_off;
 187         __le16 *pos;
 188 
 189         d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
 190         pos = (__le16 *) buf;
 191 
 192         for ( ; len > 1; len -= 2)
 193                 *pos++ = HFA384X_INW_DATA(d_off);
 194 
 195         if (len & 1)
 196                 *((char *) pos) = HFA384X_INB(d_off);
 197 
 198         return 0;
 199 }
 200 
 201 
 202 static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
 203 {
 204         u16 d_off;
 205         __le16 *pos;
 206 
 207         d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
 208         pos = (__le16 *) buf;
 209 
 210         for ( ; len > 1; len -= 2)
 211                 HFA384X_OUTW_DATA(*pos++, d_off);
 212 
 213         if (len & 1)
 214                 HFA384X_OUTB(*((char *) pos), d_off);
 215 
 216         return 0;
 217 }
 218 
 219 
 220 /* FIX: This might change at some point.. */
 221 #include "hostap_hw.c"
 222 
 223 static void prism2_pci_cor_sreset(local_info_t *local)
 224 {
 225         struct net_device *dev = local->dev;
 226         u16 reg;
 227 
 228         reg = HFA384X_INB(HFA384X_PCICOR_OFF);
 229         printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg);
 230 
 231         /* linux-wlan-ng uses extremely long hold and settle times for
 232          * COR sreset. A comment in the driver code mentions that the long
 233          * delays appear to be necessary. However, at least IBM 22P6901 seems
 234          * to work fine with shorter delays.
 235          *
 236          * Longer delays can be configured by uncommenting following line: */
 237 /* #define PRISM2_PCI_USE_LONG_DELAYS */
 238 
 239 #ifdef PRISM2_PCI_USE_LONG_DELAYS
 240         int i;
 241 
 242         HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
 243         mdelay(250);
 244 
 245         HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
 246         mdelay(500);
 247 
 248         /* Wait for f/w to complete initialization (CMD:BUSY == 0) */
 249         i = 2000000 / 10;
 250         while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i)
 251                 udelay(10);
 252 
 253 #else /* PRISM2_PCI_USE_LONG_DELAYS */
 254 
 255         HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
 256         mdelay(2);
 257         HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
 258         mdelay(2);
 259 
 260 #endif /* PRISM2_PCI_USE_LONG_DELAYS */
 261 
 262         if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) {
 263                 printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name);
 264         }
 265 }
 266 
 267 
 268 static void prism2_pci_genesis_reset(local_info_t *local, int hcr)
 269 {
 270         struct net_device *dev = local->dev;
 271 
 272         HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF);
 273         mdelay(10);
 274         HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF);
 275         mdelay(10);
 276         HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF);
 277         mdelay(10);
 278 }
 279 
 280 
 281 static struct prism2_helper_functions prism2_pci_funcs =
 282 {
 283         .card_present   = NULL,
 284         .cor_sreset     = prism2_pci_cor_sreset,
 285         .genesis_reset  = prism2_pci_genesis_reset,
 286         .hw_type        = HOSTAP_HW_PCI,
 287 };
 288 
 289 
 290 static int prism2_pci_probe(struct pci_dev *pdev,
 291                             const struct pci_device_id *id)
 292 {
 293         unsigned long phymem;
 294         void __iomem *mem = NULL;
 295         local_info_t *local = NULL;
 296         struct net_device *dev = NULL;
 297         static int cards_found /* = 0 */;
 298         int irq_registered = 0;
 299         struct hostap_interface *iface;
 300         struct hostap_pci_priv *hw_priv;
 301 
 302         hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
 303         if (hw_priv == NULL)
 304                 return -ENOMEM;
 305 
 306         if (pci_enable_device(pdev))
 307                 goto err_out_free;
 308 
 309         phymem = pci_resource_start(pdev, 0);
 310 
 311         if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
 312                 printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
 313                 goto err_out_disable;
 314         }
 315 
 316         mem = pci_ioremap_bar(pdev, 0);
 317         if (mem == NULL) {
 318                 printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
 319                 goto fail;
 320         }
 321 
 322         dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
 323                                      &pdev->dev);
 324         if (dev == NULL)
 325                 goto fail;
 326         iface = netdev_priv(dev);
 327         local = iface->local;
 328         local->hw_priv = hw_priv;
 329         cards_found++;
 330 
 331         dev->irq = pdev->irq;
 332         hw_priv->mem_start = mem;
 333         dev->base_addr = (unsigned long) mem;
 334 
 335         prism2_pci_cor_sreset(local);
 336 
 337         pci_set_drvdata(pdev, dev);
 338 
 339         if (request_irq(dev->irq, prism2_interrupt, IRQF_SHARED, dev->name,
 340                         dev)) {
 341                 printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
 342                 goto fail;
 343         } else
 344                 irq_registered = 1;
 345 
 346         if (!local->pri_only && prism2_hw_config(dev, 1)) {
 347                 printk(KERN_DEBUG "%s: hardware initialization failed\n",
 348                        dev_info);
 349                 goto fail;
 350         }
 351 
 352         printk(KERN_INFO "%s: Intersil Prism2.5 PCI: "
 353                "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq);
 354 
 355         return hostap_hw_ready(dev);
 356 
 357  fail:
 358         if (irq_registered && dev)
 359                 free_irq(dev->irq, dev);
 360 
 361         if (mem)
 362                 iounmap(mem);
 363 
 364         release_mem_region(phymem, pci_resource_len(pdev, 0));
 365 
 366  err_out_disable:
 367         pci_disable_device(pdev);
 368         prism2_free_local_data(dev);
 369 
 370  err_out_free:
 371         kfree(hw_priv);
 372 
 373         return -ENODEV;
 374 }
 375 
 376 
 377 static void prism2_pci_remove(struct pci_dev *pdev)
 378 {
 379         struct net_device *dev;
 380         struct hostap_interface *iface;
 381         void __iomem *mem_start;
 382         struct hostap_pci_priv *hw_priv;
 383 
 384         dev = pci_get_drvdata(pdev);
 385         iface = netdev_priv(dev);
 386         hw_priv = iface->local->hw_priv;
 387 
 388         /* Reset the hardware, and ensure interrupts are disabled. */
 389         prism2_pci_cor_sreset(iface->local);
 390         hfa384x_disable_interrupts(dev);
 391 
 392         if (dev->irq)
 393                 free_irq(dev->irq, dev);
 394 
 395         mem_start = hw_priv->mem_start;
 396         prism2_free_local_data(dev);
 397         kfree(hw_priv);
 398 
 399         iounmap(mem_start);
 400 
 401         release_mem_region(pci_resource_start(pdev, 0),
 402                            pci_resource_len(pdev, 0));
 403         pci_disable_device(pdev);
 404 }
 405 
 406 
 407 #ifdef CONFIG_PM
 408 static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 409 {
 410         struct net_device *dev = pci_get_drvdata(pdev);
 411 
 412         if (netif_running(dev)) {
 413                 netif_stop_queue(dev);
 414                 netif_device_detach(dev);
 415         }
 416         prism2_suspend(dev);
 417         pci_save_state(pdev);
 418         pci_disable_device(pdev);
 419         pci_set_power_state(pdev, PCI_D3hot);
 420 
 421         return 0;
 422 }
 423 
 424 static int prism2_pci_resume(struct pci_dev *pdev)
 425 {
 426         struct net_device *dev = pci_get_drvdata(pdev);
 427         int err;
 428 
 429         err = pci_enable_device(pdev);
 430         if (err) {
 431                 printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
 432                        dev->name);
 433                 return err;
 434         }
 435         pci_restore_state(pdev);
 436         prism2_hw_config(dev, 0);
 437         if (netif_running(dev)) {
 438                 netif_device_attach(dev);
 439                 netif_start_queue(dev);
 440         }
 441 
 442         return 0;
 443 }
 444 #endif /* CONFIG_PM */
 445 
 446 
 447 MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
 448 
 449 static struct pci_driver prism2_pci_driver = {
 450         .name           = "hostap_pci",
 451         .id_table       = prism2_pci_id_table,
 452         .probe          = prism2_pci_probe,
 453         .remove         = prism2_pci_remove,
 454 #ifdef CONFIG_PM
 455         .suspend        = prism2_pci_suspend,
 456         .resume         = prism2_pci_resume,
 457 #endif /* CONFIG_PM */
 458 };
 459 
 460 module_pci_driver(prism2_pci_driver);

/* [<][>][^][v][top][bottom][index][help] */