1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2019 Inspur Corp.
6 #include <linux/debugfs.h>
7 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/pmbus.h>
12 #include <linux/hwmon-sysfs.h>
16 #define IPSPS_REG_VENDOR_ID 0x99
17 #define IPSPS_REG_MODEL 0x9A
18 #define IPSPS_REG_FW_VERSION 0x9B
19 #define IPSPS_REG_PN 0x9C
20 #define IPSPS_REG_SN 0x9E
21 #define IPSPS_REG_HW_VERSION 0xB0
22 #define IPSPS_REG_MODE 0xFC
24 #define MODE_ACTIVE 0x55
25 #define MODE_STANDBY 0x0E
26 #define MODE_REDUNDANCY 0x00
28 #define MODE_ACTIVE_STRING "active"
29 #define MODE_STANDBY_STRING "standby"
30 #define MODE_REDUNDANCY_STRING "redundancy"
43 static const u8 ipsps_regs
[num_regs
] = {
44 [vendor
] = IPSPS_REG_VENDOR_ID
,
45 [model
] = IPSPS_REG_MODEL
,
46 [fw_version
] = IPSPS_REG_FW_VERSION
,
47 [part_number
] = IPSPS_REG_PN
,
48 [serial_number
] = IPSPS_REG_SN
,
49 [hw_version
] = IPSPS_REG_HW_VERSION
,
50 [mode
] = IPSPS_REG_MODE
,
53 static ssize_t
ipsps_string_show(struct device
*dev
,
54 struct device_attribute
*devattr
,
60 char data
[I2C_SMBUS_BLOCK_MAX
+ 1];
61 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
62 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
64 reg
= ipsps_regs
[attr
->index
];
65 rc
= i2c_smbus_read_block_data(client
, reg
, data
);
69 /* filled with printable characters, ending with # */
70 p
= memscan(data
, '#', rc
);
73 return snprintf(buf
, PAGE_SIZE
, "%s\n", data
);
76 static ssize_t
ipsps_fw_version_show(struct device
*dev
,
77 struct device_attribute
*devattr
,
82 u8 data
[I2C_SMBUS_BLOCK_MAX
] = { 0 };
83 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
84 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
86 reg
= ipsps_regs
[attr
->index
];
87 rc
= i2c_smbus_read_block_data(client
, reg
, data
);
94 return snprintf(buf
, PAGE_SIZE
, "%u.%02u%u-%u.%02u\n",
95 data
[1], data
[2]/* < 100 */, data
[3]/*< 10*/,
96 data
[4], data
[5]/* < 100 */);
99 static ssize_t
ipsps_mode_show(struct device
*dev
,
100 struct device_attribute
*devattr
, char *buf
)
104 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
105 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
107 reg
= ipsps_regs
[attr
->index
];
108 rc
= i2c_smbus_read_byte_data(client
, reg
);
114 return snprintf(buf
, PAGE_SIZE
, "[%s] %s %s\n",
116 MODE_STANDBY_STRING
, MODE_REDUNDANCY_STRING
);
118 return snprintf(buf
, PAGE_SIZE
, "%s [%s] %s\n",
120 MODE_STANDBY_STRING
, MODE_REDUNDANCY_STRING
);
121 case MODE_REDUNDANCY
:
122 return snprintf(buf
, PAGE_SIZE
, "%s %s [%s]\n",
124 MODE_STANDBY_STRING
, MODE_REDUNDANCY_STRING
);
126 return snprintf(buf
, PAGE_SIZE
, "unspecified\n");
130 static ssize_t
ipsps_mode_store(struct device
*dev
,
131 struct device_attribute
*devattr
,
132 const char *buf
, size_t count
)
136 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
137 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
139 reg
= ipsps_regs
[attr
->index
];
140 if (sysfs_streq(MODE_STANDBY_STRING
, buf
)) {
141 rc
= i2c_smbus_write_byte_data(client
, reg
,
146 } else if (sysfs_streq(MODE_ACTIVE_STRING
, buf
)) {
147 rc
= i2c_smbus_write_byte_data(client
, reg
,
157 static SENSOR_DEVICE_ATTR_RO(vendor
, ipsps_string
, vendor
);
158 static SENSOR_DEVICE_ATTR_RO(model
, ipsps_string
, model
);
159 static SENSOR_DEVICE_ATTR_RO(part_number
, ipsps_string
, part_number
);
160 static SENSOR_DEVICE_ATTR_RO(serial_number
, ipsps_string
, serial_number
);
161 static SENSOR_DEVICE_ATTR_RO(hw_version
, ipsps_string
, hw_version
);
162 static SENSOR_DEVICE_ATTR_RO(fw_version
, ipsps_fw_version
, fw_version
);
163 static SENSOR_DEVICE_ATTR_RW(mode
, ipsps_mode
, mode
);
165 static struct attribute
*ipsps_attrs
[] = {
166 &sensor_dev_attr_vendor
.dev_attr
.attr
,
167 &sensor_dev_attr_model
.dev_attr
.attr
,
168 &sensor_dev_attr_part_number
.dev_attr
.attr
,
169 &sensor_dev_attr_serial_number
.dev_attr
.attr
,
170 &sensor_dev_attr_hw_version
.dev_attr
.attr
,
171 &sensor_dev_attr_fw_version
.dev_attr
.attr
,
172 &sensor_dev_attr_mode
.dev_attr
.attr
,
176 ATTRIBUTE_GROUPS(ipsps
);
178 static struct pmbus_driver_info ipsps_info
= {
180 .func
[0] = PMBUS_HAVE_VIN
| PMBUS_HAVE_VOUT
| PMBUS_HAVE_IOUT
|
181 PMBUS_HAVE_IIN
| PMBUS_HAVE_POUT
| PMBUS_HAVE_PIN
|
182 PMBUS_HAVE_FAN12
| PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2
|
183 PMBUS_HAVE_TEMP3
| PMBUS_HAVE_STATUS_VOUT
|
184 PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_STATUS_INPUT
|
185 PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_STATUS_FAN12
,
186 .groups
= ipsps_groups
,
189 static struct pmbus_platform_data ipsps_pdata
= {
190 .flags
= PMBUS_SKIP_STATUS_CHECK
,
193 static int ipsps_probe(struct i2c_client
*client
)
195 client
->dev
.platform_data
= &ipsps_pdata
;
196 return pmbus_do_probe(client
, &ipsps_info
);
199 static const struct i2c_device_id ipsps_id
[] = {
203 MODULE_DEVICE_TABLE(i2c
, ipsps_id
);
206 static const struct of_device_id ipsps_of_match
[] = {
207 { .compatible
= "inspur,ipsps1" },
210 MODULE_DEVICE_TABLE(of
, ipsps_of_match
);
213 static struct i2c_driver ipsps_driver
= {
215 .name
= "inspur-ipsps",
216 .of_match_table
= of_match_ptr(ipsps_of_match
),
218 .probe_new
= ipsps_probe
,
219 .id_table
= ipsps_id
,
222 module_i2c_driver(ipsps_driver
);
224 MODULE_AUTHOR("John Wang");
225 MODULE_DESCRIPTION("PMBus driver for Inspur Power System power supplies");
226 MODULE_LICENSE("GPL");