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