1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * MEN 14F021P00 Board Management Controller (BMC) LEDs Driver. 4 * 5 * This is the core LED driver of the MEN 14F021P00 BMC. 6 * There are four LEDs available which can be switched on and off. 7 * STATUS LED, HOT SWAP LED, USER LED 1, USER LED 2 8 * 9 * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH 10 */ 11 12 #include <linux/module.h> 13 #include <linux/kernel.h> 14 #include <linux/platform_device.h> 15 #include <linux/leds.h> 16 #include <linux/i2c.h> 17 18 #define BMC_CMD_LED_GET_SET 0xA0 19 #define BMC_BIT_LED_STATUS BIT(0) 20 #define BMC_BIT_LED_HOTSWAP BIT(1) 21 #define BMC_BIT_LED_USER1 BIT(2) 22 #define BMC_BIT_LED_USER2 BIT(3) 23 24 struct menf21bmc_led { 25 struct led_classdev cdev; 26 u8 led_bit; 27 const char *name; 28 struct i2c_client *i2c_client; 29 }; 30 31 static struct menf21bmc_led leds[] = { 32 { 33 .name = "menf21bmc:led_status", 34 .led_bit = BMC_BIT_LED_STATUS, 35 }, 36 { 37 .name = "menf21bmc:led_hotswap", 38 .led_bit = BMC_BIT_LED_HOTSWAP, 39 }, 40 { 41 .name = "menf21bmc:led_user1", 42 .led_bit = BMC_BIT_LED_USER1, 43 }, 44 { 45 .name = "menf21bmc:led_user2", 46 .led_bit = BMC_BIT_LED_USER2, 47 } 48 }; 49 50 static DEFINE_MUTEX(led_lock); 51 52 static void 53 menf21bmc_led_set(struct led_classdev *led_cdev, enum led_brightness value) 54 { 55 int led_val; 56 struct menf21bmc_led *led = container_of(led_cdev, 57 struct menf21bmc_led, cdev); 58 59 mutex_lock(&led_lock); 60 led_val = i2c_smbus_read_byte_data(led->i2c_client, 61 BMC_CMD_LED_GET_SET); 62 if (led_val < 0) 63 goto err_out; 64 65 if (value == LED_OFF) 66 led_val &= ~led->led_bit; 67 else 68 led_val |= led->led_bit; 69 70 i2c_smbus_write_byte_data(led->i2c_client, 71 BMC_CMD_LED_GET_SET, led_val); 72 err_out: 73 mutex_unlock(&led_lock); 74 } 75 76 static int menf21bmc_led_probe(struct platform_device *pdev) 77 { 78 int i; 79 int ret; 80 struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent); 81 82 for (i = 0; i < ARRAY_SIZE(leds); i++) { 83 leds[i].cdev.name = leds[i].name; 84 leds[i].cdev.brightness_set = menf21bmc_led_set; 85 leds[i].i2c_client = i2c_client; 86 ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev); 87 if (ret < 0) { 88 dev_err(&pdev->dev, "failed to register LED device\n"); 89 return ret; 90 } 91 } 92 dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n"); 93 94 return 0; 95 96 } 97 98 static struct platform_driver menf21bmc_led = { 99 .probe = menf21bmc_led_probe, 100 .driver = { 101 .name = "menf21bmc_led", 102 }, 103 }; 104 105 module_platform_driver(menf21bmc_led); 106 107 MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>"); 108 MODULE_DESCRIPTION("MEN 14F021P00 BMC led driver"); 109 MODULE_LICENSE("GPL v2"); 110 MODULE_ALIAS("platform:menf21bmc_led"); 111