2010-02-22 08:38:27 +02:00
/*
* This file is part of wl1271
*
* Copyright ( C ) 2009 - 2010 Nokia Corporation
*
* Contact : Luciano Coelho < luciano . coelho @ nokia . com >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation .
*
* 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 ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA
* 02110 - 1301 USA
*
*/
# include <linux/irq.h>
# include <linux/module.h>
# include <linux/vmalloc.h>
2011-10-05 09:00:12 +03:00
# include <linux/platform_device.h>
2012-05-10 12:13:07 +03:00
# include <linux/mmc/sdio.h>
2010-02-22 08:38:27 +02:00
# include <linux/mmc/sdio_func.h>
# include <linux/mmc/sdio_ids.h>
# include <linux/mmc/card.h>
2011-02-28 00:13:58 +02:00
# include <linux/mmc/host.h>
2010-05-13 12:43:24 +03:00
# include <linux/gpio.h>
2010-10-08 16:16:16 +03:00
# include <linux/pm_runtime.h>
2012-05-10 12:13:57 +03:00
# include <linux/printk.h>
2015-03-18 18:38:28 +02:00
# include <linux/of.h>
# include <linux/of_irq.h>
2010-02-22 08:38:27 +02:00
2011-11-21 19:25:24 +02:00
# include "wlcore.h"
2010-02-22 08:38:27 +02:00
# include "wl12xx_80211.h"
2010-11-08 11:20:10 +00:00
# include "io.h"
2010-02-22 08:38:27 +02:00
# ifndef SDIO_VENDOR_ID_TI
# define SDIO_VENDOR_ID_TI 0x0097
# endif
# ifndef SDIO_DEVICE_ID_TI_WL1271
# define SDIO_DEVICE_ID_TI_WL1271 0x4076
# endif
2012-05-10 12:13:57 +03:00
static bool dump = false ;
2011-10-04 23:10:28 +03:00
struct wl12xx_sdio_glue {
struct device * dev ;
2011-10-05 09:00:12 +03:00
struct platform_device * core ;
2011-10-04 23:10:28 +03:00
} ;
2012-12-03 09:56:42 -05:00
static const struct sdio_device_id wl1271_devices [ ] = {
2010-02-22 08:38:27 +02:00
{ SDIO_DEVICE ( SDIO_VENDOR_ID_TI , SDIO_DEVICE_ID_TI_WL1271 ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( sdio , wl1271_devices ) ;
2011-10-06 10:07:44 +03:00
static void wl1271_sdio_set_block_size ( struct device * child ,
unsigned int blksz )
2011-03-14 14:05:13 +02:00
{
2011-10-06 10:07:44 +03:00
struct wl12xx_sdio_glue * glue = dev_get_drvdata ( child - > parent ) ;
struct sdio_func * func = dev_to_sdio_func ( glue - > dev ) ;
2010-02-22 08:38:27 +02:00
2011-10-06 10:07:44 +03:00
sdio_claim_host ( func ) ;
sdio_set_block_size ( func , blksz ) ;
sdio_release_host ( func ) ;
2010-02-22 08:38:27 +02:00
}
2012-06-20 00:03:46 +03:00
static int __must_check wl12xx_sdio_raw_read ( struct device * child , int addr ,
void * buf , size_t len , bool fixed )
2010-02-22 08:38:27 +02:00
{
int ret ;
2011-10-06 10:07:44 +03:00
struct wl12xx_sdio_glue * glue = dev_get_drvdata ( child - > parent ) ;
2011-10-04 23:10:28 +03:00
struct sdio_func * func = dev_to_sdio_func ( glue - > dev ) ;
2010-02-22 08:38:27 +02:00
2012-01-26 14:12:31 +02:00
sdio_claim_host ( func ) ;
2011-11-29 13:38:37 +02:00
if ( unlikely ( addr = = HW_ACCESS_ELP_CTRL_REG ) ) {
2010-02-22 08:38:27 +02:00
( ( u8 * ) buf ) [ 0 ] = sdio_f0_readb ( func , addr , & ret ) ;
2011-10-07 14:14:25 +03:00
dev_dbg ( child - > parent , " sdio read 52 addr 0x%x, byte 0x%02x \n " ,
addr , ( ( u8 * ) buf ) [ 0 ] ) ;
2010-02-22 08:38:27 +02:00
} else {
if ( fixed )
ret = sdio_readsb ( func , buf , addr , len ) ;
else
ret = sdio_memcpy_fromio ( func , buf , addr , len ) ;
2011-10-07 14:14:25 +03:00
dev_dbg ( child - > parent , " sdio read 53 addr 0x%x, %zu bytes \n " ,
addr , len ) ;
2010-02-22 08:38:27 +02:00
}
2012-01-26 14:12:31 +02:00
sdio_release_host ( func ) ;
2012-06-17 20:30:05 +03:00
if ( WARN_ON ( ret ) )
2011-10-07 14:14:25 +03:00
dev_err ( child - > parent , " sdio read failed (%d) \n " , ret ) ;
2012-06-17 20:30:05 +03:00
2017-01-26 17:35:13 +02:00
if ( unlikely ( dump ) ) {
printk ( KERN_DEBUG " wlcore_sdio: READ from 0x%04x \n " , addr ) ;
print_hex_dump ( KERN_DEBUG , " wlcore_sdio: READ " ,
DUMP_PREFIX_OFFSET , 16 , 1 ,
buf , len , false ) ;
}
2012-06-17 20:30:05 +03:00
return ret ;
2010-02-22 08:38:27 +02:00
}
2012-06-20 00:03:46 +03:00
static int __must_check wl12xx_sdio_raw_write ( struct device * child , int addr ,
void * buf , size_t len , bool fixed )
2010-02-22 08:38:27 +02:00
{
int ret ;
2011-10-06 10:07:44 +03:00
struct wl12xx_sdio_glue * glue = dev_get_drvdata ( child - > parent ) ;
2011-10-04 23:10:28 +03:00
struct sdio_func * func = dev_to_sdio_func ( glue - > dev ) ;
2010-02-22 08:38:27 +02:00
2012-01-26 14:12:31 +02:00
sdio_claim_host ( func ) ;
2012-05-10 12:13:57 +03:00
if ( unlikely ( dump ) ) {
printk ( KERN_DEBUG " wlcore_sdio: WRITE to 0x%04x \n " , addr ) ;
print_hex_dump ( KERN_DEBUG , " wlcore_sdio: WRITE " ,
DUMP_PREFIX_OFFSET , 16 , 1 ,
buf , len , false ) ;
}
2011-11-29 13:38:37 +02:00
if ( unlikely ( addr = = HW_ACCESS_ELP_CTRL_REG ) ) {
2010-02-22 08:38:27 +02:00
sdio_f0_writeb ( func , ( ( u8 * ) buf ) [ 0 ] , addr , & ret ) ;
2011-10-07 14:14:25 +03:00
dev_dbg ( child - > parent , " sdio write 52 addr 0x%x, byte 0x%02x \n " ,
addr , ( ( u8 * ) buf ) [ 0 ] ) ;
2010-02-22 08:38:27 +02:00
} else {
2011-10-07 14:14:25 +03:00
dev_dbg ( child - > parent , " sdio write 53 addr 0x%x, %zu bytes \n " ,
addr , len ) ;
2010-02-22 08:38:27 +02:00
if ( fixed )
ret = sdio_writesb ( func , addr , buf , len ) ;
else
ret = sdio_memcpy_toio ( func , addr , buf , len ) ;
}
2010-09-07 04:24:21 +03:00
2012-01-26 14:12:31 +02:00
sdio_release_host ( func ) ;
2012-06-17 20:30:05 +03:00
if ( WARN_ON ( ret ) )
2011-10-07 14:14:25 +03:00
dev_err ( child - > parent , " sdio write failed (%d) \n " , ret ) ;
2012-06-17 20:30:05 +03:00
return ret ;
2010-09-07 04:24:21 +03:00
}
2011-10-06 10:07:44 +03:00
static int wl12xx_sdio_power_on ( struct wl12xx_sdio_glue * glue )
2010-09-07 04:24:21 +03:00
{
2010-10-08 16:16:16 +03:00
int ret ;
2011-10-04 23:10:28 +03:00
struct sdio_func * func = dev_to_sdio_func ( glue - > dev ) ;
2012-05-20 10:38:16 +03:00
struct mmc_card * card = func - > card ;
ret = pm_runtime_get_sync ( & card - > dev ) ;
if ( ret ) {
/*
* Runtime PM might be temporarily disabled , or the device
* might have a positive reference counter . Make sure it is
* really powered on .
*/
ret = mmc_power_restore_host ( card - > host ) ;
if ( ret < 0 ) {
pm_runtime_put_sync ( & card - > dev ) ;
2011-06-26 18:00:11 +03:00
goto out ;
2012-05-20 10:38:16 +03:00
}
2011-05-29 16:36:03 +03:00
}
2010-02-22 08:38:27 +02:00
2010-09-07 04:24:21 +03:00
sdio_claim_host ( func ) ;
sdio_enable_func ( func ) ;
2012-01-26 14:12:31 +02:00
sdio_release_host ( func ) ;
2010-09-16 01:22:04 +02:00
2010-10-08 16:16:16 +03:00
out :
return ret ;
2010-09-07 04:24:21 +03:00
}
2011-10-06 10:07:44 +03:00
static int wl12xx_sdio_power_off ( struct wl12xx_sdio_glue * glue )
2010-09-07 04:24:21 +03:00
{
2011-02-28 00:13:58 +02:00
int ret ;
2011-10-04 23:10:28 +03:00
struct sdio_func * func = dev_to_sdio_func ( glue - > dev ) ;
2012-05-20 10:38:16 +03:00
struct mmc_card * card = func - > card ;
2010-09-07 04:24:21 +03:00
2012-01-26 14:12:31 +02:00
sdio_claim_host ( func ) ;
2010-09-07 04:24:21 +03:00
sdio_disable_func ( func ) ;
sdio_release_host ( func ) ;
2010-09-16 01:22:04 +02:00
2012-05-20 10:38:16 +03:00
/* Power off the card manually in case it wasn't powered off above */
ret = mmc_power_save_host ( card - > host ) ;
2011-02-28 00:13:58 +02:00
if ( ret < 0 )
2012-05-20 10:38:16 +03:00
goto out ;
2011-02-28 00:13:58 +02:00
2012-05-20 10:38:16 +03:00
/* Let runtime PM know the card is powered off */
pm_runtime_put_sync ( & card - > dev ) ;
2011-05-29 16:36:03 +03:00
2012-05-20 10:38:16 +03:00
out :
2011-05-29 16:36:03 +03:00
return ret ;
2010-02-22 08:38:27 +02:00
}
2011-10-06 10:07:44 +03:00
static int wl12xx_sdio_set_power ( struct device * child , bool enable )
2010-03-18 12:26:27 +02:00
{
2011-10-06 10:07:44 +03:00
struct wl12xx_sdio_glue * glue = dev_get_drvdata ( child - > parent ) ;
2010-09-07 04:24:21 +03:00
if ( enable )
2011-10-06 10:07:44 +03:00
return wl12xx_sdio_power_on ( glue ) ;
2010-09-07 04:24:21 +03:00
else
2011-10-06 10:07:44 +03:00
return wl12xx_sdio_power_off ( glue ) ;
2010-03-18 12:26:27 +02:00
}
2010-02-22 08:38:27 +02:00
static struct wl1271_if_operations sdio_ops = {
2011-10-06 10:07:44 +03:00
. read = wl12xx_sdio_raw_read ,
. write = wl12xx_sdio_raw_write ,
. power = wl12xx_sdio_set_power ,
2011-03-14 14:05:13 +02:00
. set_block_size = wl1271_sdio_set_block_size ,
2010-02-22 08:38:27 +02:00
} ;
2015-03-18 18:38:28 +02:00
# ifdef CONFIG_OF
2016-09-17 09:06:30 -07:00
static const struct wilink_family_data wl127x_data = {
. name = " wl127x " ,
. nvs_name = " ti-connectivity/wl127x-nvs.bin " ,
} ;
static const struct wilink_family_data wl128x_data = {
. name = " wl128x " ,
. nvs_name = " ti-connectivity/wl128x-nvs.bin " ,
} ;
static const struct wilink_family_data wl18xx_data = {
. name = " wl18xx " ,
. cfg_name = " ti-connectivity/wl18xx-conf.bin " ,
} ;
2015-03-18 18:38:28 +02:00
static const struct of_device_id wlcore_sdio_of_match_table [ ] = {
2016-09-17 09:06:30 -07:00
{ . compatible = " ti,wl1271 " , . data = & wl127x_data } ,
{ . compatible = " ti,wl1273 " , . data = & wl127x_data } ,
{ . compatible = " ti,wl1281 " , . data = & wl128x_data } ,
{ . compatible = " ti,wl1283 " , . data = & wl128x_data } ,
2017-06-08 22:50:00 +02:00
{ . compatible = " ti,wl1285 " , . data = & wl128x_data } ,
2016-09-17 09:06:30 -07:00
{ . compatible = " ti,wl1801 " , . data = & wl18xx_data } ,
{ . compatible = " ti,wl1805 " , . data = & wl18xx_data } ,
{ . compatible = " ti,wl1807 " , . data = & wl18xx_data } ,
{ . compatible = " ti,wl1831 " , . data = & wl18xx_data } ,
{ . compatible = " ti,wl1835 " , . data = & wl18xx_data } ,
{ . compatible = " ti,wl1837 " , . data = & wl18xx_data } ,
2015-03-18 18:38:28 +02:00
{ }
} ;
2015-03-18 18:38:30 +02:00
static int wlcore_probe_of ( struct device * dev , int * irq ,
struct wlcore_platdev_data * pdev_data )
2015-03-18 18:38:28 +02:00
{
struct device_node * np = dev - > of_node ;
2016-09-17 09:06:30 -07:00
const struct of_device_id * of_id ;
2015-03-18 18:38:28 +02:00
2016-09-17 09:06:30 -07:00
of_id = of_match_node ( wlcore_sdio_of_match_table , np ) ;
if ( ! of_id )
return - ENODEV ;
pdev_data - > family = of_id - > data ;
2015-03-18 18:38:28 +02:00
2015-03-18 18:38:30 +02:00
* irq = irq_of_parse_and_map ( np , 0 ) ;
if ( ! * irq ) {
2015-03-18 18:38:28 +02:00
dev_err ( dev , " No irq in platform data \n " ) ;
2015-03-18 18:38:30 +02:00
return - EINVAL ;
2015-03-18 18:38:28 +02:00
}
/* optional clock frequency params */
of_property_read_u32 ( np , " ref-clock-frequency " ,
2015-03-18 18:38:30 +02:00
& pdev_data - > ref_clock_freq ) ;
2015-03-18 18:38:28 +02:00
of_property_read_u32 ( np , " tcxo-clock-frequency " ,
2015-03-18 18:38:30 +02:00
& pdev_data - > tcxo_clock_freq ) ;
2015-03-18 18:38:28 +02:00
2015-03-18 18:38:30 +02:00
return 0 ;
2015-03-18 18:38:28 +02:00
}
# else
2015-03-18 18:38:30 +02:00
static int wlcore_probe_of ( struct device * dev , int * irq ,
struct wlcore_platdev_data * pdev_data )
2015-03-18 18:38:28 +02:00
{
2015-03-18 18:38:30 +02:00
return - ENODATA ;
2015-03-18 18:38:28 +02:00
}
# endif
2012-12-03 09:56:42 -05:00
static int wl1271_probe ( struct sdio_func * func ,
2010-02-22 08:38:27 +02:00
const struct sdio_device_id * id )
{
2016-09-17 09:06:30 -07:00
struct wlcore_platdev_data * pdev_data ;
2011-10-04 23:10:28 +03:00
struct wl12xx_sdio_glue * glue ;
2011-10-05 09:00:12 +03:00
struct resource res [ 1 ] ;
2011-05-13 11:57:12 +03:00
mmc_pm_flag_t mmcflags ;
2011-10-04 23:10:28 +03:00
int ret = - ENOMEM ;
2015-03-18 18:38:30 +02:00
int irq ;
2012-05-10 12:13:07 +03:00
const char * chip_family ;
2010-02-22 08:38:27 +02:00
/* We are only able to handle the wlan function */
if ( func - > num ! = 0x02 )
return - ENODEV ;
2016-09-17 09:06:30 -07:00
pdev_data = devm_kzalloc ( & func - > dev , sizeof ( * pdev_data ) , GFP_KERNEL ) ;
if ( ! pdev_data )
return - ENOMEM ;
2013-01-25 11:57:48 +02:00
2016-09-17 09:06:30 -07:00
pdev_data - > if_ops = & sdio_ops ;
glue = devm_kzalloc ( & func - > dev , sizeof ( * glue ) , GFP_KERNEL ) ;
if ( ! glue )
return - ENOMEM ;
2011-10-04 23:10:28 +03:00
glue - > dev = & func - > dev ;
2010-02-22 08:38:27 +02:00
/* Grab access to FN0 for ELP reg. */
func - > card - > quirks | = MMC_QUIRK_LENIENT_FN0 ;
2011-03-18 14:49:57 +02:00
/* Use block mode for transferring over one block size of data */
func - > card - > quirks | = MMC_QUIRK_BLKSZ_FOR_BYTE_MODE ;
2016-09-17 09:06:30 -07:00
ret = wlcore_probe_of ( & func - > dev , & irq , pdev_data ) ;
2015-07-02 10:34:49 +02:00
if ( ret )
2016-09-17 09:06:30 -07:00
goto out ;
2010-02-22 08:38:27 +02:00
2011-10-06 10:07:44 +03:00
/* if sdio can keep power while host is suspended, enable wow */
mmcflags = sdio_get_host_pm_caps ( func ) ;
2011-10-07 14:14:25 +03:00
dev_dbg ( glue - > dev , " sdio PM caps = 0x%x \n " , mmcflags ) ;
2011-05-13 11:57:08 +03:00
2011-10-06 10:07:44 +03:00
if ( mmcflags & MMC_PM_KEEP_POWER )
2016-09-17 09:06:30 -07:00
pdev_data - > pwr_in_suspend = true ;
2011-05-13 11:57:12 +03:00
2011-10-04 23:10:28 +03:00
sdio_set_drvdata ( func , glue ) ;
2010-02-22 08:38:29 +02:00
2010-10-08 16:16:16 +03:00
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle ( & func - > dev ) ;
2012-05-10 12:13:07 +03:00
/*
* Due to a hardware bug , we can ' t differentiate wl18xx from
* wl12xx , because both report the same device ID . The only
* way to differentiate is by checking the SDIO revision ,
* which is 3.00 on the wl18xx chips .
*/
if ( func - > card - > cccr . sdio_vsn = = SDIO_SDIO_REV_3_00 )
chip_family = " wl18xx " ;
else
chip_family = " wl12xx " ;
2013-01-23 16:40:37 +02:00
glue - > core = platform_device_alloc ( chip_family , PLATFORM_DEVID_AUTO ) ;
2011-10-05 09:00:12 +03:00
if ( ! glue - > core ) {
2011-10-07 14:14:25 +03:00
dev_err ( glue - > dev , " can't allocate platform_device " ) ;
2011-10-05 09:00:12 +03:00
ret = - ENOMEM ;
2016-09-17 09:06:30 -07:00
goto out ;
2011-10-05 09:00:12 +03:00
}
glue - > core - > dev . parent = & func - > dev ;
memset ( res , 0x00 , sizeof ( res ) ) ;
2015-03-18 18:38:30 +02:00
res [ 0 ] . start = irq ;
res [ 0 ] . flags = IORESOURCE_IRQ |
irqd_get_trigger_type ( irq_get_irq_data ( irq ) ) ;
2011-10-05 09:00:12 +03:00
res [ 0 ] . name = " irq " ;
ret = platform_device_add_resources ( glue - > core , res , ARRAY_SIZE ( res ) ) ;
if ( ret ) {
2011-10-07 14:14:25 +03:00
dev_err ( glue - > dev , " can't add resources \n " ) ;
2011-10-05 09:00:12 +03:00
goto out_dev_put ;
}
2016-09-17 09:06:30 -07:00
ret = platform_device_add_data ( glue - > core , pdev_data ,
sizeof ( * pdev_data ) ) ;
2011-10-05 09:00:12 +03:00
if ( ret ) {
2011-10-07 14:14:25 +03:00
dev_err ( glue - > dev , " can't add platform data \n " ) ;
2011-10-05 09:00:12 +03:00
goto out_dev_put ;
}
ret = platform_device_add ( glue - > core ) ;
if ( ret ) {
2011-10-07 14:14:25 +03:00
dev_err ( glue - > dev , " can't add platform device \n " ) ;
2011-10-05 09:00:12 +03:00
goto out_dev_put ;
}
2010-02-22 08:38:27 +02:00
return 0 ;
2011-10-05 09:00:12 +03:00
out_dev_put :
platform_device_put ( glue - > core ) ;
2011-10-04 23:10:28 +03:00
out :
2010-02-22 08:38:27 +02:00
return ret ;
}
2012-12-03 09:56:42 -05:00
static void wl1271_remove ( struct sdio_func * func )
2010-02-22 08:38:27 +02:00
{
2011-10-04 23:10:28 +03:00
struct wl12xx_sdio_glue * glue = sdio_get_drvdata ( func ) ;
2010-02-22 08:38:27 +02:00
2010-10-08 16:16:16 +03:00
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume ( & func - > dev ) ;
2012-10-23 13:23:13 +08:00
platform_device_unregister ( glue - > core ) ;
2010-02-22 08:38:27 +02:00
}
2011-05-18 16:51:26 -04:00
# ifdef CONFIG_PM
2010-10-08 16:16:27 +03:00
static int wl1271_suspend ( struct device * dev )
{
/* Tell MMC/SDIO core it's OK to power down the card
* ( if it isn ' t already ) , but not to remove it completely */
2011-05-13 11:57:10 +03:00
struct sdio_func * func = dev_to_sdio_func ( dev ) ;
2011-11-08 15:56:55 +02:00
struct wl12xx_sdio_glue * glue = sdio_get_drvdata ( func ) ;
struct wl1271 * wl = platform_get_drvdata ( glue - > core ) ;
2011-05-13 11:57:10 +03:00
mmc_pm_flag_t sdio_flags ;
int ret = 0 ;
2011-10-07 14:14:25 +03:00
dev_dbg ( dev , " wl1271 suspend. wow_enabled: %d \n " ,
wl - > wow_enabled ) ;
2011-05-13 11:57:10 +03:00
/* check whether sdio should keep power */
if ( wl - > wow_enabled ) {
sdio_flags = sdio_get_host_pm_caps ( func ) ;
if ( ! ( sdio_flags & MMC_PM_KEEP_POWER ) ) {
2011-10-07 14:14:25 +03:00
dev_err ( dev , " can't keep power while host "
" is suspended \n " ) ;
2011-05-13 11:57:10 +03:00
ret = - EINVAL ;
goto out ;
}
/* keep power while host suspended */
ret = sdio_set_host_pm_flags ( func , MMC_PM_KEEP_POWER ) ;
if ( ret ) {
2011-10-07 14:14:25 +03:00
dev_err ( dev , " error while trying to keep power \n " ) ;
2011-05-13 11:57:10 +03:00
goto out ;
}
}
out :
return ret ;
2010-10-08 16:16:27 +03:00
}
static int wl1271_resume ( struct device * dev )
{
2011-10-07 14:14:25 +03:00
dev_dbg ( dev , " wl1271 resume \n " ) ;
2011-05-13 11:57:11 +03:00
2010-10-08 16:16:27 +03:00
return 0 ;
}
static const struct dev_pm_ops wl1271_sdio_pm_ops = {
. suspend = wl1271_suspend ,
. resume = wl1271_resume ,
} ;
2011-05-18 16:51:26 -04:00
# endif
2010-10-08 16:16:27 +03:00
2010-02-22 08:38:27 +02:00
static struct sdio_driver wl1271_sdio_driver = {
2010-04-01 11:38:17 +03:00
. name = " wl1271_sdio " ,
2010-02-22 08:38:27 +02:00
. id_table = wl1271_devices ,
. probe = wl1271_probe ,
2012-12-03 09:56:42 -05:00
. remove = wl1271_remove ,
2011-05-18 16:51:26 -04:00
# ifdef CONFIG_PM
2010-10-08 16:16:27 +03:00
. drv = {
. pm = & wl1271_sdio_pm_ops ,
} ,
2011-05-18 16:51:26 -04:00
# endif
2010-02-22 08:38:27 +02:00
} ;
static int __init wl1271_init ( void )
{
2011-05-14 00:26:20 +03:00
return sdio_register_driver ( & wl1271_sdio_driver ) ;
2010-02-22 08:38:27 +02:00
}
static void __exit wl1271_exit ( void )
{
sdio_unregister_driver ( & wl1271_sdio_driver ) ;
}
module_init ( wl1271_init ) ;
module_exit ( wl1271_exit ) ;
2012-05-10 12:13:57 +03:00
module_param ( dump , bool , S_IRUSR | S_IWUSR ) ;
MODULE_PARM_DESC ( dump , " Enable sdio read/write dumps. " ) ;
2010-02-22 08:38:27 +02:00
MODULE_LICENSE ( " GPL " ) ;
2011-03-30 21:31:39 +03:00
MODULE_AUTHOR ( " Luciano Coelho <coelho@ti.com> " ) ;
2010-02-22 08:38:27 +02:00
MODULE_AUTHOR ( " Juuso Oikarinen <juuso.oikarinen@nokia.com> " ) ;