1// SPDX-License-Identifier: GPL-2.0
2#include <linux/property.h>
3#include <linux/regmap.h>
4#include <net/dsa.h>
5
6#include "qca8k.h"
7#include "qca8k_leds.h"
8
9static u32 qca8k_phy_to_port(int phy)
10{
11	/* Internal PHY 0 has port at index 1.
12	 * Internal PHY 1 has port at index 2.
13	 * Internal PHY 2 has port at index 3.
14	 * Internal PHY 3 has port at index 4.
15	 * Internal PHY 4 has port at index 5.
16	 */
17
18	return phy + 1;
19}
20
21static int
22qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
23{
24	switch (port_num) {
25	case 0:
26		reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
27		reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
28		break;
29	case 1:
30	case 2:
31	case 3:
32		/* Port 123 are controlled on a different reg */
33		reg_info->reg = QCA8K_LED_CTRL3_REG;
34		reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num);
35		break;
36	case 4:
37		reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
38		reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
39		break;
40	default:
41		return -EINVAL;
42	}
43
44	return 0;
45}
46
47static int
48qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
49{
50	reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
51
52	/* 6 total control rule:
53	 * 3 control rules for phy0-3 that applies to all their leds
54	 * 3 control rules for phy4
55	 */
56	if (port_num == 4)
57		reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
58	else
59		reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
60
61	return 0;
62}
63
64static int
65qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
66{
67	/* Parsing specific to netdev trigger */
68	if (test_bit(TRIGGER_NETDEV_TX, &rules))
69		*offload_trigger |= QCA8K_LED_TX_BLINK_MASK;
70	if (test_bit(TRIGGER_NETDEV_RX, &rules))
71		*offload_trigger |= QCA8K_LED_RX_BLINK_MASK;
72	if (test_bit(TRIGGER_NETDEV_LINK_10, &rules))
73		*offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK;
74	if (test_bit(TRIGGER_NETDEV_LINK_100, &rules))
75		*offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK;
76	if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules))
77		*offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK;
78	if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules))
79		*offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK;
80	if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules))
81		*offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK;
82
83	if (rules && !*offload_trigger)
84		return -EOPNOTSUPP;
85
86	/* Enable some default rule by default to the requested mode:
87	 * - Blink at 4Hz by default
88	 */
89	*offload_trigger |= QCA8K_LED_BLINK_4HZ;
90
91	return 0;
92}
93
94static int
95qca8k_led_brightness_set(struct qca8k_led *led,
96			 enum led_brightness brightness)
97{
98	struct qca8k_led_pattern_en reg_info;
99	struct qca8k_priv *priv = led->priv;
100	u32 mask, val;
101
102	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
103
104	val = QCA8K_LED_ALWAYS_OFF;
105	if (brightness)
106		val = QCA8K_LED_ALWAYS_ON;
107
108	/* HW regs to control brightness is special and port 1-2-3
109	 * are placed in a different reg.
110	 *
111	 * To control port 0 brightness:
112	 * - the 2 bit (15, 14) of:
113	 *   - QCA8K_LED_CTRL0_REG for led1
114	 *   - QCA8K_LED_CTRL1_REG for led2
115	 *   - QCA8K_LED_CTRL2_REG for led3
116	 *
117	 * To control port 4:
118	 * - the 2 bit (31, 30) of:
119	 *   - QCA8K_LED_CTRL0_REG for led1
120	 *   - QCA8K_LED_CTRL1_REG for led2
121	 *   - QCA8K_LED_CTRL2_REG for led3
122	 *
123	 * To control port 1:
124	 *   - the 2 bit at (9, 8) of QCA8K_LED_CTRL3_REG are used for led1
125	 *   - the 2 bit at (11, 10) of QCA8K_LED_CTRL3_REG are used for led2
126	 *   - the 2 bit at (13, 12) of QCA8K_LED_CTRL3_REG are used for led3
127	 *
128	 * To control port 2:
129	 *   - the 2 bit at (15, 14) of QCA8K_LED_CTRL3_REG are used for led1
130	 *   - the 2 bit at (17, 16) of QCA8K_LED_CTRL3_REG are used for led2
131	 *   - the 2 bit at (19, 18) of QCA8K_LED_CTRL3_REG are used for led3
132	 *
133	 * To control port 3:
134	 *   - the 2 bit at (21, 20) of QCA8K_LED_CTRL3_REG are used for led1
135	 *   - the 2 bit at (23, 22) of QCA8K_LED_CTRL3_REG are used for led2
136	 *   - the 2 bit at (25, 24) of QCA8K_LED_CTRL3_REG are used for led3
137	 *
138	 * To abstract this and have less code, we use the port and led numm
139	 * to calculate the shift and the correct reg due to this problem of
140	 * not having a 1:1 map of LED with the regs.
141	 */
142	if (led->port_num == 0 || led->port_num == 4) {
143		mask = QCA8K_LED_PATTERN_EN_MASK;
144		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
145	} else {
146		mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
147	}
148
149	return regmap_update_bits(priv->regmap, reg_info.reg,
150				  mask << reg_info.shift,
151				  val << reg_info.shift);
152}
153
154static int
155qca8k_cled_brightness_set_blocking(struct led_classdev *ldev,
156				   enum led_brightness brightness)
157{
158	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
159
160	return qca8k_led_brightness_set(led, brightness);
161}
162
163static enum led_brightness
164qca8k_led_brightness_get(struct qca8k_led *led)
165{
166	struct qca8k_led_pattern_en reg_info;
167	struct qca8k_priv *priv = led->priv;
168	u32 val;
169	int ret;
170
171	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
172
173	ret = regmap_read(priv->regmap, reg_info.reg, &val);
174	if (ret)
175		return 0;
176
177	val >>= reg_info.shift;
178
179	if (led->port_num == 0 || led->port_num == 4) {
180		val &= QCA8K_LED_PATTERN_EN_MASK;
181		val >>= QCA8K_LED_PATTERN_EN_SHIFT;
182	} else {
183		val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
184	}
185
186	/* Assume brightness ON only when the LED is set to always ON */
187	return val == QCA8K_LED_ALWAYS_ON;
188}
189
190static int
191qca8k_cled_blink_set(struct led_classdev *ldev,
192		     unsigned long *delay_on,
193		     unsigned long *delay_off)
194{
195	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
196	u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
197	struct qca8k_led_pattern_en reg_info;
198	struct qca8k_priv *priv = led->priv;
199
200	if (*delay_on == 0 && *delay_off == 0) {
201		*delay_on = 125;
202		*delay_off = 125;
203	}
204
205	if (*delay_on != 125 || *delay_off != 125) {
206		/* The hardware only supports blinking at 4Hz. Fall back
207		 * to software implementation in other cases.
208		 */
209		return -EINVAL;
210	}
211
212	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
213
214	if (led->port_num == 0 || led->port_num == 4) {
215		mask = QCA8K_LED_PATTERN_EN_MASK;
216		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
217	} else {
218		mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
219	}
220
221	regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
222			   val << reg_info.shift);
223
224	return 0;
225}
226
227static int
228qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable)
229{
230	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
231
232	struct qca8k_led_pattern_en reg_info;
233	struct qca8k_priv *priv = led->priv;
234	u32 mask, val = QCA8K_LED_ALWAYS_OFF;
235
236	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
237
238	if (enable)
239		val = QCA8K_LED_RULE_CONTROLLED;
240
241	if (led->port_num == 0 || led->port_num == 4) {
242		mask = QCA8K_LED_PATTERN_EN_MASK;
243		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
244	} else {
245		mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
246	}
247
248	return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
249				  val << reg_info.shift);
250}
251
252static bool
253qca8k_cled_hw_control_status(struct led_classdev *ldev)
254{
255	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
256
257	struct qca8k_led_pattern_en reg_info;
258	struct qca8k_priv *priv = led->priv;
259	u32 val;
260
261	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
262
263	regmap_read(priv->regmap, reg_info.reg, &val);
264
265	val >>= reg_info.shift;
266
267	if (led->port_num == 0 || led->port_num == 4) {
268		val &= QCA8K_LED_PATTERN_EN_MASK;
269		val >>= QCA8K_LED_PATTERN_EN_SHIFT;
270	} else {
271		val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
272	}
273
274	return val == QCA8K_LED_RULE_CONTROLLED;
275}
276
277static int
278qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
279{
280	u32 offload_trigger = 0;
281
282	return qca8k_parse_netdev(rules, &offload_trigger);
283}
284
285static int
286qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules)
287{
288	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
289	struct qca8k_led_pattern_en reg_info;
290	struct qca8k_priv *priv = led->priv;
291	u32 offload_trigger = 0;
292	int ret;
293
294	ret = qca8k_parse_netdev(rules, &offload_trigger);
295	if (ret)
296		return ret;
297
298	ret = qca8k_cled_trigger_offload(ldev, true);
299	if (ret)
300		return ret;
301
302	qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
303
304	return regmap_update_bits(priv->regmap, reg_info.reg,
305				  QCA8K_LED_RULE_MASK << reg_info.shift,
306				  offload_trigger << reg_info.shift);
307}
308
309static int
310qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
311{
312	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
313	struct qca8k_led_pattern_en reg_info;
314	struct qca8k_priv *priv = led->priv;
315	u32 val;
316	int ret;
317
318	/* With hw control not active return err */
319	if (!qca8k_cled_hw_control_status(ldev))
320		return -EINVAL;
321
322	qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
323
324	ret = regmap_read(priv->regmap, reg_info.reg, &val);
325	if (ret)
326		return ret;
327
328	val >>= reg_info.shift;
329	val &= QCA8K_LED_RULE_MASK;
330
331	/* Parsing specific to netdev trigger */
332	if (val & QCA8K_LED_TX_BLINK_MASK)
333		set_bit(TRIGGER_NETDEV_TX, rules);
334	if (val & QCA8K_LED_RX_BLINK_MASK)
335		set_bit(TRIGGER_NETDEV_RX, rules);
336	if (val & QCA8K_LED_LINK_10M_EN_MASK)
337		set_bit(TRIGGER_NETDEV_LINK_10, rules);
338	if (val & QCA8K_LED_LINK_100M_EN_MASK)
339		set_bit(TRIGGER_NETDEV_LINK_100, rules);
340	if (val & QCA8K_LED_LINK_1000M_EN_MASK)
341		set_bit(TRIGGER_NETDEV_LINK_1000, rules);
342	if (val & QCA8K_LED_HALF_DUPLEX_MASK)
343		set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules);
344	if (val & QCA8K_LED_FULL_DUPLEX_MASK)
345		set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules);
346
347	return 0;
348}
349
350static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev)
351{
352	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
353	struct qca8k_priv *priv = led->priv;
354	struct dsa_port *dp;
355
356	dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num));
357	if (!dp)
358		return NULL;
359	if (dp->user)
360		return &dp->user->dev;
361	return NULL;
362}
363
364static int
365qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
366{
367	struct fwnode_handle *led = NULL, *leds = NULL;
368	struct led_init_data init_data = { };
369	enum led_default_state state;
370	struct qca8k_led *port_led;
371	int led_num, led_index;
372	int ret;
373
374	leds = fwnode_get_named_child_node(port, "leds");
375	if (!leds) {
376		dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n",
377			port_num);
378		return 0;
379	}
380
381	fwnode_for_each_child_node(leds, led) {
382		/* Reg represent the led number of the port.
383		 * Each port can have at most 3 leds attached
384		 * Commonly:
385		 * 1. is gigabit led
386		 * 2. is mbit led
387		 * 3. additional status led
388		 */
389		if (fwnode_property_read_u32(led, "reg", &led_num))
390			continue;
391
392		if (led_num >= QCA8K_LED_PORT_COUNT) {
393			dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
394				 led_num, port_num);
395			continue;
396		}
397
398		led_index = QCA8K_LED_PORT_INDEX(port_num, led_num);
399
400		port_led = &priv->ports_led[led_index];
401		port_led->port_num = port_num;
402		port_led->led_num = led_num;
403		port_led->priv = priv;
404
405		state = led_init_default_state_get(led);
406		switch (state) {
407		case LEDS_DEFSTATE_ON:
408			port_led->cdev.brightness = 1;
409			qca8k_led_brightness_set(port_led, 1);
410			break;
411		case LEDS_DEFSTATE_KEEP:
412			port_led->cdev.brightness =
413					qca8k_led_brightness_get(port_led);
414			break;
415		default:
416			port_led->cdev.brightness = 0;
417			qca8k_led_brightness_set(port_led, 0);
418		}
419
420		port_led->cdev.max_brightness = 1;
421		port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
422		port_led->cdev.blink_set = qca8k_cled_blink_set;
423		port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported;
424		port_led->cdev.hw_control_set = qca8k_cled_hw_control_set;
425		port_led->cdev.hw_control_get = qca8k_cled_hw_control_get;
426		port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device;
427		port_led->cdev.hw_control_trigger = "netdev";
428		init_data.default_label = ":port";
429		init_data.fwnode = led;
430		init_data.devname_mandatory = true;
431		init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d",
432						 priv->internal_mdio_bus->id,
433						 port_num);
434		if (!init_data.devicename)
435			return -ENOMEM;
436
437		ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data);
438		if (ret)
439			dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num);
440
441		kfree(init_data.devicename);
442	}
443
444	return 0;
445}
446
447int
448qca8k_setup_led_ctrl(struct qca8k_priv *priv)
449{
450	struct fwnode_handle *ports, *port;
451	int port_num;
452	int ret;
453
454	ports = device_get_named_child_node(priv->dev, "ports");
455	if (!ports) {
456		dev_info(priv->dev, "No ports node specified in device tree!");
457		return 0;
458	}
459
460	fwnode_for_each_child_node(ports, port) {
461		if (fwnode_property_read_u32(port, "reg", &port_num))
462			continue;
463
464		/* Skip checking for CPU port 0 and CPU port 6 as not supported */
465		if (port_num == 0 || port_num == 6)
466			continue;
467
468		/* Each port can have at most 3 different leds attached.
469		 * Switch port starts from 0 to 6, but port 0 and 6 are CPU
470		 * port. The port index needs to be decreased by one to identify
471		 * the correct port for LED setup.
472		 */
473		ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num));
474		if (ret)
475			return ret;
476	}
477
478	return 0;
479}
480