aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreajames@linux.vnet.ibm.com <eajames@linux.vnet.ibm.com>2018-01-11 12:20:10 -0500
committerGuenter Roeck <linux@roeck-us.net>2018-01-11 13:28:35 -0500
commitef9e1cdf419a37065364edb47bd6dd9aee1bcb7d (patch)
treee629317138b3341290f0ead34888000a35298e3e
parent4471879acf926221231fe68ebc30f9cad0d7f7c8 (diff)
hwmon: (pmbus/cffps) Add led class device for power supply fault led
This power supply device doesn't correctly manage it's own fault led. Add an led class device and register it so that userspace can manage power supply fault led as necessary. Signed-off-by: Eddie James <eajames@linux.vnet.ibm.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c96
1 files changed, 88 insertions, 8 deletions
diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index 2d6f4f41e736..93d9a9ea112b 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -13,6 +13,7 @@
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/jiffies.h> 15#include <linux/jiffies.h>
16#include <linux/leds.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/mutex.h> 18#include <linux/mutex.h>
18#include <linux/pmbus.h> 19#include <linux/pmbus.h>
@@ -25,6 +26,7 @@
25#define CFFPS_CCIN_CMD 0xBD 26#define CFFPS_CCIN_CMD 0xBD
26#define CFFPS_FW_CMD_START 0xFA 27#define CFFPS_FW_CMD_START 0xFA
27#define CFFPS_FW_NUM_BYTES 4 28#define CFFPS_FW_NUM_BYTES 4
29#define CFFPS_SYS_CONFIG_CMD 0xDA
28 30
29#define CFFPS_INPUT_HISTORY_CMD 0xD6 31#define CFFPS_INPUT_HISTORY_CMD 0xD6
30#define CFFPS_INPUT_HISTORY_SIZE 100 32#define CFFPS_INPUT_HISTORY_SIZE 100
@@ -39,6 +41,11 @@
39#define CFFPS_MFR_VAUX_FAULT BIT(6) 41#define CFFPS_MFR_VAUX_FAULT BIT(6)
40#define CFFPS_MFR_CURRENT_SHARE_WARNING BIT(7) 42#define CFFPS_MFR_CURRENT_SHARE_WARNING BIT(7)
41 43
44#define CFFPS_LED_BLINK BIT(0)
45#define CFFPS_LED_ON BIT(1)
46#define CFFPS_LED_OFF BIT(2)
47#define CFFPS_BLINK_RATE_MS 250
48
42enum { 49enum {
43 CFFPS_DEBUGFS_INPUT_HISTORY = 0, 50 CFFPS_DEBUGFS_INPUT_HISTORY = 0,
44 CFFPS_DEBUGFS_FRU, 51 CFFPS_DEBUGFS_FRU,
@@ -63,6 +70,10 @@ struct ibm_cffps {
63 struct ibm_cffps_input_history input_history; 70 struct ibm_cffps_input_history input_history;
64 71
65 int debugfs_entries[CFFPS_DEBUGFS_NUM_ENTRIES]; 72 int debugfs_entries[CFFPS_DEBUGFS_NUM_ENTRIES];
73
74 char led_name[32];
75 u8 led_state;
76 struct led_classdev led;
66}; 77};
67 78
68#define to_psu(x, y) container_of((x), struct ibm_cffps, debugfs_entries[(y)]) 79#define to_psu(x, y) container_of((x), struct ibm_cffps, debugfs_entries[(y)])
@@ -258,6 +269,69 @@ static int ibm_cffps_read_word_data(struct i2c_client *client, int page,
258 return rc; 269 return rc;
259} 270}
260 271
272static void ibm_cffps_led_brightness_set(struct led_classdev *led_cdev,
273 enum led_brightness brightness)
274{
275 int rc;
276 struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led);
277
278 if (brightness == LED_OFF) {
279 psu->led_state = CFFPS_LED_OFF;
280 } else {
281 brightness = LED_FULL;
282 if (psu->led_state != CFFPS_LED_BLINK)
283 psu->led_state = CFFPS_LED_ON;
284 }
285
286 rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
287 psu->led_state);
288 if (rc < 0)
289 return;
290
291 led_cdev->brightness = brightness;
292}
293
294static int ibm_cffps_led_blink_set(struct led_classdev *led_cdev,
295 unsigned long *delay_on,
296 unsigned long *delay_off)
297{
298 int rc;
299 struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led);
300
301 psu->led_state = CFFPS_LED_BLINK;
302
303 if (led_cdev->brightness == LED_OFF)
304 return 0;
305
306 rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
307 CFFPS_LED_BLINK);
308 if (rc < 0)
309 return rc;
310
311 *delay_on = CFFPS_BLINK_RATE_MS;
312 *delay_off = CFFPS_BLINK_RATE_MS;
313
314 return 0;
315}
316
317static void ibm_cffps_create_led_class(struct ibm_cffps *psu)
318{
319 int rc;
320 struct i2c_client *client = psu->client;
321 struct device *dev = &client->dev;
322
323 snprintf(psu->led_name, sizeof(psu->led_name), "%s-%02x", client->name,
324 client->addr);
325 psu->led.name = psu->led_name;
326 psu->led.max_brightness = LED_FULL;
327 psu->led.brightness_set = ibm_cffps_led_brightness_set;
328 psu->led.blink_set = ibm_cffps_led_blink_set;
329
330 rc = devm_led_classdev_register(dev, &psu->led);
331 if (rc)
332 dev_warn(dev, "failed to register led class: %d\n", rc);
333}
334
261static struct pmbus_driver_info ibm_cffps_info = { 335static struct pmbus_driver_info ibm_cffps_info = {
262 .pages = 1, 336 .pages = 1,
263 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | 337 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
@@ -286,6 +360,20 @@ static int ibm_cffps_probe(struct i2c_client *client,
286 if (rc) 360 if (rc)
287 return rc; 361 return rc;
288 362
363 /*
364 * Don't fail the probe if there isn't enough memory for leds and
365 * debugfs.
366 */
367 psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL);
368 if (!psu)
369 return 0;
370
371 psu->client = client;
372 mutex_init(&psu->input_history.update_lock);
373 psu->input_history.last_update = jiffies - HZ;
374
375 ibm_cffps_create_led_class(psu);
376
289 /* Don't fail the probe if we can't create debugfs */ 377 /* Don't fail the probe if we can't create debugfs */
290 debugfs = pmbus_get_debugfs_dir(client); 378 debugfs = pmbus_get_debugfs_dir(client);
291 if (!debugfs) 379 if (!debugfs)
@@ -295,14 +383,6 @@ static int ibm_cffps_probe(struct i2c_client *client,
295 if (!ibm_cffps_dir) 383 if (!ibm_cffps_dir)
296 return 0; 384 return 0;
297 385
298 psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL);
299 if (!psu)
300 return 0;
301
302 psu->client = client;
303 mutex_init(&psu->input_history.update_lock);
304 psu->input_history.last_update = jiffies - HZ;
305
306 for (i = 0; i < CFFPS_DEBUGFS_NUM_ENTRIES; ++i) 386 for (i = 0; i < CFFPS_DEBUGFS_NUM_ENTRIES; ++i)
307 psu->debugfs_entries[i] = i; 387 psu->debugfs_entries[i] = i;
308 388