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