2019-05-27 09:55:00 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2010-06-19 22:32:58 +04:00
/*
* Copyright ( C ) 2009 - 2010 , Lars - Peter Clausen < lars @ metafoo . de >
* JZ4740 SoC HWMON driver
*/
# include <linux/err.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/mutex.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
2012-06-02 23:22:08 +04:00
# include <linux/io.h>
2010-06-19 22:32:58 +04:00
# include <linux/completion.h>
# include <linux/mfd/core.h>
# include <linux/hwmon.h>
struct jz4740_hwmon {
void __iomem * base ;
int irq ;
2011-03-02 00:35:48 +03:00
const struct mfd_cell * cell ;
2014-06-29 17:39:11 +04:00
struct platform_device * pdev ;
2010-06-19 22:32:58 +04:00
struct completion read_completion ;
struct mutex lock ;
} ;
static irqreturn_t jz4740_hwmon_irq ( int irq , void * data )
{
struct jz4740_hwmon * hwmon = data ;
complete ( & hwmon - > read_completion ) ;
return IRQ_HANDLED ;
}
2016-12-22 15:04:48 +03:00
static ssize_t in0_input_show ( struct device * dev ,
struct device_attribute * dev_attr , char * buf )
2010-06-19 22:32:58 +04:00
{
struct jz4740_hwmon * hwmon = dev_get_drvdata ( dev ) ;
2014-06-29 17:39:11 +04:00
struct platform_device * pdev = hwmon - > pdev ;
2010-06-19 22:32:58 +04:00
struct completion * completion = & hwmon - > read_completion ;
2011-12-08 17:04:12 +04:00
long t ;
2010-06-19 22:32:58 +04:00
unsigned long val ;
int ret ;
mutex_lock ( & hwmon - > lock ) ;
2013-11-15 02:32:02 +04:00
reinit_completion ( completion ) ;
2010-06-19 22:32:58 +04:00
enable_irq ( hwmon - > irq ) ;
2014-06-29 17:39:11 +04:00
hwmon - > cell - > enable ( pdev ) ;
2010-06-19 22:32:58 +04:00
t = wait_for_completion_interruptible_timeout ( completion , HZ ) ;
if ( t > 0 ) {
val = readw ( hwmon - > base ) & 0xfff ;
val = ( val * 3300 ) > > 12 ;
ret = sprintf ( buf , " %lu \n " , val ) ;
} else {
ret = t ? t : - ETIMEDOUT ;
}
2014-06-29 17:39:11 +04:00
hwmon - > cell - > disable ( pdev ) ;
2010-06-19 22:32:58 +04:00
disable_irq ( hwmon - > irq ) ;
mutex_unlock ( & hwmon - > lock ) ;
return ret ;
}
2016-12-22 15:04:48 +03:00
static DEVICE_ATTR_RO ( in0_input ) ;
2010-06-19 22:32:58 +04:00
2014-06-29 17:39:11 +04:00
static struct attribute * jz4740_attrs [ ] = {
2010-06-19 22:32:58 +04:00
& dev_attr_in0_input . attr ,
NULL
} ;
2014-06-29 17:39:11 +04:00
ATTRIBUTE_GROUPS ( jz4740 ) ;
2010-06-19 22:32:58 +04:00
2012-11-19 22:22:35 +04:00
static int jz4740_hwmon_probe ( struct platform_device * pdev )
2010-06-19 22:32:58 +04:00
{
int ret ;
2014-06-29 17:39:11 +04:00
struct device * dev = & pdev - > dev ;
2010-06-19 22:32:58 +04:00
struct jz4740_hwmon * hwmon ;
2014-06-29 17:39:11 +04:00
struct device * hwmon_dev ;
2010-06-19 22:32:58 +04:00
2014-06-29 17:39:11 +04:00
hwmon = devm_kzalloc ( dev , sizeof ( * hwmon ) , GFP_KERNEL ) ;
2012-06-02 23:22:08 +04:00
if ( ! hwmon )
2010-06-19 22:32:58 +04:00
return - ENOMEM ;
2011-02-18 06:07:10 +03:00
hwmon - > cell = mfd_get_cell ( pdev ) ;
2010-06-19 22:32:58 +04:00
hwmon - > irq = platform_get_irq ( pdev , 0 ) ;
if ( hwmon - > irq < 0 ) {
2012-06-02 23:22:08 +04:00
dev_err ( & pdev - > dev , " Failed to get platform irq: %d \n " ,
hwmon - > irq ) ;
return hwmon - > irq ;
2010-06-19 22:32:58 +04:00
}
2019-04-01 20:36:41 +03:00
hwmon - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2014-02-11 16:10:50 +04:00
if ( IS_ERR ( hwmon - > base ) )
return PTR_ERR ( hwmon - > base ) ;
2010-06-19 22:32:58 +04:00
2014-06-29 17:39:11 +04:00
hwmon - > pdev = pdev ;
2010-06-19 22:32:58 +04:00
init_completion ( & hwmon - > read_completion ) ;
mutex_init ( & hwmon - > lock ) ;
2014-06-29 17:39:11 +04:00
ret = devm_request_irq ( dev , hwmon - > irq , jz4740_hwmon_irq , 0 ,
2012-06-02 23:22:08 +04:00
pdev - > name , hwmon ) ;
2010-06-19 22:32:58 +04:00
if ( ret ) {
dev_err ( & pdev - > dev , " Failed to request irq: %d \n " , ret ) ;
2012-06-02 23:22:08 +04:00
return ret ;
2010-06-19 22:32:58 +04:00
}
disable_irq ( hwmon - > irq ) ;
2014-06-29 17:39:11 +04:00
hwmon_dev = devm_hwmon_device_register_with_groups ( dev , " jz4740 " , hwmon ,
jz4740_groups ) ;
return PTR_ERR_OR_ZERO ( hwmon_dev ) ;
2010-06-19 22:32:58 +04:00
}
2011-12-08 17:33:37 +04:00
static struct platform_driver jz4740_hwmon_driver = {
2010-06-19 22:32:58 +04:00
. probe = jz4740_hwmon_probe ,
. driver = {
. name = " jz4740-hwmon " ,
} ,
} ;
2011-11-25 11:31:00 +04:00
module_platform_driver ( jz4740_hwmon_driver ) ;
2010-06-19 22:32:58 +04:00
MODULE_DESCRIPTION ( " JZ4740 SoC HWMON driver " ) ;
MODULE_AUTHOR ( " Lars-Peter Clausen <lars@metafoo.de> " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:jz4740-hwmon " ) ;