Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /*
0003  * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
0004  * Copyright (C) 2017 Intel Deutschland GmbH
0005  */
0006 #include <linux/leds.h>
0007 #include "iwl-io.h"
0008 #include "iwl-csr.h"
0009 #include "mvm.h"
0010 
0011 static void iwl_mvm_send_led_fw_cmd(struct iwl_mvm *mvm, bool on)
0012 {
0013     struct iwl_led_cmd led_cmd = {
0014         .status = cpu_to_le32(on),
0015     };
0016     struct iwl_host_cmd cmd = {
0017         .id = WIDE_ID(LONG_GROUP, LEDS_CMD),
0018         .len = { sizeof(led_cmd), },
0019         .data = { &led_cmd, },
0020         .flags = CMD_ASYNC,
0021     };
0022     int err;
0023 
0024     if (!iwl_mvm_firmware_running(mvm))
0025         return;
0026 
0027     err = iwl_mvm_send_cmd(mvm, &cmd);
0028 
0029     if (err)
0030         IWL_WARN(mvm, "LED command failed: %d\n", err);
0031 }
0032 
0033 static void iwl_mvm_led_set(struct iwl_mvm *mvm, bool on)
0034 {
0035     if (fw_has_capa(&mvm->fw->ucode_capa,
0036             IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT)) {
0037         iwl_mvm_send_led_fw_cmd(mvm, on);
0038         return;
0039     }
0040 
0041     iwl_write32(mvm->trans, CSR_LED_REG,
0042             on ? CSR_LED_REG_TURN_ON : CSR_LED_REG_TURN_OFF);
0043 }
0044 
0045 static void iwl_led_brightness_set(struct led_classdev *led_cdev,
0046                    enum led_brightness brightness)
0047 {
0048     struct iwl_mvm *mvm = container_of(led_cdev, struct iwl_mvm, led);
0049 
0050     iwl_mvm_led_set(mvm, brightness > 0);
0051 }
0052 
0053 int iwl_mvm_leds_init(struct iwl_mvm *mvm)
0054 {
0055     int mode = iwlwifi_mod_params.led_mode;
0056     int ret;
0057 
0058     switch (mode) {
0059     case IWL_LED_BLINK:
0060         IWL_ERR(mvm, "Blink led mode not supported, used default\n");
0061         fallthrough;
0062     case IWL_LED_DEFAULT:
0063     case IWL_LED_RF_STATE:
0064         mode = IWL_LED_RF_STATE;
0065         break;
0066     case IWL_LED_DISABLE:
0067         IWL_INFO(mvm, "Led disabled\n");
0068         return 0;
0069     default:
0070         return -EINVAL;
0071     }
0072 
0073     mvm->led.name = kasprintf(GFP_KERNEL, "%s-led",
0074                    wiphy_name(mvm->hw->wiphy));
0075     if (!mvm->led.name)
0076         return -ENOMEM;
0077 
0078     mvm->led.brightness_set = iwl_led_brightness_set;
0079     mvm->led.max_brightness = 1;
0080 
0081     if (mode == IWL_LED_RF_STATE)
0082         mvm->led.default_trigger =
0083             ieee80211_get_radio_led_name(mvm->hw);
0084 
0085     ret = led_classdev_register(mvm->trans->dev, &mvm->led);
0086     if (ret) {
0087         kfree(mvm->led.name);
0088         IWL_INFO(mvm, "Failed to enable led\n");
0089         return ret;
0090     }
0091 
0092     mvm->init_status |= IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
0093     return 0;
0094 }
0095 
0096 void iwl_mvm_leds_sync(struct iwl_mvm *mvm)
0097 {
0098     if (!(mvm->init_status & IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE))
0099         return;
0100 
0101     /*
0102      * if we control through the register, we're doing it
0103      * even when the firmware isn't up, so no need to sync
0104      */
0105     if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
0106         return;
0107 
0108     iwl_mvm_led_set(mvm, mvm->led.brightness > 0);
0109 }
0110 
0111 void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
0112 {
0113     if (!(mvm->init_status & IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE))
0114         return;
0115 
0116     led_classdev_unregister(&mvm->led);
0117     kfree(mvm->led.name);
0118     mvm->init_status &= ~IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
0119 }