leds-menf21bmc.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * MEN 14F021P00 Board Management Controller (BMC) LEDs Driver.
  3. *
  4. * This is the core LED driver of the MEN 14F021P00 BMC.
  5. * There are four LEDs available which can be switched on and off.
  6. * STATUS LED, HOT SWAP LED, USER LED 1, USER LED 2
  7. *
  8. * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by the
  12. * Free Software Foundation; either version 2 of the License, or (at your
  13. * option) any later version.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/leds.h>
  19. #include <linux/i2c.h>
  20. #define BMC_CMD_LED_GET_SET 0xA0
  21. #define BMC_BIT_LED_STATUS BIT(0)
  22. #define BMC_BIT_LED_HOTSWAP BIT(1)
  23. #define BMC_BIT_LED_USER1 BIT(2)
  24. #define BMC_BIT_LED_USER2 BIT(3)
  25. struct menf21bmc_led {
  26. struct led_classdev cdev;
  27. u8 led_bit;
  28. const char *name;
  29. struct i2c_client *i2c_client;
  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. static DEFINE_MUTEX(led_lock);
  50. static void
  51. menf21bmc_led_set(struct led_classdev *led_cdev, enum led_brightness value)
  52. {
  53. int led_val;
  54. struct menf21bmc_led *led = container_of(led_cdev,
  55. struct menf21bmc_led, cdev);
  56. mutex_lock(&led_lock);
  57. led_val = i2c_smbus_read_byte_data(led->i2c_client,
  58. BMC_CMD_LED_GET_SET);
  59. if (led_val < 0)
  60. goto err_out;
  61. if (value == LED_OFF)
  62. led_val &= ~led->led_bit;
  63. else
  64. led_val |= led->led_bit;
  65. i2c_smbus_write_byte_data(led->i2c_client,
  66. BMC_CMD_LED_GET_SET, led_val);
  67. err_out:
  68. mutex_unlock(&led_lock);
  69. }
  70. static int menf21bmc_led_probe(struct platform_device *pdev)
  71. {
  72. int i;
  73. int ret;
  74. struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent);
  75. for (i = 0; i < ARRAY_SIZE(leds); i++) {
  76. leds[i].cdev.name = leds[i].name;
  77. leds[i].cdev.brightness_set = menf21bmc_led_set;
  78. leds[i].i2c_client = i2c_client;
  79. ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
  80. if (ret < 0) {
  81. dev_err(&pdev->dev, "failed to register LED device\n");
  82. return ret;
  83. }
  84. }
  85. dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n");
  86. return 0;
  87. }
  88. static struct platform_driver menf21bmc_led = {
  89. .probe = menf21bmc_led_probe,
  90. .driver = {
  91. .name = "menf21bmc_led",
  92. },
  93. };
  94. module_platform_driver(menf21bmc_led);
  95. MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
  96. MODULE_DESCRIPTION("MEN 14F021P00 BMC led driver");
  97. MODULE_LICENSE("GPL v2");
  98. MODULE_ALIAS("platform:menf21bmc_led");