cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

leds-menf21bmc.c (2588B)


      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
     24struct menf21bmc_led {
     25	struct led_classdev cdev;
     26	u8 led_bit;
     27	const char *name;
     28	struct i2c_client *i2c_client;
     29};
     30
     31static 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
     50static DEFINE_MUTEX(led_lock);
     51
     52static void
     53menf21bmc_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);
     72err_out:
     73	mutex_unlock(&led_lock);
     74}
     75
     76static 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
     98static struct platform_driver menf21bmc_led = {
     99	.probe		= menf21bmc_led_probe,
    100	.driver		= {
    101		.name		= "menf21bmc_led",
    102	},
    103};
    104
    105module_platform_driver(menf21bmc_led);
    106
    107MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
    108MODULE_DESCRIPTION("MEN 14F021P00 BMC led driver");
    109MODULE_LICENSE("GPL v2");
    110MODULE_ALIAS("platform:menf21bmc_led");