| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Hardware monitoring driver for UCD90xxx Sequencer and System Health |
|---|
| 3 | 4 | * Controller series |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Copyright (C) 2011 Ericsson AB. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | | - * |
|---|
| 17 | | - * You should have received a copy of the GNU General Public License |
|---|
| 18 | | - * along with this program; if not, write to the Free Software |
|---|
| 19 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 20 | 7 | */ |
|---|
| 21 | 8 | |
|---|
| 22 | 9 | #include <linux/debugfs.h> |
|---|
| .. | .. |
|---|
| 28 | 15 | #include <linux/slab.h> |
|---|
| 29 | 16 | #include <linux/i2c.h> |
|---|
| 30 | 17 | #include <linux/pmbus.h> |
|---|
| 31 | | -#include <linux/gpio.h> |
|---|
| 32 | 18 | #include <linux/gpio/driver.h> |
|---|
| 33 | 19 | #include "pmbus.h" |
|---|
| 34 | 20 | |
|---|
| 35 | | -enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 }; |
|---|
| 21 | +enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd90320, ucd9090, |
|---|
| 22 | + ucd90910 }; |
|---|
| 36 | 23 | |
|---|
| 37 | 24 | #define UCD9000_MONITOR_CONFIG 0xd5 |
|---|
| 38 | 25 | #define UCD9000_NUM_PAGES 0xd6 |
|---|
| .. | .. |
|---|
| 52 | 39 | #define UCD9000_GPIO_OUTPUT 1 |
|---|
| 53 | 40 | |
|---|
| 54 | 41 | #define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) |
|---|
| 55 | | -#define UCD9000_MON_PAGE(x) ((x) & 0x0f) |
|---|
| 42 | +#define UCD9000_MON_PAGE(x) ((x) & 0x1f) |
|---|
| 56 | 43 | |
|---|
| 57 | 44 | #define UCD9000_MON_VOLTAGE 1 |
|---|
| 58 | 45 | #define UCD9000_MON_TEMPERATURE 2 |
|---|
| .. | .. |
|---|
| 64 | 51 | #define UCD9000_GPIO_NAME_LEN 16 |
|---|
| 65 | 52 | #define UCD9090_NUM_GPIOS 23 |
|---|
| 66 | 53 | #define UCD901XX_NUM_GPIOS 26 |
|---|
| 54 | +#define UCD90320_NUM_GPIOS 84 |
|---|
| 67 | 55 | #define UCD90910_NUM_GPIOS 26 |
|---|
| 68 | 56 | |
|---|
| 69 | 57 | #define UCD9000_DEBUGFS_NAME_LEN 24 |
|---|
| 70 | 58 | #define UCD9000_GPI_COUNT 8 |
|---|
| 59 | +#define UCD90320_GPI_COUNT 32 |
|---|
| 71 | 60 | |
|---|
| 72 | 61 | struct ucd9000_data { |
|---|
| 73 | 62 | u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; |
|---|
| .. | .. |
|---|
| 145 | 134 | {"ucd90120", ucd90120}, |
|---|
| 146 | 135 | {"ucd90124", ucd90124}, |
|---|
| 147 | 136 | {"ucd90160", ucd90160}, |
|---|
| 137 | + {"ucd90320", ucd90320}, |
|---|
| 148 | 138 | {"ucd9090", ucd9090}, |
|---|
| 149 | 139 | {"ucd90910", ucd90910}, |
|---|
| 150 | 140 | {} |
|---|
| 151 | 141 | }; |
|---|
| 152 | 142 | MODULE_DEVICE_TABLE(i2c, ucd9000_id); |
|---|
| 153 | 143 | |
|---|
| 154 | | -static const struct of_device_id ucd9000_of_match[] = { |
|---|
| 144 | +static const struct of_device_id __maybe_unused ucd9000_of_match[] = { |
|---|
| 155 | 145 | { |
|---|
| 156 | 146 | .compatible = "ti,ucd9000", |
|---|
| 157 | 147 | .data = (void *)ucd9000 |
|---|
| .. | .. |
|---|
| 167 | 157 | { |
|---|
| 168 | 158 | .compatible = "ti,ucd90160", |
|---|
| 169 | 159 | .data = (void *)ucd90160 |
|---|
| 160 | + }, |
|---|
| 161 | + { |
|---|
| 162 | + .compatible = "ti,ucd90320", |
|---|
| 163 | + .data = (void *)ucd90320 |
|---|
| 170 | 164 | }, |
|---|
| 171 | 165 | { |
|---|
| 172 | 166 | .compatible = "ti,ucd9090", |
|---|
| .. | .. |
|---|
| 336 | 330 | case ucd90160: |
|---|
| 337 | 331 | data->gpio.ngpio = UCD901XX_NUM_GPIOS; |
|---|
| 338 | 332 | break; |
|---|
| 333 | + case ucd90320: |
|---|
| 334 | + data->gpio.ngpio = UCD90320_NUM_GPIOS; |
|---|
| 335 | + break; |
|---|
| 339 | 336 | case ucd90910: |
|---|
| 340 | 337 | data->gpio.ngpio = UCD90910_NUM_GPIOS; |
|---|
| 341 | 338 | break; |
|---|
| .. | .. |
|---|
| 373 | 370 | #ifdef CONFIG_DEBUG_FS |
|---|
| 374 | 371 | static int ucd9000_get_mfr_status(struct i2c_client *client, u8 *buffer) |
|---|
| 375 | 372 | { |
|---|
| 376 | | - int ret = pmbus_set_page(client, 0); |
|---|
| 373 | + int ret = pmbus_set_page(client, 0, 0xff); |
|---|
| 377 | 374 | |
|---|
| 378 | 375 | if (ret < 0) |
|---|
| 379 | 376 | return ret; |
|---|
| .. | .. |
|---|
| 386 | 383 | struct ucd9000_debugfs_entry *entry = data; |
|---|
| 387 | 384 | struct i2c_client *client = entry->client; |
|---|
| 388 | 385 | u8 buffer[I2C_SMBUS_BLOCK_MAX]; |
|---|
| 389 | | - int ret; |
|---|
| 386 | + int ret, i; |
|---|
| 390 | 387 | |
|---|
| 391 | 388 | ret = ucd9000_get_mfr_status(client, buffer); |
|---|
| 392 | 389 | if (ret < 0) |
|---|
| 393 | 390 | return ret; |
|---|
| 394 | 391 | |
|---|
| 395 | 392 | /* |
|---|
| 396 | | - * Attribute only created for devices with gpi fault bits at bits |
|---|
| 397 | | - * 16-23, which is the second byte of the response. |
|---|
| 393 | + * GPI fault bits are in sets of 8, two bytes from end of response. |
|---|
| 398 | 394 | */ |
|---|
| 399 | | - *val = !!(buffer[1] & BIT(entry->index)); |
|---|
| 395 | + i = ret - 3 - entry->index / 8; |
|---|
| 396 | + if (i >= 0) |
|---|
| 397 | + *val = !!(buffer[i] & BIT(entry->index % 8)); |
|---|
| 400 | 398 | |
|---|
| 401 | 399 | return 0; |
|---|
| 402 | 400 | } |
|---|
| .. | .. |
|---|
| 436 | 434 | { |
|---|
| 437 | 435 | struct dentry *debugfs; |
|---|
| 438 | 436 | struct ucd9000_debugfs_entry *entries; |
|---|
| 439 | | - int i; |
|---|
| 437 | + int i, gpi_count; |
|---|
| 440 | 438 | char name[UCD9000_DEBUGFS_NAME_LEN]; |
|---|
| 441 | 439 | |
|---|
| 442 | 440 | debugfs = pmbus_get_debugfs_dir(client); |
|---|
| .. | .. |
|---|
| 449 | 447 | |
|---|
| 450 | 448 | /* |
|---|
| 451 | 449 | * Of the chips this driver supports, only the UCD9090, UCD90160, |
|---|
| 452 | | - * and UCD90910 report GPI faults in their MFR_STATUS register, so only |
|---|
| 453 | | - * create the GPI fault debugfs attributes for those chips. |
|---|
| 450 | + * UCD90320, and UCD90910 report GPI faults in their MFR_STATUS |
|---|
| 451 | + * register, so only create the GPI fault debugfs attributes for those |
|---|
| 452 | + * chips. |
|---|
| 454 | 453 | */ |
|---|
| 455 | 454 | if (mid->driver_data == ucd9090 || mid->driver_data == ucd90160 || |
|---|
| 456 | | - mid->driver_data == ucd90910) { |
|---|
| 455 | + mid->driver_data == ucd90320 || mid->driver_data == ucd90910) { |
|---|
| 456 | + gpi_count = mid->driver_data == ucd90320 ? UCD90320_GPI_COUNT |
|---|
| 457 | + : UCD9000_GPI_COUNT; |
|---|
| 457 | 458 | entries = devm_kcalloc(&client->dev, |
|---|
| 458 | | - UCD9000_GPI_COUNT, sizeof(*entries), |
|---|
| 459 | + gpi_count, sizeof(*entries), |
|---|
| 459 | 460 | GFP_KERNEL); |
|---|
| 460 | 461 | if (!entries) |
|---|
| 461 | 462 | return -ENOMEM; |
|---|
| 462 | 463 | |
|---|
| 463 | | - for (i = 0; i < UCD9000_GPI_COUNT; i++) { |
|---|
| 464 | + for (i = 0; i < gpi_count; i++) { |
|---|
| 464 | 465 | entries[i].client = client; |
|---|
| 465 | 466 | entries[i].index = i; |
|---|
| 466 | 467 | scnprintf(name, UCD9000_DEBUGFS_NAME_LEN, |
|---|
| .. | .. |
|---|
| 486 | 487 | } |
|---|
| 487 | 488 | #endif /* CONFIG_DEBUG_FS */ |
|---|
| 488 | 489 | |
|---|
| 489 | | -static int ucd9000_probe(struct i2c_client *client, |
|---|
| 490 | | - const struct i2c_device_id *id) |
|---|
| 490 | +static int ucd9000_probe(struct i2c_client *client) |
|---|
| 491 | 491 | { |
|---|
| 492 | 492 | u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; |
|---|
| 493 | 493 | struct ucd9000_data *data; |
|---|
| .. | .. |
|---|
| 522 | 522 | if (client->dev.of_node) |
|---|
| 523 | 523 | chip = (enum chips)of_device_get_match_data(&client->dev); |
|---|
| 524 | 524 | else |
|---|
| 525 | | - chip = id->driver_data; |
|---|
| 525 | + chip = mid->driver_data; |
|---|
| 526 | 526 | |
|---|
| 527 | | - if (chip != ucd9000 && chip != mid->driver_data) |
|---|
| 527 | + if (chip != ucd9000 && strcmp(client->name, mid->name) != 0) |
|---|
| 528 | 528 | dev_notice(&client->dev, |
|---|
| 529 | 529 | "Device mismatch: Configured %s, detected %s\n", |
|---|
| 530 | | - id->name, mid->name); |
|---|
| 530 | + client->name, mid->name); |
|---|
| 531 | 531 | |
|---|
| 532 | 532 | data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), |
|---|
| 533 | 533 | GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 602 | 602 | |
|---|
| 603 | 603 | ucd9000_probe_gpio(client, mid, data); |
|---|
| 604 | 604 | |
|---|
| 605 | | - ret = pmbus_do_probe(client, mid, info); |
|---|
| 605 | + ret = pmbus_do_probe(client, info); |
|---|
| 606 | 606 | if (ret) |
|---|
| 607 | 607 | return ret; |
|---|
| 608 | 608 | |
|---|
| .. | .. |
|---|
| 620 | 620 | .name = "ucd9000", |
|---|
| 621 | 621 | .of_match_table = of_match_ptr(ucd9000_of_match), |
|---|
| 622 | 622 | }, |
|---|
| 623 | | - .probe = ucd9000_probe, |
|---|
| 623 | + .probe_new = ucd9000_probe, |
|---|
| 624 | 624 | .remove = pmbus_do_remove, |
|---|
| 625 | 625 | .id_table = ucd9000_id, |
|---|
| 626 | 626 | }; |
|---|