xref: /linux/drivers/net/dsa/realtek/rtl8366rb-leds.c (revision 1e15510b71c99c6e49134d756df91069f7d18141)
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 
rtl8366rb_led_group_port_mask(u8 led_group,u8 port)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 
rb8366rb_get_port_led(struct rtl8366rb_led * led)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 
rb8366rb_set_port_led(struct rtl8366rb_led * led,bool enable)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
rtl8366rb_cled_brightness_set_blocking(struct led_classdev * ldev,enum led_brightness brightness)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 
rtl8366rb_setup_led(struct realtek_priv * priv,struct dsa_port * dp,struct fwnode_handle * led_fwnode)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 
rtl8366rb_setup_leds(struct realtek_priv * priv)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