2012-09-17 13:50:49 +04:00
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/mtd/mtd.h>
# include <linux/platform_device.h>
# include <linux/bcma/bcma.h>
2013-01-07 00:28:50 +04:00
# include "bcm47xxsflash.h"
2012-09-17 13:50:49 +04:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " Serial flash driver for BCMA bus " ) ;
static const char * probes [ ] = { " bcm47xxpart " , NULL } ;
static int bcm47xxsflash_read ( struct mtd_info * mtd , loff_t from , size_t len ,
size_t * retlen , u_char * buf )
{
2013-01-07 00:28:50 +04:00
struct bcm47xxsflash * b47s = mtd - > priv ;
2012-09-17 13:50:49 +04:00
/* Check address range */
if ( ( from + len ) > mtd - > size )
return - EINVAL ;
2013-01-07 00:28:50 +04:00
memcpy_fromio ( buf , ( void __iomem * ) KSEG0ADDR ( b47s - > window + from ) ,
2012-09-17 13:50:49 +04:00
len ) ;
2013-01-24 20:39:54 +04:00
* retlen = len ;
2012-09-17 13:50:49 +04:00
return len ;
}
2013-01-07 00:28:50 +04:00
static void bcm47xxsflash_fill_mtd ( struct bcm47xxsflash * b47s )
2012-09-17 13:50:49 +04:00
{
2013-01-07 00:28:50 +04:00
struct mtd_info * mtd = & b47s - > mtd ;
mtd - > priv = b47s ;
2012-09-17 13:50:49 +04:00
mtd - > name = " bcm47xxsflash " ;
mtd - > owner = THIS_MODULE ;
mtd - > type = MTD_ROM ;
2013-01-07 00:28:50 +04:00
mtd - > size = b47s - > size ;
2012-09-17 13:50:49 +04:00
mtd - > _read = bcm47xxsflash_read ;
/* TODO: implement writing support and verify/change following code */
mtd - > flags = MTD_CAP_ROM ;
mtd - > writebufsize = mtd - > writesize = 1 ;
}
2013-02-04 11:23:08 +04:00
/**************************************************
* BCMA
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int bcm47xxsflash_bcma_probe ( struct platform_device * pdev )
2012-09-17 13:50:49 +04:00
{
struct bcma_sflash * sflash = dev_get_platdata ( & pdev - > dev ) ;
2013-01-07 00:28:50 +04:00
struct bcm47xxsflash * b47s ;
2012-09-17 13:50:49 +04:00
int err ;
2013-01-07 00:28:50 +04:00
b47s = kzalloc ( sizeof ( * b47s ) , GFP_KERNEL ) ;
if ( ! b47s ) {
2012-09-17 13:50:49 +04:00
err = - ENOMEM ;
goto out ;
}
2013-01-07 00:28:50 +04:00
sflash - > priv = b47s ;
b47s - > window = sflash - > window ;
b47s - > blocksize = sflash - > blocksize ;
b47s - > numblocks = sflash - > numblocks ;
b47s - > size = sflash - > size ;
bcm47xxsflash_fill_mtd ( b47s ) ;
2012-09-17 13:50:49 +04:00
2013-01-07 00:28:50 +04:00
err = mtd_device_parse_register ( & b47s - > mtd , probes , NULL , NULL , 0 ) ;
2012-09-17 13:50:49 +04:00
if ( err ) {
pr_err ( " Failed to register MTD device: %d \n " , err ) ;
goto err_dev_reg ;
}
return 0 ;
err_dev_reg :
2013-01-07 00:28:50 +04:00
kfree ( & b47s - > mtd ) ;
2012-09-17 13:50:49 +04:00
out :
return err ;
}
2013-02-04 11:23:08 +04:00
static int bcm47xxsflash_bcma_remove ( struct platform_device * pdev )
2012-09-17 13:50:49 +04:00
{
struct bcma_sflash * sflash = dev_get_platdata ( & pdev - > dev ) ;
2013-01-07 00:28:50 +04:00
struct bcm47xxsflash * b47s = sflash - > priv ;
2012-09-17 13:50:49 +04:00
2013-01-07 00:28:50 +04:00
mtd_device_unregister ( & b47s - > mtd ) ;
kfree ( b47s ) ;
2012-09-17 13:50:49 +04:00
return 0 ;
}
static struct platform_driver bcma_sflash_driver = {
2013-02-04 11:23:08 +04:00
. probe = bcm47xxsflash_bcma_probe ,
. remove = bcm47xxsflash_bcma_remove ,
2012-09-17 13:50:49 +04:00
. driver = {
. name = " bcma_sflash " ,
. owner = THIS_MODULE ,
} ,
} ;
2013-02-04 11:23:08 +04:00
/**************************************************
* Init
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-09-17 13:50:49 +04:00
static int __init bcm47xxsflash_init ( void )
{
int err ;
2013-01-24 20:39:55 +04:00
err = platform_driver_register ( & bcma_sflash_driver ) ;
2012-09-17 13:50:49 +04:00
if ( err )
pr_err ( " Failed to register BCMA serial flash driver: %d \n " ,
err ) ;
return err ;
}
static void __exit bcm47xxsflash_exit ( void )
{
platform_driver_unregister ( & bcma_sflash_driver ) ;
}
module_init ( bcm47xxsflash_init ) ;
module_exit ( bcm47xxsflash_exit ) ;