2019-08-19 17:15:09 +08:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2019 Inspur Corp .
*/
# include <linux/debugfs.h>
# include <linux/device.h>
# include <linux/fs.h>
# include <linux/i2c.h>
# include <linux/module.h>
# include <linux/pmbus.h>
# include <linux/hwmon-sysfs.h>
# include "pmbus.h"
# define IPSPS_REG_VENDOR_ID 0x99
# define IPSPS_REG_MODEL 0x9A
# define IPSPS_REG_FW_VERSION 0x9B
# define IPSPS_REG_PN 0x9C
# define IPSPS_REG_SN 0x9E
# define IPSPS_REG_HW_VERSION 0xB0
# define IPSPS_REG_MODE 0xFC
# define MODE_ACTIVE 0x55
# define MODE_STANDBY 0x0E
# define MODE_REDUNDANCY 0x00
# define MODE_ACTIVE_STRING "active"
# define MODE_STANDBY_STRING "standby"
# define MODE_REDUNDANCY_STRING "redundancy"
enum ipsps_index {
vendor ,
model ,
fw_version ,
part_number ,
serial_number ,
hw_version ,
mode ,
num_regs ,
} ;
static const u8 ipsps_regs [ num_regs ] = {
[ vendor ] = IPSPS_REG_VENDOR_ID ,
[ model ] = IPSPS_REG_MODEL ,
[ fw_version ] = IPSPS_REG_FW_VERSION ,
[ part_number ] = IPSPS_REG_PN ,
[ serial_number ] = IPSPS_REG_SN ,
[ hw_version ] = IPSPS_REG_HW_VERSION ,
[ mode ] = IPSPS_REG_MODE ,
} ;
static ssize_t ipsps_string_show ( struct device * dev ,
struct device_attribute * devattr ,
char * buf )
{
u8 reg ;
int rc ;
char * p ;
char data [ I2C_SMBUS_BLOCK_MAX + 1 ] ;
struct i2c_client * client = to_i2c_client ( dev - > parent ) ;
struct sensor_device_attribute * attr = to_sensor_dev_attr ( devattr ) ;
reg = ipsps_regs [ attr - > index ] ;
rc = i2c_smbus_read_block_data ( client , reg , data ) ;
if ( rc < 0 )
return rc ;
/* filled with printable characters, ending with # */
p = memscan ( data , ' # ' , rc ) ;
* p = ' \0 ' ;
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " %s \n " , data ) ;
2019-08-19 17:15:09 +08:00
}
static ssize_t ipsps_fw_version_show ( struct device * dev ,
struct device_attribute * devattr ,
char * buf )
{
u8 reg ;
int rc ;
u8 data [ I2C_SMBUS_BLOCK_MAX ] = { 0 } ;
struct i2c_client * client = to_i2c_client ( dev - > parent ) ;
struct sensor_device_attribute * attr = to_sensor_dev_attr ( devattr ) ;
reg = ipsps_regs [ attr - > index ] ;
rc = i2c_smbus_read_block_data ( client , reg , data ) ;
if ( rc < 0 )
return rc ;
if ( rc ! = 6 )
return - EPROTO ;
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " %u.%02u%u-%u.%02u \n " ,
data [ 1 ] , data [ 2 ] /* < 100 */ , data [ 3 ] /*< 10*/ ,
data [ 4 ] , data [ 5 ] /* < 100 */ ) ;
2019-08-19 17:15:09 +08:00
}
static ssize_t ipsps_mode_show ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
u8 reg ;
int rc ;
struct i2c_client * client = to_i2c_client ( dev - > parent ) ;
struct sensor_device_attribute * attr = to_sensor_dev_attr ( devattr ) ;
reg = ipsps_regs [ attr - > index ] ;
rc = i2c_smbus_read_byte_data ( client , reg ) ;
if ( rc < 0 )
return rc ;
switch ( rc ) {
case MODE_ACTIVE :
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " [%s] %s %s \n " ,
MODE_ACTIVE_STRING ,
MODE_STANDBY_STRING , MODE_REDUNDANCY_STRING ) ;
2019-08-19 17:15:09 +08:00
case MODE_STANDBY :
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " %s [%s] %s \n " ,
MODE_ACTIVE_STRING ,
MODE_STANDBY_STRING , MODE_REDUNDANCY_STRING ) ;
2019-08-19 17:15:09 +08:00
case MODE_REDUNDANCY :
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " %s %s [%s] \n " ,
MODE_ACTIVE_STRING ,
MODE_STANDBY_STRING , MODE_REDUNDANCY_STRING ) ;
2019-08-19 17:15:09 +08:00
default :
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " unspecified \n " ) ;
2019-08-19 17:15:09 +08:00
}
}
static ssize_t ipsps_mode_store ( struct device * dev ,
struct device_attribute * devattr ,
const char * buf , size_t count )
{
u8 reg ;
int rc ;
struct i2c_client * client = to_i2c_client ( dev - > parent ) ;
struct sensor_device_attribute * attr = to_sensor_dev_attr ( devattr ) ;
reg = ipsps_regs [ attr - > index ] ;
if ( sysfs_streq ( MODE_STANDBY_STRING , buf ) ) {
rc = i2c_smbus_write_byte_data ( client , reg ,
MODE_STANDBY ) ;
if ( rc < 0 )
return rc ;
return count ;
} else if ( sysfs_streq ( MODE_ACTIVE_STRING , buf ) ) {
rc = i2c_smbus_write_byte_data ( client , reg ,
MODE_ACTIVE ) ;
if ( rc < 0 )
return rc ;
return count ;
}
return - EINVAL ;
}
static SENSOR_DEVICE_ATTR_RO ( vendor , ipsps_string , vendor ) ;
static SENSOR_DEVICE_ATTR_RO ( model , ipsps_string , model ) ;
static SENSOR_DEVICE_ATTR_RO ( part_number , ipsps_string , part_number ) ;
static SENSOR_DEVICE_ATTR_RO ( serial_number , ipsps_string , serial_number ) ;
static SENSOR_DEVICE_ATTR_RO ( hw_version , ipsps_string , hw_version ) ;
static SENSOR_DEVICE_ATTR_RO ( fw_version , ipsps_fw_version , fw_version ) ;
static SENSOR_DEVICE_ATTR_RW ( mode , ipsps_mode , mode ) ;
static struct attribute * ipsps_attrs [ ] = {
& sensor_dev_attr_vendor . dev_attr . attr ,
& sensor_dev_attr_model . dev_attr . attr ,
& sensor_dev_attr_part_number . dev_attr . attr ,
& sensor_dev_attr_serial_number . dev_attr . attr ,
& sensor_dev_attr_hw_version . dev_attr . attr ,
& sensor_dev_attr_fw_version . dev_attr . attr ,
& sensor_dev_attr_mode . dev_attr . attr ,
NULL ,
} ;
ATTRIBUTE_GROUPS ( ipsps ) ;
static struct pmbus_driver_info ipsps_info = {
. pages = 1 ,
. func [ 0 ] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
PMBUS_HAVE_IIN | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN |
PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT |
PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_FAN12 ,
. groups = ipsps_groups ,
} ;
static struct pmbus_platform_data ipsps_pdata = {
. flags = PMBUS_SKIP_STATUS_CHECK ,
} ;
2020-08-08 23:00:04 +02:00
static int ipsps_probe ( struct i2c_client * client )
2019-08-19 17:15:09 +08:00
{
client - > dev . platform_data = & ipsps_pdata ;
2020-08-08 23:00:04 +02:00
return pmbus_do_probe ( client , & ipsps_info ) ;
2019-08-19 17:15:09 +08:00
}
static const struct i2c_device_id ipsps_id [ ] = {
{ " ipsps1 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , ipsps_id ) ;
# ifdef CONFIG_OF
static const struct of_device_id ipsps_of_match [ ] = {
{ . compatible = " inspur,ipsps1 " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , ipsps_of_match ) ;
# endif
static struct i2c_driver ipsps_driver = {
. driver = {
. name = " inspur-ipsps " ,
. of_match_table = of_match_ptr ( ipsps_of_match ) ,
} ,
2020-08-08 23:00:04 +02:00
. probe_new = ipsps_probe ,
2019-08-19 17:15:09 +08:00
. id_table = ipsps_id ,
} ;
module_i2c_driver ( ipsps_driver ) ;
MODULE_AUTHOR ( " John Wang " ) ;
MODULE_DESCRIPTION ( " PMBus driver for Inspur Power System power supplies " ) ;
MODULE_LICENSE ( " GPL " ) ;
2021-04-19 23:07:07 -07:00
MODULE_IMPORT_NS ( PMBUS ) ;