leds-upboard.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * UP board LED driver.
  4. *
  5. * Copyright (c) AAEON. All rights reserved.
  6. * Copyright (C) 2024 Bootlin
  7. *
  8. * Author: Gary Wang <garywang@aaeon.com.tw>
  9. * Author: Thomas Richard <thomas.richard@bootlin.com>
  10. */
  11. #include <linux/device.h>
  12. #include <linux/container_of.h>
  13. #include <linux/leds.h>
  14. #include <linux/mfd/upboard-fpga.h>
  15. #include <linux/module.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/regmap.h>
  18. #define led_cdev_to_led_upboard(c) container_of(c, struct upboard_led, cdev)
  19. struct upboard_led {
  20. struct regmap_field *field;
  21. struct led_classdev cdev;
  22. };
  23. struct upboard_led_profile {
  24. const char *name;
  25. unsigned int bit;
  26. };
  27. static struct upboard_led_profile upboard_up_led_profile[] = {
  28. { "upboard:yellow:" LED_FUNCTION_STATUS, 0 },
  29. { "upboard:green:" LED_FUNCTION_STATUS, 1 },
  30. { "upboard:red:" LED_FUNCTION_STATUS, 2 },
  31. };
  32. static struct upboard_led_profile upboard_up2_led_profile[] = {
  33. { "upboard:blue:" LED_FUNCTION_STATUS, 0 },
  34. { "upboard:yellow:" LED_FUNCTION_STATUS, 1 },
  35. { "upboard:green:" LED_FUNCTION_STATUS, 2 },
  36. { "upboard:red:" LED_FUNCTION_STATUS, 3 },
  37. };
  38. static enum led_brightness upboard_led_brightness_get(struct led_classdev *cdev)
  39. {
  40. struct upboard_led *led = led_cdev_to_led_upboard(cdev);
  41. int brightness, ret;
  42. ret = regmap_field_read(led->field, &brightness);
  43. return ret ? LED_OFF : brightness;
  44. };
  45. static int upboard_led_brightness_set(struct led_classdev *cdev, enum led_brightness brightness)
  46. {
  47. struct upboard_led *led = led_cdev_to_led_upboard(cdev);
  48. return regmap_field_write(led->field, brightness != LED_OFF);
  49. };
  50. static int upboard_led_probe(struct platform_device *pdev)
  51. {
  52. struct device *dev = &pdev->dev;
  53. struct upboard_fpga *fpga = dev_get_drvdata(dev->parent);
  54. struct upboard_led_profile *led_profile;
  55. struct upboard_led *led;
  56. int led_instances, ret, i;
  57. switch (fpga->fpga_data->type) {
  58. case UPBOARD_UP_FPGA:
  59. led_profile = upboard_up_led_profile;
  60. led_instances = ARRAY_SIZE(upboard_up_led_profile);
  61. break;
  62. case UPBOARD_UP2_FPGA:
  63. led_profile = upboard_up2_led_profile;
  64. led_instances = ARRAY_SIZE(upboard_up2_led_profile);
  65. break;
  66. default:
  67. return dev_err_probe(dev, -EINVAL, "Unknown device type %d\n",
  68. fpga->fpga_data->type);
  69. }
  70. for (i = 0; i < led_instances; i++) {
  71. const struct reg_field fldconf = {
  72. .reg = UPBOARD_REG_FUNC_EN0,
  73. .lsb = led_profile[i].bit,
  74. .msb = led_profile[i].bit,
  75. };
  76. led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
  77. if (!led)
  78. return -ENOMEM;
  79. led->field = devm_regmap_field_alloc(&pdev->dev, fpga->regmap, fldconf);
  80. if (IS_ERR(led->field))
  81. return PTR_ERR(led->field);
  82. led->cdev.brightness_get = upboard_led_brightness_get;
  83. led->cdev.brightness_set_blocking = upboard_led_brightness_set;
  84. led->cdev.max_brightness = LED_ON;
  85. led->cdev.name = led_profile[i].name;
  86. ret = devm_led_classdev_register(dev, &led->cdev);
  87. if (ret)
  88. return ret;
  89. }
  90. return 0;
  91. }
  92. static struct platform_driver upboard_led_driver = {
  93. .driver = {
  94. .name = "upboard-leds",
  95. },
  96. .probe = upboard_led_probe,
  97. };
  98. module_platform_driver(upboard_led_driver);
  99. MODULE_AUTHOR("Gary Wang <garywang@aaeon.com.tw>");
  100. MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
  101. MODULE_DESCRIPTION("UP Board LED driver");
  102. MODULE_LICENSE("GPL");
  103. MODULE_ALIAS("platform:upboard-leds");