2007-09-18 15:39:42 -04:00
/*
Broadcom B43 wireless driver
Copyright ( c ) 2007 Michael Buesch < mb @ bu3sch . de >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; see the file COPYING . If not , write to
the Free Software Foundation , Inc . , 51 Franklin Steet , Fifth Floor ,
Boston , MA 02110 - 1301 , USA .
*/
2007-09-20 11:13:40 -07:00
# include "pcmcia.h"
2007-09-18 15:39:42 -04:00
# include <linux/ssb/ssb.h>
# include <pcmcia/cs_types.h>
# include <pcmcia/cs.h>
# include <pcmcia/cistpl.h>
# include <pcmcia/ciscode.h>
# include <pcmcia/ds.h>
# include <pcmcia/cisreg.h>
2007-09-20 11:13:40 -07:00
2007-09-18 15:39:42 -04:00
static /*const */ struct pcmcia_device_id b43_pcmcia_tbl [ ] = {
PCMCIA_DEVICE_MANF_CARD ( 0x2D0 , 0x448 ) ,
2009-06-30 22:39:28 -05:00
PCMCIA_DEVICE_MANF_CARD ( 0x2D0 , 0x476 ) ,
2007-09-18 15:39:42 -04:00
PCMCIA_DEVICE_NULL ,
} ;
MODULE_DEVICE_TABLE ( pcmcia , b43_pcmcia_tbl ) ;
# ifdef CONFIG_PM
static int b43_pcmcia_suspend ( struct pcmcia_device * dev )
{
2008-03-30 00:10:50 +01:00
struct ssb_bus * ssb = dev - > priv ;
return ssb_bus_suspend ( ssb ) ;
2007-09-18 15:39:42 -04:00
}
static int b43_pcmcia_resume ( struct pcmcia_device * dev )
{
2008-03-30 00:10:50 +01:00
struct ssb_bus * ssb = dev - > priv ;
return ssb_bus_resume ( ssb ) ;
2007-09-18 15:39:42 -04:00
}
# else /* CONFIG_PM */
# define b43_pcmcia_suspend NULL
# define b43_pcmcia_resume NULL
# endif /* CONFIG_PM */
static int __devinit b43_pcmcia_probe ( struct pcmcia_device * dev )
{
struct ssb_bus * ssb ;
win_req_t win ;
memreq_t mem ;
int err = - ENOMEM ;
2007-11-06 16:36:41 +01:00
int res = 0 ;
2007-09-18 15:39:42 -04:00
ssb = kzalloc ( sizeof ( * ssb ) , GFP_KERNEL ) ;
if ( ! ssb )
2007-11-06 16:36:41 +01:00
goto out_error ;
2007-09-18 15:39:42 -04:00
err = - ENODEV ;
2008-03-28 11:48:53 +01:00
dev - > conf . Attributes = CONF_ENABLE_IRQ ;
dev - > conf . IntType = INT_MEMORY_AND_IO ;
2007-09-18 15:39:42 -04:00
dev - > io . BasePort2 = 0 ;
dev - > io . NumPorts2 = 0 ;
dev - > io . Attributes2 = 0 ;
2007-11-06 16:36:41 +01:00
win . Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM |
WIN_ENABLE | WIN_DATA_WIDTH_16 |
WIN_USE_WAIT ;
2007-09-18 15:39:42 -04:00
win . Base = 0 ;
win . Size = SSB_CORE_SIZE ;
2007-11-06 16:36:41 +01:00
win . AccessSpeed = 250 ;
2009-11-03 01:31:52 +01:00
res = pcmcia_request_window ( dev , & win , & dev - > win ) ;
2008-08-03 10:07:45 +02:00
if ( res ! = 0 )
2007-09-18 15:39:42 -04:00
goto err_kfree_ssb ;
mem . CardOffset = 0 ;
mem . Page = 0 ;
2006-12-13 19:46:43 +09:00
res = pcmcia_map_mem_page ( dev , dev - > win , & mem ) ;
2008-08-03 10:07:45 +02:00
if ( res ! = 0 )
2007-11-06 16:36:41 +01:00
goto err_disable ;
2007-09-18 15:39:42 -04:00
2008-03-28 11:48:53 +01:00
dev - > irq . Attributes = IRQ_TYPE_DYNAMIC_SHARING ;
2007-11-07 19:08:26 +01:00
dev - > irq . Handler = NULL ; /* The handler is registered later. */
res = pcmcia_request_irq ( dev , & dev - > irq ) ;
2008-08-03 10:07:45 +02:00
if ( res ! = 0 )
2007-11-07 19:08:26 +01:00
goto err_disable ;
2007-09-18 15:39:42 -04:00
res = pcmcia_request_configuration ( dev , & dev - > conf ) ;
2008-08-03 10:07:45 +02:00
if ( res ! = 0 )
2007-09-18 15:39:42 -04:00
goto err_disable ;
err = ssb_bus_pcmciabus_register ( ssb , dev , win . Base ) ;
2007-11-06 16:36:41 +01:00
if ( err )
goto err_disable ;
2007-09-18 15:39:42 -04:00
dev - > priv = ssb ;
2007-11-06 16:36:41 +01:00
return 0 ;
err_disable :
2007-09-18 15:39:42 -04:00
pcmcia_disable_device ( dev ) ;
2007-11-06 16:36:41 +01:00
err_kfree_ssb :
2007-09-18 15:39:42 -04:00
kfree ( ssb ) ;
2007-11-06 16:36:41 +01:00
out_error :
printk ( KERN_ERR " b43-pcmcia: Initialization failed (%d, %d) \n " ,
res , err ) ;
2007-09-18 15:39:42 -04:00
return err ;
}
static void __devexit b43_pcmcia_remove ( struct pcmcia_device * dev )
{
struct ssb_bus * ssb = dev - > priv ;
ssb_bus_unregister ( ssb ) ;
pcmcia_disable_device ( dev ) ;
kfree ( ssb ) ;
dev - > priv = NULL ;
}
static struct pcmcia_driver b43_pcmcia_driver = {
2007-11-06 16:36:41 +01:00
. owner = THIS_MODULE ,
. drv = {
. name = " b43-pcmcia " ,
} ,
. id_table = b43_pcmcia_tbl ,
. probe = b43_pcmcia_probe ,
. remove = __devexit_p ( b43_pcmcia_remove ) ,
. suspend = b43_pcmcia_suspend ,
. resume = b43_pcmcia_resume ,
2007-09-18 15:39:42 -04:00
} ;
int b43_pcmcia_init ( void )
{
return pcmcia_register_driver ( & b43_pcmcia_driver ) ;
}
void b43_pcmcia_exit ( void )
{
pcmcia_unregister_driver ( & b43_pcmcia_driver ) ;
}