xref: /linux/drivers/net/wireless/ath/ath10k/leds.c (revision 96f30c8f0aa9923aa39b30bcaefeacf88b490231)
1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (c) 2005-2011 Atheros Communications Inc.
4  * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
5  * Copyright (c) 2018 Sebastian Gottschall <s.gottschall@dd-wrt.com>
6  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
7  */
8 
9 #include <linux/leds.h>
10 
11 #include "core.h"
12 #include "wmi.h"
13 #include "wmi-ops.h"
14 
15 #include "leds.h"
16 
17 static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev,
18 					       enum led_brightness brightness)
19 {
20 	struct ath10k *ar = container_of(led_cdev, struct ath10k,
21 					 leds.cdev);
22 	struct gpio_led *led = &ar->leds.wifi_led;
23 
24 	mutex_lock(&ar->conf_mutex);
25 
26 	if (ar->state != ATH10K_STATE_ON)
27 		goto out;
28 
29 	ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low;
30 	ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin);
31 
32 out:
33 	mutex_unlock(&ar->conf_mutex);
34 
35 	return 0;
36 }
37 
38 int ath10k_leds_start(struct ath10k *ar)
39 {
40 	if (ar->hw_params.led_pin == 0)
41 		/* leds not supported */
42 		return 0;
43 
44 	/* under some circumstances, the gpio pin gets reconfigured
45 	 * to default state by the firmware, so we need to
46 	 * reconfigure it this behaviour has only ben seen on
47 	 * QCA9984 and QCA99XX devices so far
48 	 */
49 	ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0,
50 			       WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE);
51 	ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1);
52 
53 	return 0;
54 }
55 
56 int ath10k_leds_register(struct ath10k *ar)
57 {
58 	int ret;
59 
60 	if (ar->hw_params.led_pin == 0)
61 		/* leds not supported */
62 		return 0;
63 
64 	snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s",
65 		 wiphy_name(ar->hw->wiphy));
66 	ar->leds.wifi_led.active_low = 1;
67 	ar->leds.wifi_led.gpio = ar->hw_params.led_pin;
68 	ar->leds.wifi_led.name = ar->leds.label;
69 	ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
70 
71 	ar->leds.cdev.name = ar->leds.label;
72 	ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
73 	ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger;
74 
75 	ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
76 	if (ret)
77 		return ret;
78 
79 	return 0;
80 }
81 
82 void ath10k_leds_unregister(struct ath10k *ar)
83 {
84 	if (ar->hw_params.led_pin == 0)
85 		/* leds not supported */
86 		return;
87 
88 	led_classdev_unregister(&ar->leds.cdev);
89 }
90 
91