linux/drivers/hwmon/tps23861.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2020 Sartura Ltd.
   4 *
   5 * Driver for the TI TPS23861 PoE PSE.
   6 *
   7 * Author: Robert Marko <robert.marko@sartura.hr>
   8 */
   9
  10#include <linux/bitfield.h>
  11#include <linux/debugfs.h>
  12#include <linux/delay.h>
  13#include <linux/hwmon-sysfs.h>
  14#include <linux/hwmon.h>
  15#include <linux/i2c.h>
  16#include <linux/module.h>
  17#include <linux/of_device.h>
  18#include <linux/regmap.h>
  19
  20#define TEMPERATURE                     0x2c
  21#define INPUT_VOLTAGE_LSB               0x2e
  22#define INPUT_VOLTAGE_MSB               0x2f
  23#define PORT_1_CURRENT_LSB              0x30
  24#define PORT_1_CURRENT_MSB              0x31
  25#define PORT_1_VOLTAGE_LSB              0x32
  26#define PORT_1_VOLTAGE_MSB              0x33
  27#define PORT_2_CURRENT_LSB              0x34
  28#define PORT_2_CURRENT_MSB              0x35
  29#define PORT_2_VOLTAGE_LSB              0x36
  30#define PORT_2_VOLTAGE_MSB              0x37
  31#define PORT_3_CURRENT_LSB              0x38
  32#define PORT_3_CURRENT_MSB              0x39
  33#define PORT_3_VOLTAGE_LSB              0x3a
  34#define PORT_3_VOLTAGE_MSB              0x3b
  35#define PORT_4_CURRENT_LSB              0x3c
  36#define PORT_4_CURRENT_MSB              0x3d
  37#define PORT_4_VOLTAGE_LSB              0x3e
  38#define PORT_4_VOLTAGE_MSB              0x3f
  39#define PORT_N_CURRENT_LSB_OFFSET       0x04
  40#define PORT_N_VOLTAGE_LSB_OFFSET       0x04
  41#define VOLTAGE_CURRENT_MASK            GENMASK(13, 0)
  42#define PORT_1_RESISTANCE_LSB           0x60
  43#define PORT_1_RESISTANCE_MSB           0x61
  44#define PORT_2_RESISTANCE_LSB           0x62
  45#define PORT_2_RESISTANCE_MSB           0x63
  46#define PORT_3_RESISTANCE_LSB           0x64
  47#define PORT_3_RESISTANCE_MSB           0x65
  48#define PORT_4_RESISTANCE_LSB           0x66
  49#define PORT_4_RESISTANCE_MSB           0x67
  50#define PORT_N_RESISTANCE_LSB_OFFSET    0x02
  51#define PORT_RESISTANCE_MASK            GENMASK(13, 0)
  52#define PORT_RESISTANCE_RSN_MASK        GENMASK(15, 14)
  53#define PORT_RESISTANCE_RSN_OTHER       0
  54#define PORT_RESISTANCE_RSN_LOW         1
  55#define PORT_RESISTANCE_RSN_OPEN        2
  56#define PORT_RESISTANCE_RSN_SHORT       3
  57#define PORT_1_STATUS                   0x0c
  58#define PORT_2_STATUS                   0x0d
  59#define PORT_3_STATUS                   0x0e
  60#define PORT_4_STATUS                   0x0f
  61#define PORT_STATUS_CLASS_MASK          GENMASK(7, 4)
  62#define PORT_STATUS_DETECT_MASK         GENMASK(3, 0)
  63#define PORT_CLASS_UNKNOWN              0
  64#define PORT_CLASS_1                    1
  65#define PORT_CLASS_2                    2
  66#define PORT_CLASS_3                    3
  67#define PORT_CLASS_4                    4
  68#define PORT_CLASS_RESERVED             5
  69#define PORT_CLASS_0                    6
  70#define PORT_CLASS_OVERCURRENT          7
  71#define PORT_CLASS_MISMATCH             8
  72#define PORT_DETECT_UNKNOWN             0
  73#define PORT_DETECT_SHORT               1
  74#define PORT_DETECT_RESERVED            2
  75#define PORT_DETECT_RESISTANCE_LOW      3
  76#define PORT_DETECT_RESISTANCE_OK       4
  77#define PORT_DETECT_RESISTANCE_HIGH     5
  78#define PORT_DETECT_OPEN_CIRCUIT        6
  79#define PORT_DETECT_RESERVED_2          7
  80#define PORT_DETECT_MOSFET_FAULT        8
  81#define PORT_DETECT_LEGACY              9
  82/* Measurment beyond clamp voltage */
  83#define PORT_DETECT_CAPACITANCE_INVALID_BEYOND  10
  84/* Insufficient voltage delta */
  85#define PORT_DETECT_CAPACITANCE_INVALID_DELTA   11
  86#define PORT_DETECT_CAPACITANCE_OUT_OF_RANGE    12
  87#define POE_PLUS                        0x40
  88#define OPERATING_MODE                  0x12
  89#define OPERATING_MODE_OFF              0
  90#define OPERATING_MODE_MANUAL           1
  91#define OPERATING_MODE_SEMI             2
  92#define OPERATING_MODE_AUTO             3
  93#define OPERATING_MODE_PORT_1_MASK      GENMASK(1, 0)
  94#define OPERATING_MODE_PORT_2_MASK      GENMASK(3, 2)
  95#define OPERATING_MODE_PORT_3_MASK      GENMASK(5, 4)
  96#define OPERATING_MODE_PORT_4_MASK      GENMASK(7, 6)
  97
  98#define DETECT_CLASS_RESTART            0x18
  99#define POWER_ENABLE                    0x19
 100#define TPS23861_NUM_PORTS              4
 101
 102#define TPS23861_GENERAL_MASK_1         0x17
 103#define TPS23861_CURRENT_SHUNT_MASK     BIT(0)
 104
 105#define TEMPERATURE_LSB                 652 /* 0.652 degrees Celsius */
 106#define VOLTAGE_LSB                     3662 /* 3.662 mV */
 107#define SHUNT_RESISTOR_DEFAULT          255000 /* 255 mOhm */
 108#define CURRENT_LSB_250                 62260 /* 62.260 uA */
 109#define CURRENT_LSB_255                 61039 /* 61.039 uA */
 110#define RESISTANCE_LSB                  110966 /* 11.0966 Ohm*/
 111#define RESISTANCE_LSB_LOW              157216 /* 15.7216 Ohm*/
 112
 113struct tps23861_data {
 114        struct regmap *regmap;
 115        u32 shunt_resistor;
 116        struct i2c_client *client;
 117        struct dentry *debugfs_dir;
 118};
 119
 120static struct regmap_config tps23861_regmap_config = {
 121        .reg_bits = 8,
 122        .val_bits = 8,
 123        .max_register = 0x6f,
 124};
 125
 126static int tps23861_read_temp(struct tps23861_data *data, long *val)
 127{
 128        unsigned int regval;
 129        int err;
 130
 131        err = regmap_read(data->regmap, TEMPERATURE, &regval);
 132        if (err < 0)
 133                return err;
 134
 135        *val = (regval * TEMPERATURE_LSB) - 20000;
 136
 137        return 0;
 138}
 139
 140static int tps23861_read_voltage(struct tps23861_data *data, int channel,
 141                                 long *val)
 142{
 143        unsigned int regval;
 144        int err;
 145
 146        if (channel < TPS23861_NUM_PORTS) {
 147                err = regmap_bulk_read(data->regmap,
 148                                       PORT_1_VOLTAGE_LSB + channel * PORT_N_VOLTAGE_LSB_OFFSET,
 149                                       &regval, 2);
 150        } else {
 151                err = regmap_bulk_read(data->regmap,
 152                                       INPUT_VOLTAGE_LSB,
 153                                       &regval, 2);
 154        }
 155        if (err < 0)
 156                return err;
 157
 158        *val = (FIELD_GET(VOLTAGE_CURRENT_MASK, regval) * VOLTAGE_LSB) / 1000;
 159
 160        return 0;
 161}
 162
 163static int tps23861_read_current(struct tps23861_data *data, int channel,
 164                                 long *val)
 165{
 166        unsigned int current_lsb;
 167        unsigned int regval;
 168        int err;
 169
 170        if (data->shunt_resistor == SHUNT_RESISTOR_DEFAULT)
 171                current_lsb = CURRENT_LSB_255;
 172        else
 173                current_lsb = CURRENT_LSB_250;
 174
 175        err = regmap_bulk_read(data->regmap,
 176                               PORT_1_CURRENT_LSB + channel * PORT_N_CURRENT_LSB_OFFSET,
 177                               &regval, 2);
 178        if (err < 0)
 179                return err;
 180
 181        *val = (FIELD_GET(VOLTAGE_CURRENT_MASK, regval) * current_lsb) / 1000000;
 182
 183        return 0;
 184}
 185
 186static int tps23861_port_disable(struct tps23861_data *data, int channel)
 187{
 188        unsigned int regval = 0;
 189        int err;
 190
 191        regval |= BIT(channel + 4);
 192        err = regmap_write(data->regmap, POWER_ENABLE, regval);
 193
 194        return err;
 195}
 196
 197static int tps23861_port_enable(struct tps23861_data *data, int channel)
 198{
 199        unsigned int regval = 0;
 200        int err;
 201
 202        regval |= BIT(channel);
 203        regval |= BIT(channel + 4);
 204        err = regmap_write(data->regmap, DETECT_CLASS_RESTART, regval);
 205
 206        return err;
 207}
 208
 209static umode_t tps23861_is_visible(const void *data, enum hwmon_sensor_types type,
 210                                   u32 attr, int channel)
 211{
 212        switch (type) {
 213        case hwmon_temp:
 214                switch (attr) {
 215                case hwmon_temp_input:
 216                case hwmon_temp_label:
 217                        return 0444;
 218                default:
 219                        return 0;
 220                }
 221        case hwmon_in:
 222                switch (attr) {
 223                case hwmon_in_input:
 224                case hwmon_in_label:
 225                        return 0444;
 226                case hwmon_in_enable:
 227                        return 0200;
 228                default:
 229                        return 0;
 230                }
 231        case hwmon_curr:
 232                switch (attr) {
 233                case hwmon_curr_input:
 234                case hwmon_curr_label:
 235                        return 0444;
 236                default:
 237                        return 0;
 238                }
 239        default:
 240                return 0;
 241        }
 242}
 243
 244static int tps23861_write(struct device *dev, enum hwmon_sensor_types type,
 245                          u32 attr, int channel, long val)
 246{
 247        struct tps23861_data *data = dev_get_drvdata(dev);
 248        int err;
 249
 250        switch (type) {
 251        case hwmon_in:
 252                switch (attr) {
 253                case hwmon_in_enable:
 254                        if (val == 0)
 255                                err = tps23861_port_disable(data, channel);
 256                        else if (val == 1)
 257                                err = tps23861_port_enable(data, channel);
 258                        else
 259                                err = -EINVAL;
 260                        break;
 261                default:
 262                        return -EOPNOTSUPP;
 263                }
 264                break;
 265        default:
 266                return -EOPNOTSUPP;
 267        }
 268
 269        return err;
 270}
 271
 272static int tps23861_read(struct device *dev, enum hwmon_sensor_types type,
 273                         u32 attr, int channel, long *val)
 274{
 275        struct tps23861_data *data = dev_get_drvdata(dev);
 276        int err;
 277
 278        switch (type) {
 279        case hwmon_temp:
 280                switch (attr) {
 281                case hwmon_temp_input:
 282                        err = tps23861_read_temp(data, val);
 283                        break;
 284                default:
 285                        return -EOPNOTSUPP;
 286                }
 287                break;
 288        case hwmon_in:
 289                switch (attr) {
 290                case hwmon_in_input:
 291                        err = tps23861_read_voltage(data, channel, val);
 292                        break;
 293                default:
 294                        return -EOPNOTSUPP;
 295                }
 296                break;
 297        case hwmon_curr:
 298                switch (attr) {
 299                case hwmon_curr_input:
 300                        err = tps23861_read_current(data, channel, val);
 301                        break;
 302                default:
 303                        return -EOPNOTSUPP;
 304                }
 305                break;
 306        default:
 307                return -EOPNOTSUPP;
 308        }
 309
 310        return err;
 311}
 312
 313static const char * const tps23861_port_label[] = {
 314        "Port1",
 315        "Port2",
 316        "Port3",
 317        "Port4",
 318        "Input",
 319};
 320
 321static int tps23861_read_string(struct device *dev,
 322                                enum hwmon_sensor_types type,
 323                                u32 attr, int channel, const char **str)
 324{
 325        switch (type) {
 326        case hwmon_in:
 327        case hwmon_curr:
 328                *str = tps23861_port_label[channel];
 329                break;
 330        case hwmon_temp:
 331                *str = "Die";
 332                break;
 333        default:
 334                return -EOPNOTSUPP;
 335        }
 336
 337        return 0;
 338}
 339
 340static const struct hwmon_channel_info *tps23861_info[] = {
 341        HWMON_CHANNEL_INFO(chip,
 342                           HWMON_C_REGISTER_TZ),
 343        HWMON_CHANNEL_INFO(temp,
 344                           HWMON_T_INPUT | HWMON_T_LABEL),
 345        HWMON_CHANNEL_INFO(in,
 346                           HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
 347                           HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
 348                           HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
 349                           HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
 350                           HWMON_I_INPUT | HWMON_I_LABEL),
 351        HWMON_CHANNEL_INFO(curr,
 352                           HWMON_C_INPUT | HWMON_C_LABEL,
 353                           HWMON_C_INPUT | HWMON_C_LABEL,
 354                           HWMON_C_INPUT | HWMON_C_LABEL,
 355                           HWMON_C_INPUT | HWMON_C_LABEL),
 356        NULL
 357};
 358
 359static const struct hwmon_ops tps23861_hwmon_ops = {
 360        .is_visible = tps23861_is_visible,
 361        .write = tps23861_write,
 362        .read = tps23861_read,
 363        .read_string = tps23861_read_string,
 364};
 365
 366static const struct hwmon_chip_info tps23861_chip_info = {
 367        .ops = &tps23861_hwmon_ops,
 368        .info = tps23861_info,
 369};
 370
 371static char *tps23861_port_operating_mode(struct tps23861_data *data, int port)
 372{
 373        unsigned int regval;
 374        int mode;
 375
 376        regmap_read(data->regmap, OPERATING_MODE, &regval);
 377
 378        switch (port) {
 379        case 1:
 380                mode = FIELD_GET(OPERATING_MODE_PORT_1_MASK, regval);
 381                break;
 382        case 2:
 383                mode = FIELD_GET(OPERATING_MODE_PORT_2_MASK, regval);
 384                break;
 385        case 3:
 386                mode = FIELD_GET(OPERATING_MODE_PORT_3_MASK, regval);
 387                break;
 388        case 4:
 389                mode = FIELD_GET(OPERATING_MODE_PORT_4_MASK, regval);
 390                break;
 391        default:
 392                mode = -EINVAL;
 393        }
 394
 395        switch (mode) {
 396        case OPERATING_MODE_OFF:
 397                return "Off";
 398        case OPERATING_MODE_MANUAL:
 399                return "Manual";
 400        case OPERATING_MODE_SEMI:
 401                return "Semi-Auto";
 402        case OPERATING_MODE_AUTO:
 403                return "Auto";
 404        default:
 405                return "Invalid";
 406        }
 407}
 408
 409static char *tps23861_port_detect_status(struct tps23861_data *data, int port)
 410{
 411        unsigned int regval;
 412
 413        regmap_read(data->regmap,
 414                    PORT_1_STATUS + (port - 1),
 415                    &regval);
 416
 417        switch (FIELD_GET(PORT_STATUS_DETECT_MASK, regval)) {
 418        case PORT_DETECT_UNKNOWN:
 419                return "Unknown device";
 420        case PORT_DETECT_SHORT:
 421                return "Short circuit";
 422        case PORT_DETECT_RESISTANCE_LOW:
 423                return "Too low resistance";
 424        case PORT_DETECT_RESISTANCE_OK:
 425                return "Valid resistance";
 426        case PORT_DETECT_RESISTANCE_HIGH:
 427                return "Too high resistance";
 428        case PORT_DETECT_OPEN_CIRCUIT:
 429                return "Open circuit";
 430        case PORT_DETECT_MOSFET_FAULT:
 431                return "MOSFET fault";
 432        case PORT_DETECT_LEGACY:
 433                return "Legacy device";
 434        case PORT_DETECT_CAPACITANCE_INVALID_BEYOND:
 435                return "Invalid capacitance, beyond clamp voltage";
 436        case PORT_DETECT_CAPACITANCE_INVALID_DELTA:
 437                return "Invalid capacitance, insufficient voltage delta";
 438        case PORT_DETECT_CAPACITANCE_OUT_OF_RANGE:
 439                return "Valid capacitance, outside of legacy range";
 440        case PORT_DETECT_RESERVED:
 441        case PORT_DETECT_RESERVED_2:
 442        default:
 443                return "Invalid";
 444        }
 445}
 446
 447static char *tps23861_port_class_status(struct tps23861_data *data, int port)
 448{
 449        unsigned int regval;
 450
 451        regmap_read(data->regmap,
 452                    PORT_1_STATUS + (port - 1),
 453                    &regval);
 454
 455        switch (FIELD_GET(PORT_STATUS_CLASS_MASK, regval)) {
 456        case PORT_CLASS_UNKNOWN:
 457                return "Unknown";
 458        case PORT_CLASS_RESERVED:
 459        case PORT_CLASS_0:
 460                return "0";
 461        case PORT_CLASS_1:
 462                return "1";
 463        case PORT_CLASS_2:
 464                return "2";
 465        case PORT_CLASS_3:
 466                return "3";
 467        case PORT_CLASS_4:
 468                return "4";
 469        case PORT_CLASS_OVERCURRENT:
 470                return "Overcurrent";
 471        case PORT_CLASS_MISMATCH:
 472                return "Mismatch";
 473        default:
 474                return "Invalid";
 475        }
 476}
 477
 478static char *tps23861_port_poe_plus_status(struct tps23861_data *data, int port)
 479{
 480        unsigned int regval;
 481
 482        regmap_read(data->regmap, POE_PLUS, &regval);
 483
 484        if (BIT(port + 3) & regval)
 485                return "Yes";
 486        else
 487                return "No";
 488}
 489
 490static int tps23861_port_resistance(struct tps23861_data *data, int port)
 491{
 492        u16 regval;
 493
 494        regmap_bulk_read(data->regmap,
 495                         PORT_1_RESISTANCE_LSB + PORT_N_RESISTANCE_LSB_OFFSET * (port - 1),
 496                         &regval,
 497                         2);
 498
 499        switch (FIELD_GET(PORT_RESISTANCE_RSN_MASK, regval)) {
 500        case PORT_RESISTANCE_RSN_OTHER:
 501                return (FIELD_GET(PORT_RESISTANCE_MASK, regval) * RESISTANCE_LSB) / 10000;
 502        case PORT_RESISTANCE_RSN_LOW:
 503                return (FIELD_GET(PORT_RESISTANCE_MASK, regval) * RESISTANCE_LSB_LOW) / 10000;
 504        case PORT_RESISTANCE_RSN_SHORT:
 505        case PORT_RESISTANCE_RSN_OPEN:
 506        default:
 507                return 0;
 508        }
 509}
 510
 511static int tps23861_port_status_show(struct seq_file *s, void *data)
 512{
 513        struct tps23861_data *priv = s->private;
 514        int i;
 515
 516        for (i = 1; i < TPS23861_NUM_PORTS + 1; i++) {
 517                seq_printf(s, "Port: \t\t%d\n", i);
 518                seq_printf(s, "Operating mode: %s\n", tps23861_port_operating_mode(priv, i));
 519                seq_printf(s, "Detected: \t%s\n", tps23861_port_detect_status(priv, i));
 520                seq_printf(s, "Class: \t\t%s\n", tps23861_port_class_status(priv, i));
 521                seq_printf(s, "PoE Plus: \t%s\n", tps23861_port_poe_plus_status(priv, i));
 522                seq_printf(s, "Resistance: \t%d\n", tps23861_port_resistance(priv, i));
 523                seq_putc(s, '\n');
 524        }
 525
 526        return 0;
 527}
 528
 529DEFINE_SHOW_ATTRIBUTE(tps23861_port_status);
 530
 531static void tps23861_init_debugfs(struct tps23861_data *data)
 532{
 533        data->debugfs_dir = debugfs_create_dir(data->client->name, NULL);
 534
 535        debugfs_create_file("port_status",
 536                            0400,
 537                            data->debugfs_dir,
 538                            data,
 539                            &tps23861_port_status_fops);
 540}
 541
 542static int tps23861_probe(struct i2c_client *client)
 543{
 544        struct device *dev = &client->dev;
 545        struct tps23861_data *data;
 546        struct device *hwmon_dev;
 547        u32 shunt_resistor;
 548
 549        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 550        if (!data)
 551                return -ENOMEM;
 552
 553        data->client = client;
 554        i2c_set_clientdata(client, data);
 555
 556        data->regmap = devm_regmap_init_i2c(client, &tps23861_regmap_config);
 557        if (IS_ERR(data->regmap)) {
 558                dev_err(dev, "failed to allocate register map\n");
 559                return PTR_ERR(data->regmap);
 560        }
 561
 562        if (!of_property_read_u32(dev->of_node, "shunt-resistor-micro-ohms", &shunt_resistor))
 563                data->shunt_resistor = shunt_resistor;
 564        else
 565                data->shunt_resistor = SHUNT_RESISTOR_DEFAULT;
 566
 567        if (data->shunt_resistor == SHUNT_RESISTOR_DEFAULT)
 568                regmap_clear_bits(data->regmap,
 569                                  TPS23861_GENERAL_MASK_1,
 570                                  TPS23861_CURRENT_SHUNT_MASK);
 571        else
 572                regmap_set_bits(data->regmap,
 573                                TPS23861_GENERAL_MASK_1,
 574                                TPS23861_CURRENT_SHUNT_MASK);
 575
 576        hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
 577                                                         data, &tps23861_chip_info,
 578                                                         NULL);
 579        if (IS_ERR(hwmon_dev))
 580                return PTR_ERR(hwmon_dev);
 581
 582        tps23861_init_debugfs(data);
 583
 584        return 0;
 585}
 586
 587static int tps23861_remove(struct i2c_client *client)
 588{
 589        struct tps23861_data *data = i2c_get_clientdata(client);
 590
 591        debugfs_remove_recursive(data->debugfs_dir);
 592
 593        return 0;
 594}
 595
 596static const struct of_device_id __maybe_unused tps23861_of_match[] = {
 597        { .compatible = "ti,tps23861", },
 598        { },
 599};
 600MODULE_DEVICE_TABLE(of, tps23861_of_match);
 601
 602static struct i2c_driver tps23861_driver = {
 603        .probe_new              = tps23861_probe,
 604        .remove                 = tps23861_remove,
 605        .driver = {
 606                .name           = "tps23861",
 607                .of_match_table = of_match_ptr(tps23861_of_match),
 608        },
 609};
 610module_i2c_driver(tps23861_driver);
 611
 612MODULE_LICENSE("GPL");
 613MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>");
 614MODULE_DESCRIPTION("TI TPS23861 PoE PSE");
 615