linux/drivers/hwmon/pmbus/q54sj108a2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for Delta modules, Q54SJ108A2 series 1/4 Brick DC/DC
   4 * Regulated Power Module
   5 *
   6 * Copyright 2020 Delta LLC.
   7 */
   8
   9#include <linux/debugfs.h>
  10#include <linux/i2c.h>
  11#include <linux/module.h>
  12#include <linux/of_device.h>
  13#include "pmbus.h"
  14
  15#define STORE_DEFAULT_ALL               0x11
  16#define ERASE_BLACKBOX_DATA             0xD1
  17#define READ_HISTORY_EVENT_NUMBER       0xD2
  18#define READ_HISTORY_EVENTS             0xE0
  19#define SET_HISTORY_EVENT_OFFSET        0xE1
  20#define PMBUS_FLASH_KEY_WRITE           0xEC
  21
  22enum chips {
  23        q54sj108a2
  24};
  25
  26enum {
  27        Q54SJ108A2_DEBUGFS_OPERATION = 0,
  28        Q54SJ108A2_DEBUGFS_CLEARFAULT,
  29        Q54SJ108A2_DEBUGFS_WRITEPROTECT,
  30        Q54SJ108A2_DEBUGFS_STOREDEFAULT,
  31        Q54SJ108A2_DEBUGFS_VOOV_RESPONSE,
  32        Q54SJ108A2_DEBUGFS_IOOC_RESPONSE,
  33        Q54SJ108A2_DEBUGFS_PMBUS_VERSION,
  34        Q54SJ108A2_DEBUGFS_MFR_ID,
  35        Q54SJ108A2_DEBUGFS_MFR_MODEL,
  36        Q54SJ108A2_DEBUGFS_MFR_REVISION,
  37        Q54SJ108A2_DEBUGFS_MFR_LOCATION,
  38        Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE,
  39        Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET,
  40        Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET,
  41        Q54SJ108A2_DEBUGFS_BLACKBOX_READ,
  42        Q54SJ108A2_DEBUGFS_FLASH_KEY,
  43        Q54SJ108A2_DEBUGFS_NUM_ENTRIES
  44};
  45
  46struct q54sj108a2_data {
  47        enum chips chip;
  48        struct i2c_client *client;
  49
  50        int debugfs_entries[Q54SJ108A2_DEBUGFS_NUM_ENTRIES];
  51};
  52
  53#define to_psu(x, y) container_of((x), struct q54sj108a2_data, debugfs_entries[(y)])
  54
  55static struct pmbus_driver_info q54sj108a2_info[] = {
  56        [q54sj108a2] = {
  57                .pages = 1,
  58
  59                /* Source : Delta Q54SJ108A2 */
  60                .format[PSC_TEMPERATURE] = linear,
  61                .format[PSC_VOLTAGE_IN] = linear,
  62                .format[PSC_CURRENT_OUT] = linear,
  63
  64                .func[0] = PMBUS_HAVE_VIN |
  65                PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
  66                PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
  67                PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
  68                PMBUS_HAVE_STATUS_INPUT,
  69        },
  70};
  71
  72static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf,
  73                                       size_t count, loff_t *ppos)
  74{
  75        int rc;
  76        int *idxp = file->private_data;
  77        int idx = *idxp;
  78        struct q54sj108a2_data *psu = to_psu(idxp, idx);
  79        char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
  80        char data_char[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
  81        char *res;
  82
  83        switch (idx) {
  84        case Q54SJ108A2_DEBUGFS_OPERATION:
  85                rc = i2c_smbus_read_byte_data(psu->client, PMBUS_OPERATION);
  86                if (rc < 0)
  87                        return rc;
  88
  89                rc = snprintf(data, 3, "%02x", rc);
  90                break;
  91        case Q54SJ108A2_DEBUGFS_WRITEPROTECT:
  92                rc = i2c_smbus_read_byte_data(psu->client, PMBUS_WRITE_PROTECT);
  93                if (rc < 0)
  94                        return rc;
  95
  96                rc = snprintf(data, 3, "%02x", rc);
  97                break;
  98        case Q54SJ108A2_DEBUGFS_VOOV_RESPONSE:
  99                rc = i2c_smbus_read_byte_data(psu->client, PMBUS_VOUT_OV_FAULT_RESPONSE);
 100                if (rc < 0)
 101                        return rc;
 102
 103                rc = snprintf(data, 3, "%02x", rc);
 104                break;
 105        case Q54SJ108A2_DEBUGFS_IOOC_RESPONSE:
 106                rc = i2c_smbus_read_byte_data(psu->client, PMBUS_IOUT_OC_FAULT_RESPONSE);
 107                if (rc < 0)
 108                        return rc;
 109
 110                rc = snprintf(data, 3, "%02x", rc);
 111                break;
 112        case Q54SJ108A2_DEBUGFS_PMBUS_VERSION:
 113                rc = i2c_smbus_read_byte_data(psu->client, PMBUS_REVISION);
 114                if (rc < 0)
 115                        return rc;
 116
 117                rc = snprintf(data, 3, "%02x", rc);
 118                break;
 119        case Q54SJ108A2_DEBUGFS_MFR_ID:
 120                rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_ID, data);
 121                if (rc < 0)
 122                        return rc;
 123                break;
 124        case Q54SJ108A2_DEBUGFS_MFR_MODEL:
 125                rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_MODEL, data);
 126                if (rc < 0)
 127                        return rc;
 128                break;
 129        case Q54SJ108A2_DEBUGFS_MFR_REVISION:
 130                rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_REVISION, data);
 131                if (rc < 0)
 132                        return rc;
 133                break;
 134        case Q54SJ108A2_DEBUGFS_MFR_LOCATION:
 135                rc = i2c_smbus_read_block_data(psu->client, PMBUS_MFR_LOCATION, data);
 136                if (rc < 0)
 137                        return rc;
 138                break;
 139        case Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET:
 140                rc = i2c_smbus_read_byte_data(psu->client, READ_HISTORY_EVENT_NUMBER);
 141                if (rc < 0)
 142                        return rc;
 143
 144                rc = snprintf(data, 3, "%02x", rc);
 145                break;
 146        case Q54SJ108A2_DEBUGFS_BLACKBOX_READ:
 147                rc = i2c_smbus_read_block_data(psu->client, READ_HISTORY_EVENTS, data);
 148                if (rc < 0)
 149                        return rc;
 150
 151                res = bin2hex(data, data_char, 32);
 152                rc = res - data;
 153
 154                break;
 155        case Q54SJ108A2_DEBUGFS_FLASH_KEY:
 156                rc = i2c_smbus_read_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, data);
 157                if (rc < 0)
 158                        return rc;
 159
 160                res = bin2hex(data, data_char, 4);
 161                rc = res - data;
 162
 163                break;
 164        default:
 165                return -EINVAL;
 166        }
 167
 168        data[rc] = '\n';
 169        rc += 2;
 170
 171        return simple_read_from_buffer(buf, count, ppos, data, rc);
 172}
 173
 174static ssize_t q54sj108a2_debugfs_write(struct file *file, const char __user *buf,
 175                                        size_t count, loff_t *ppos)
 176{
 177        u8 flash_key[4];
 178        u8 dst_data;
 179        ssize_t rc;
 180        int *idxp = file->private_data;
 181        int idx = *idxp;
 182        struct q54sj108a2_data *psu = to_psu(idxp, idx);
 183
 184        rc = i2c_smbus_write_byte_data(psu->client, PMBUS_WRITE_PROTECT, 0);
 185        if (rc)
 186                return rc;
 187
 188        switch (idx) {
 189        case Q54SJ108A2_DEBUGFS_OPERATION:
 190                rc = kstrtou8_from_user(buf, count, 0, &dst_data);
 191                if (rc < 0)
 192                        return rc;
 193
 194                rc = i2c_smbus_write_byte_data(psu->client, PMBUS_OPERATION, dst_data);
 195                if (rc < 0)
 196                        return rc;
 197
 198                break;
 199        case Q54SJ108A2_DEBUGFS_CLEARFAULT:
 200                rc = i2c_smbus_write_byte(psu->client, PMBUS_CLEAR_FAULTS);
 201                if (rc < 0)
 202                        return rc;
 203
 204                break;
 205        case Q54SJ108A2_DEBUGFS_STOREDEFAULT:
 206                flash_key[0] = 0x7E;
 207                flash_key[1] = 0x15;
 208                flash_key[2] = 0xDC;
 209                flash_key[3] = 0x42;
 210                rc = i2c_smbus_write_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, 4, flash_key);
 211                if (rc < 0)
 212                        return rc;
 213
 214                rc = i2c_smbus_write_byte(psu->client, STORE_DEFAULT_ALL);
 215                if (rc < 0)
 216                        return rc;
 217
 218                break;
 219        case Q54SJ108A2_DEBUGFS_VOOV_RESPONSE:
 220                rc = kstrtou8_from_user(buf, count, 0, &dst_data);
 221                if (rc < 0)
 222                        return rc;
 223
 224                rc = i2c_smbus_write_byte_data(psu->client, PMBUS_VOUT_OV_FAULT_RESPONSE, dst_data);
 225                if (rc < 0)
 226                        return rc;
 227
 228                break;
 229        case Q54SJ108A2_DEBUGFS_IOOC_RESPONSE:
 230                rc = kstrtou8_from_user(buf, count, 0, &dst_data);
 231                if (rc < 0)
 232                        return rc;
 233
 234                rc = i2c_smbus_write_byte_data(psu->client, PMBUS_IOUT_OC_FAULT_RESPONSE, dst_data);
 235                if (rc < 0)
 236                        return rc;
 237
 238                break;
 239        case Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE:
 240                rc = i2c_smbus_write_byte(psu->client, ERASE_BLACKBOX_DATA);
 241                if (rc < 0)
 242                        return rc;
 243
 244                break;
 245        case Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET:
 246                rc = kstrtou8_from_user(buf, count, 0, &dst_data);
 247                if (rc < 0)
 248                        return rc;
 249
 250                rc = i2c_smbus_write_byte_data(psu->client, SET_HISTORY_EVENT_OFFSET, dst_data);
 251                if (rc < 0)
 252                        return rc;
 253
 254                break;
 255        default:
 256                return -EINVAL;
 257        }
 258
 259        return count;
 260}
 261
 262static const struct file_operations q54sj108a2_fops = {
 263        .llseek = noop_llseek,
 264        .read = q54sj108a2_debugfs_read,
 265        .write = q54sj108a2_debugfs_write,
 266        .open = simple_open,
 267};
 268
 269static const struct i2c_device_id q54sj108a2_id[] = {
 270        { "q54sj108a2", q54sj108a2 },
 271        { },
 272};
 273
 274MODULE_DEVICE_TABLE(i2c, q54sj108a2_id);
 275
 276static int q54sj108a2_probe(struct i2c_client *client)
 277{
 278        struct device *dev = &client->dev;
 279        u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
 280        enum chips chip_id;
 281        int ret, i;
 282        struct dentry *debugfs;
 283        struct dentry *q54sj108a2_dir;
 284        struct q54sj108a2_data *psu;
 285
 286        if (!i2c_check_functionality(client->adapter,
 287                                     I2C_FUNC_SMBUS_BYTE_DATA |
 288                                     I2C_FUNC_SMBUS_WORD_DATA |
 289                                     I2C_FUNC_SMBUS_BLOCK_DATA))
 290                return -ENODEV;
 291
 292        if (client->dev.of_node)
 293                chip_id = (enum chips)(unsigned long)of_device_get_match_data(dev);
 294        else
 295                chip_id = i2c_match_id(q54sj108a2_id, client)->driver_data;
 296
 297        ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
 298        if (ret < 0) {
 299                dev_err(&client->dev, "Failed to read Manufacturer ID\n");
 300                return ret;
 301        }
 302        if (ret != 6 || strncmp(buf, "DELTA", 5)) {
 303                buf[ret] = '\0';
 304                dev_err(dev, "Unsupported Manufacturer ID '%s'\n", buf);
 305                return -ENODEV;
 306        }
 307
 308        /*
 309         * The chips support reading PMBUS_MFR_MODEL.
 310         */
 311        ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
 312        if (ret < 0) {
 313                dev_err(dev, "Failed to read Manufacturer Model\n");
 314                return ret;
 315        }
 316        if (ret != 14 || strncmp(buf, "Q54SJ108A2", 10)) {
 317                buf[ret] = '\0';
 318                dev_err(dev, "Unsupported Manufacturer Model '%s'\n", buf);
 319                return -ENODEV;
 320        }
 321
 322        ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf);
 323        if (ret < 0) {
 324                dev_err(dev, "Failed to read Manufacturer Revision\n");
 325                return ret;
 326        }
 327        if (ret != 4 || buf[0] != 'S') {
 328                buf[ret] = '\0';
 329                dev_err(dev, "Unsupported Manufacturer Revision '%s'\n", buf);
 330                return -ENODEV;
 331        }
 332
 333        ret = pmbus_do_probe(client, &q54sj108a2_info[chip_id]);
 334        if (ret)
 335                return ret;
 336
 337        psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL);
 338        if (!psu)
 339                return 0;
 340
 341        psu->client = client;
 342
 343        debugfs = pmbus_get_debugfs_dir(client);
 344
 345        q54sj108a2_dir = debugfs_create_dir(client->name, debugfs);
 346
 347        for (i = 0; i < Q54SJ108A2_DEBUGFS_NUM_ENTRIES; ++i)
 348                psu->debugfs_entries[i] = i;
 349
 350        debugfs_create_file("operation", 0644, q54sj108a2_dir,
 351                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_OPERATION],
 352                            &q54sj108a2_fops);
 353        debugfs_create_file("clear_fault", 0200, q54sj108a2_dir,
 354                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_CLEARFAULT],
 355                            &q54sj108a2_fops);
 356        debugfs_create_file("write_protect", 0444, q54sj108a2_dir,
 357                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_WRITEPROTECT],
 358                            &q54sj108a2_fops);
 359        debugfs_create_file("store_default", 0200, q54sj108a2_dir,
 360                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_STOREDEFAULT],
 361                            &q54sj108a2_fops);
 362        debugfs_create_file("vo_ov_response", 0644, q54sj108a2_dir,
 363                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_VOOV_RESPONSE],
 364                            &q54sj108a2_fops);
 365        debugfs_create_file("io_oc_response", 0644, q54sj108a2_dir,
 366                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_IOOC_RESPONSE],
 367                            &q54sj108a2_fops);
 368        debugfs_create_file("pmbus_revision", 0444, q54sj108a2_dir,
 369                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_PMBUS_VERSION],
 370                            &q54sj108a2_fops);
 371        debugfs_create_file("mfr_id", 0444, q54sj108a2_dir,
 372                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_ID],
 373                            &q54sj108a2_fops);
 374        debugfs_create_file("mfr_model", 0444, q54sj108a2_dir,
 375                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_MODEL],
 376                            &q54sj108a2_fops);
 377        debugfs_create_file("mfr_revision", 0444, q54sj108a2_dir,
 378                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_REVISION],
 379                            &q54sj108a2_fops);
 380        debugfs_create_file("mfr_location", 0444, q54sj108a2_dir,
 381                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_MFR_LOCATION],
 382                            &q54sj108a2_fops);
 383        debugfs_create_file("blackbox_erase", 0200, q54sj108a2_dir,
 384                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_ERASE],
 385                            &q54sj108a2_fops);
 386        debugfs_create_file("blackbox_read_offset", 0444, q54sj108a2_dir,
 387                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_READ_OFFSET],
 388                            &q54sj108a2_fops);
 389        debugfs_create_file("blackbox_set_offset", 0200, q54sj108a2_dir,
 390                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_SET_OFFSET],
 391                            &q54sj108a2_fops);
 392        debugfs_create_file("blackbox_read", 0444, q54sj108a2_dir,
 393                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_BLACKBOX_READ],
 394                            &q54sj108a2_fops);
 395        debugfs_create_file("flash_key", 0444, q54sj108a2_dir,
 396                            &psu->debugfs_entries[Q54SJ108A2_DEBUGFS_FLASH_KEY],
 397                            &q54sj108a2_fops);
 398
 399        return 0;
 400}
 401
 402static const struct of_device_id q54sj108a2_of_match[] = {
 403        { .compatible = "delta,q54sj108a2", .data = (void *)q54sj108a2 },
 404        { },
 405};
 406
 407MODULE_DEVICE_TABLE(of, q54sj108a2_of_match);
 408
 409static struct i2c_driver q54sj108a2_driver = {
 410        .driver = {
 411                .name = "q54sj108a2",
 412                .of_match_table = q54sj108a2_of_match,
 413        },
 414        .probe_new = q54sj108a2_probe,
 415        .id_table = q54sj108a2_id,
 416};
 417
 418module_i2c_driver(q54sj108a2_driver);
 419
 420MODULE_AUTHOR("Xiao.Ma <xiao.mx.ma@deltaww.com>");
 421MODULE_DESCRIPTION("PMBus driver for Delta Q54SJ108A2 series modules");
 422MODULE_LICENSE("GPL");
 423MODULE_IMPORT_NS(PMBUS);
 424