root/drivers/hwmon/pmbus/inspur-ipsps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipsps_string_show
  2. ipsps_fw_version_show
  3. ipsps_mode_show
  4. ipsps_mode_store
  5. ipsps_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2019 Inspur Corp.
   4  */
   5 
   6 #include <linux/debugfs.h>
   7 #include <linux/device.h>
   8 #include <linux/fs.h>
   9 #include <linux/i2c.h>
  10 #include <linux/module.h>
  11 #include <linux/pmbus.h>
  12 #include <linux/hwmon-sysfs.h>
  13 
  14 #include "pmbus.h"
  15 
  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
  23 
  24 #define MODE_ACTIVE             0x55
  25 #define MODE_STANDBY            0x0E
  26 #define MODE_REDUNDANCY         0x00
  27 
  28 #define MODE_ACTIVE_STRING              "active"
  29 #define MODE_STANDBY_STRING             "standby"
  30 #define MODE_REDUNDANCY_STRING          "redundancy"
  31 
  32 enum ipsps_index {
  33         vendor,
  34         model,
  35         fw_version,
  36         part_number,
  37         serial_number,
  38         hw_version,
  39         mode,
  40         num_regs,
  41 };
  42 
  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,
  51 };
  52 
  53 static ssize_t ipsps_string_show(struct device *dev,
  54                                  struct device_attribute *devattr,
  55                                  char *buf)
  56 {
  57         u8 reg;
  58         int rc;
  59         char *p;
  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);
  63 
  64         reg = ipsps_regs[attr->index];
  65         rc = i2c_smbus_read_block_data(client, reg, data);
  66         if (rc < 0)
  67                 return rc;
  68 
  69         /* filled with printable characters, ending with # */
  70         p = memscan(data, '#', rc);
  71         *p = '\0';
  72 
  73         return snprintf(buf, PAGE_SIZE, "%s\n", data);
  74 }
  75 
  76 static ssize_t ipsps_fw_version_show(struct device *dev,
  77                                      struct device_attribute *devattr,
  78                                      char *buf)
  79 {
  80         u8 reg;
  81         int rc;
  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);
  85 
  86         reg = ipsps_regs[attr->index];
  87         rc = i2c_smbus_read_block_data(client, reg, data);
  88         if (rc < 0)
  89                 return rc;
  90 
  91         if (rc != 6)
  92                 return -EPROTO;
  93 
  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 */);
  97 }
  98 
  99 static ssize_t ipsps_mode_show(struct device *dev,
 100                                struct device_attribute *devattr, char *buf)
 101 {
 102         u8 reg;
 103         int rc;
 104         struct i2c_client *client = to_i2c_client(dev->parent);
 105         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 106 
 107         reg = ipsps_regs[attr->index];
 108         rc = i2c_smbus_read_byte_data(client, reg);
 109         if (rc < 0)
 110                 return rc;
 111 
 112         switch (rc) {
 113         case MODE_ACTIVE:
 114                 return snprintf(buf, PAGE_SIZE, "[%s] %s %s\n",
 115                                 MODE_ACTIVE_STRING,
 116                                 MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
 117         case MODE_STANDBY:
 118                 return snprintf(buf, PAGE_SIZE, "%s [%s] %s\n",
 119                                 MODE_ACTIVE_STRING,
 120                                 MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
 121         case MODE_REDUNDANCY:
 122                 return snprintf(buf, PAGE_SIZE, "%s %s [%s]\n",
 123                                 MODE_ACTIVE_STRING,
 124                                 MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
 125         default:
 126                 return snprintf(buf, PAGE_SIZE, "unspecified\n");
 127         }
 128 }
 129 
 130 static ssize_t ipsps_mode_store(struct device *dev,
 131                                 struct device_attribute *devattr,
 132                                 const char *buf, size_t count)
 133 {
 134         u8 reg;
 135         int rc;
 136         struct i2c_client *client = to_i2c_client(dev->parent);
 137         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 138 
 139         reg = ipsps_regs[attr->index];
 140         if (sysfs_streq(MODE_STANDBY_STRING, buf)) {
 141                 rc = i2c_smbus_write_byte_data(client, reg,
 142                                                MODE_STANDBY);
 143                 if (rc < 0)
 144                         return rc;
 145                 return count;
 146         } else if (sysfs_streq(MODE_ACTIVE_STRING, buf)) {
 147                 rc = i2c_smbus_write_byte_data(client, reg,
 148                                                MODE_ACTIVE);
 149                 if (rc < 0)
 150                         return rc;
 151                 return count;
 152         }
 153 
 154         return -EINVAL;
 155 }
 156 
 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);
 164 
 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,
 173         NULL,
 174 };
 175 
 176 ATTRIBUTE_GROUPS(ipsps);
 177 
 178 static struct pmbus_driver_info ipsps_info = {
 179         .pages = 1,
 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,
 187 };
 188 
 189 static struct pmbus_platform_data ipsps_pdata = {
 190         .flags = PMBUS_SKIP_STATUS_CHECK,
 191 };
 192 
 193 static int ipsps_probe(struct i2c_client *client,
 194                        const struct i2c_device_id *id)
 195 {
 196         client->dev.platform_data = &ipsps_pdata;
 197         return pmbus_do_probe(client, id, &ipsps_info);
 198 }
 199 
 200 static const struct i2c_device_id ipsps_id[] = {
 201         { "ipsps1", 0 },
 202         {}
 203 };
 204 MODULE_DEVICE_TABLE(i2c, ipsps_id);
 205 
 206 #ifdef CONFIG_OF
 207 static const struct of_device_id ipsps_of_match[] = {
 208         { .compatible = "inspur,ipsps1" },
 209         {}
 210 };
 211 MODULE_DEVICE_TABLE(of, ipsps_of_match);
 212 #endif
 213 
 214 static struct i2c_driver ipsps_driver = {
 215         .driver = {
 216                 .name = "inspur-ipsps",
 217                 .of_match_table = of_match_ptr(ipsps_of_match),
 218         },
 219         .probe = ipsps_probe,
 220         .remove = pmbus_do_remove,
 221         .id_table = ipsps_id,
 222 };
 223 
 224 module_i2c_driver(ipsps_driver);
 225 
 226 MODULE_AUTHOR("John Wang");
 227 MODULE_DESCRIPTION("PMBus driver for Inspur Power System power supplies");
 228 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */