rtl8366rb-leds.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/bitops.h>
  3. #include <linux/regmap.h>
  4. #include <net/dsa.h>
  5. #include "rtl83xx.h"
  6. #include "rtl8366rb.h"
  7. static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
  8. {
  9. switch (led_group) {
  10. case 0:
  11. return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
  12. case 1:
  13. return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
  14. case 2:
  15. return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
  16. case 3:
  17. return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
  18. default:
  19. return 0;
  20. }
  21. }
  22. static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
  23. {
  24. struct realtek_priv *priv = led->priv;
  25. u8 led_group = led->led_group;
  26. u8 port_num = led->port_num;
  27. int ret;
  28. u32 val;
  29. ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
  30. &val);
  31. if (ret) {
  32. dev_err(priv->dev, "error reading LED on port %d group %d\n",
  33. led_group, port_num);
  34. return ret;
  35. }
  36. return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
  37. }
  38. static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
  39. {
  40. struct realtek_priv *priv = led->priv;
  41. u8 led_group = led->led_group;
  42. u8 port_num = led->port_num;
  43. int ret;
  44. ret = regmap_update_bits(priv->map,
  45. RTL8366RB_LED_X_X_CTRL_REG(led_group),
  46. rtl8366rb_led_group_port_mask(led_group,
  47. port_num),
  48. enable ? 0xffff : 0);
  49. if (ret) {
  50. dev_err(priv->dev, "error updating LED on port %d group %d\n",
  51. led_group, port_num);
  52. return ret;
  53. }
  54. /* Change the LED group to manual controlled LEDs if required */
  55. ret = rb8366rb_set_ledgroup_mode(priv, led_group,
  56. RTL8366RB_LEDGROUP_FORCE);
  57. if (ret) {
  58. dev_err(priv->dev, "error updating LED GROUP group %d\n",
  59. led_group);
  60. return ret;
  61. }
  62. return 0;
  63. }
  64. static int
  65. rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
  66. enum led_brightness brightness)
  67. {
  68. struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
  69. cdev);
  70. return rb8366rb_set_port_led(led, brightness == LED_ON);
  71. }
  72. static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
  73. struct fwnode_handle *led_fwnode)
  74. {
  75. struct rtl8366rb *rb = priv->chip_data;
  76. struct led_init_data init_data = { };
  77. enum led_default_state state;
  78. struct rtl8366rb_led *led;
  79. u32 led_group;
  80. int ret;
  81. ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
  82. if (ret)
  83. return ret;
  84. if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
  85. dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
  86. led_group, dp->index);
  87. return -EINVAL;
  88. }
  89. led = &rb->leds[dp->index][led_group];
  90. led->port_num = dp->index;
  91. led->led_group = led_group;
  92. led->priv = priv;
  93. state = led_init_default_state_get(led_fwnode);
  94. switch (state) {
  95. case LEDS_DEFSTATE_ON:
  96. led->cdev.brightness = 1;
  97. rb8366rb_set_port_led(led, 1);
  98. break;
  99. case LEDS_DEFSTATE_KEEP:
  100. led->cdev.brightness =
  101. rb8366rb_get_port_led(led);
  102. break;
  103. case LEDS_DEFSTATE_OFF:
  104. default:
  105. led->cdev.brightness = 0;
  106. rb8366rb_set_port_led(led, 0);
  107. }
  108. led->cdev.max_brightness = 1;
  109. led->cdev.brightness_set_blocking =
  110. rtl8366rb_cled_brightness_set_blocking;
  111. init_data.fwnode = led_fwnode;
  112. init_data.devname_mandatory = true;
  113. init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
  114. dp->ds->index, dp->index, led_group);
  115. if (!init_data.devicename)
  116. return -ENOMEM;
  117. ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
  118. if (ret) {
  119. dev_warn(priv->dev, "Failed to init LED %d for port %d",
  120. led_group, dp->index);
  121. return ret;
  122. }
  123. return 0;
  124. }
  125. int rtl8366rb_setup_leds(struct realtek_priv *priv)
  126. {
  127. struct dsa_switch *ds = &priv->ds;
  128. struct device_node *leds_np;
  129. struct dsa_port *dp;
  130. int ret = 0;
  131. dsa_switch_for_each_port(dp, ds) {
  132. if (!dp->dn)
  133. continue;
  134. leds_np = of_get_child_by_name(dp->dn, "leds");
  135. if (!leds_np) {
  136. dev_dbg(priv->dev, "No leds defined for port %d",
  137. dp->index);
  138. continue;
  139. }
  140. for_each_child_of_node_scoped(leds_np, led_np) {
  141. ret = rtl8366rb_setup_led(priv, dp,
  142. of_fwnode_handle(led_np));
  143. if (ret)
  144. break;
  145. }
  146. of_node_put(leds_np);
  147. if (ret)
  148. return ret;
  149. }
  150. return 0;
  151. }