1/* 2 3 Broadcom B43 wireless driver 4 5 Copyright (c) 2007 Michael Buesch <mb@bu3sch.de> 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; see the file COPYING. If not, write to 19 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 20 Boston, MA 02110-1301, USA. 21 22*/ 23 24#include "pcmcia.h" 25 26#include <linux/ssb/ssb.h> 27#include <linux/slab.h> 28 29#include <pcmcia/cs.h> 30#include <pcmcia/cistpl.h> 31#include <pcmcia/ciscode.h> 32#include <pcmcia/ds.h> 33#include <pcmcia/cisreg.h> 34 35 36static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { 37 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), 38 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), 39 PCMCIA_DEVICE_NULL, 40}; 41 42MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl); 43 44#ifdef CONFIG_PM 45static int b43_pcmcia_suspend(struct pcmcia_device *dev) 46{ 47 struct ssb_bus *ssb = dev->priv; 48 49 return ssb_bus_suspend(ssb); 50} 51 52static int b43_pcmcia_resume(struct pcmcia_device *dev) 53{ 54 struct ssb_bus *ssb = dev->priv; 55 56 return ssb_bus_resume(ssb); 57} 58#else /* CONFIG_PM */ 59# define b43_pcmcia_suspend NULL 60# define b43_pcmcia_resume NULL 61#endif /* CONFIG_PM */ 62 63static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) 64{ 65 struct ssb_bus *ssb; 66 win_req_t win; 67 int err = -ENOMEM; 68 int res = 0; 69 70 ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); 71 if (!ssb) 72 goto out_error; 73 74 err = -ENODEV; 75 76 dev->conf.Attributes = CONF_ENABLE_IRQ; 77 dev->conf.IntType = INT_MEMORY_AND_IO; 78 79 win.Attributes = WIN_ENABLE | WIN_DATA_WIDTH_16 | 80 WIN_USE_WAIT; 81 win.Base = 0; 82 win.Size = SSB_CORE_SIZE; 83 win.AccessSpeed = 250; 84 res = pcmcia_request_window(dev, &win, &dev->win); 85 if (res != 0) 86 goto err_kfree_ssb; 87 88 res = pcmcia_map_mem_page(dev, dev->win, 0); 89 if (res != 0) 90 goto err_disable; 91 92 if (!dev->irq) 93 goto err_disable; 94 95 res = pcmcia_request_configuration(dev, &dev->conf); 96 if (res != 0) 97 goto err_disable; 98 99 err = ssb_bus_pcmciabus_register(ssb, dev, win.Base); 100 if (err) 101 goto err_disable; 102 dev->priv = ssb; 103 104 return 0; 105 106err_disable: 107 pcmcia_disable_device(dev); 108err_kfree_ssb: 109 kfree(ssb); 110out_error: 111 printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", 112 res, err); 113 return err; 114} 115 116static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev) 117{ 118 struct ssb_bus *ssb = dev->priv; 119 120 ssb_bus_unregister(ssb); 121 pcmcia_disable_device(dev); 122 kfree(ssb); 123 dev->priv = NULL; 124} 125 126static struct pcmcia_driver b43_pcmcia_driver = { 127 .owner = THIS_MODULE, 128 .drv = { 129 .name = "b43-pcmcia", 130 }, 131 .id_table = b43_pcmcia_tbl, 132 .probe = b43_pcmcia_probe, 133 .remove = __devexit_p(b43_pcmcia_remove), 134 .suspend = b43_pcmcia_suspend, 135 .resume = b43_pcmcia_resume, 136}; 137 138int b43_pcmcia_init(void) 139{ 140 return pcmcia_register_driver(&b43_pcmcia_driver); 141} 142 143void b43_pcmcia_exit(void) 144{ 145 pcmcia_unregister_driver(&b43_pcmcia_driver); 146} 147