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