xref: /openbmc/linux/drivers/leds/leds-menf21bmc.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
238433639SAndreas Werner /*
338433639SAndreas Werner  *  MEN 14F021P00 Board Management Controller (BMC) LEDs Driver.
438433639SAndreas Werner  *
538433639SAndreas Werner  *  This is the core LED driver of the MEN 14F021P00 BMC.
638433639SAndreas Werner  *  There are four LEDs available which can be switched on and off.
738433639SAndreas Werner  *  STATUS LED, HOT SWAP LED, USER LED 1, USER LED 2
838433639SAndreas Werner  *
938433639SAndreas Werner  *  Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH
1038433639SAndreas Werner  */
1138433639SAndreas Werner 
1238433639SAndreas Werner #include <linux/module.h>
1338433639SAndreas Werner #include <linux/kernel.h>
1438433639SAndreas Werner #include <linux/platform_device.h>
1538433639SAndreas Werner #include <linux/leds.h>
1638433639SAndreas Werner #include <linux/i2c.h>
1738433639SAndreas Werner 
1838433639SAndreas Werner #define BMC_CMD_LED_GET_SET	0xA0
1938433639SAndreas Werner #define BMC_BIT_LED_STATUS	BIT(0)
2038433639SAndreas Werner #define BMC_BIT_LED_HOTSWAP	BIT(1)
2138433639SAndreas Werner #define BMC_BIT_LED_USER1	BIT(2)
2238433639SAndreas Werner #define BMC_BIT_LED_USER2	BIT(3)
2338433639SAndreas Werner 
2438433639SAndreas Werner struct menf21bmc_led {
2538433639SAndreas Werner 	struct led_classdev cdev;
2638433639SAndreas Werner 	u8 led_bit;
2738433639SAndreas Werner 	const char *name;
2838433639SAndreas Werner 	struct i2c_client *i2c_client;
2938433639SAndreas Werner };
3038433639SAndreas Werner 
3138433639SAndreas Werner static struct menf21bmc_led leds[] = {
3238433639SAndreas Werner 	{
3338433639SAndreas Werner 		.name = "menf21bmc:led_status",
3438433639SAndreas Werner 		.led_bit = BMC_BIT_LED_STATUS,
3538433639SAndreas Werner 	},
3638433639SAndreas Werner 	{
3738433639SAndreas Werner 		.name = "menf21bmc:led_hotswap",
3838433639SAndreas Werner 		.led_bit = BMC_BIT_LED_HOTSWAP,
3938433639SAndreas Werner 	},
4038433639SAndreas Werner 	{
4138433639SAndreas Werner 		.name = "menf21bmc:led_user1",
4238433639SAndreas Werner 		.led_bit = BMC_BIT_LED_USER1,
4338433639SAndreas Werner 	},
4438433639SAndreas Werner 	{
4538433639SAndreas Werner 		.name = "menf21bmc:led_user2",
4638433639SAndreas Werner 		.led_bit = BMC_BIT_LED_USER2,
4738433639SAndreas Werner 	}
4838433639SAndreas Werner };
4938433639SAndreas Werner 
5038433639SAndreas Werner static DEFINE_MUTEX(led_lock);
5138433639SAndreas Werner 
5238433639SAndreas Werner static void
menf21bmc_led_set(struct led_classdev * led_cdev,enum led_brightness value)5338433639SAndreas Werner menf21bmc_led_set(struct led_classdev *led_cdev, enum led_brightness value)
5438433639SAndreas Werner {
5538433639SAndreas Werner 	int led_val;
5638433639SAndreas Werner 	struct menf21bmc_led *led = container_of(led_cdev,
5738433639SAndreas Werner 					struct menf21bmc_led, cdev);
5838433639SAndreas Werner 
5938433639SAndreas Werner 	mutex_lock(&led_lock);
6038433639SAndreas Werner 	led_val = i2c_smbus_read_byte_data(led->i2c_client,
6138433639SAndreas Werner 					   BMC_CMD_LED_GET_SET);
6238433639SAndreas Werner 	if (led_val < 0)
6338433639SAndreas Werner 		goto err_out;
6438433639SAndreas Werner 
6538433639SAndreas Werner 	if (value == LED_OFF)
6638433639SAndreas Werner 		led_val &= ~led->led_bit;
6738433639SAndreas Werner 	else
6838433639SAndreas Werner 		led_val |= led->led_bit;
6938433639SAndreas Werner 
7038433639SAndreas Werner 	i2c_smbus_write_byte_data(led->i2c_client,
7138433639SAndreas Werner 				  BMC_CMD_LED_GET_SET, led_val);
7238433639SAndreas Werner err_out:
7338433639SAndreas Werner 	mutex_unlock(&led_lock);
7438433639SAndreas Werner }
7538433639SAndreas Werner 
menf21bmc_led_probe(struct platform_device * pdev)7638433639SAndreas Werner static int menf21bmc_led_probe(struct platform_device *pdev)
7738433639SAndreas Werner {
7838433639SAndreas Werner 	int i;
7938433639SAndreas Werner 	int ret;
8038433639SAndreas Werner 	struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent);
8138433639SAndreas Werner 
8238433639SAndreas Werner 	for (i = 0; i < ARRAY_SIZE(leds); i++) {
8338433639SAndreas Werner 		leds[i].cdev.name = leds[i].name;
8438433639SAndreas Werner 		leds[i].cdev.brightness_set = menf21bmc_led_set;
8538433639SAndreas Werner 		leds[i].i2c_client = i2c_client;
8681aad9f8SMuhammad Falak R Wani 		ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
8781aad9f8SMuhammad Falak R Wani 		if (ret < 0) {
8881aad9f8SMuhammad Falak R Wani 			dev_err(&pdev->dev, "failed to register LED device\n");
8981aad9f8SMuhammad Falak R Wani 			return ret;
9081aad9f8SMuhammad Falak R Wani 		}
9138433639SAndreas Werner 	}
9238433639SAndreas Werner 	dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n");
9338433639SAndreas Werner 
9438433639SAndreas Werner 	return 0;
9538433639SAndreas Werner 
9638433639SAndreas Werner }
9738433639SAndreas Werner 
9838433639SAndreas Werner static struct platform_driver menf21bmc_led = {
9938433639SAndreas Werner 	.probe		= menf21bmc_led_probe,
10038433639SAndreas Werner 	.driver		= {
10138433639SAndreas Werner 		.name		= "menf21bmc_led",
10238433639SAndreas Werner 	},
10338433639SAndreas Werner };
10438433639SAndreas Werner 
10538433639SAndreas Werner module_platform_driver(menf21bmc_led);
10638433639SAndreas Werner 
10738433639SAndreas Werner MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
10838433639SAndreas Werner MODULE_DESCRIPTION("MEN 14F021P00 BMC led driver");
10938433639SAndreas Werner MODULE_LICENSE("GPL v2");
11038433639SAndreas Werner MODULE_ALIAS("platform:menf21bmc_led");
111