162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Linux RFKILL support for RTL8187
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2009 Herton Ronaldo Krzesinski <herton@mandriva.com.br>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Based on the RFKILL handling in the r8187 driver, which is:
862306a36Sopenharmony_ci * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Thanks to Realtek for their support!
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/usb.h>
1562306a36Sopenharmony_ci#include <net/mac80211.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "rtl8187.h"
1862306a36Sopenharmony_ci#include "rfkill.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	u8 gpio;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	gpio = rtl818x_ioread8(priv, &priv->map->GPIO0);
2562306a36Sopenharmony_ci	rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask);
2662306a36Sopenharmony_ci	gpio = rtl818x_ioread8(priv, &priv->map->GPIO1);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	return gpio & priv->rfkill_mask;
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_civoid rtl8187_rfkill_init(struct ieee80211_hw *hw)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	struct rtl8187_priv *priv = hw->priv;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	priv->rfkill_off = rtl8187_is_radio_enabled(priv);
3662306a36Sopenharmony_ci	printk(KERN_INFO "rtl8187: wireless switch is %s\n",
3762306a36Sopenharmony_ci	       priv->rfkill_off ? "on" : "off");
3862306a36Sopenharmony_ci	wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off);
3962306a36Sopenharmony_ci	wiphy_rfkill_start_polling(hw->wiphy);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_civoid rtl8187_rfkill_poll(struct ieee80211_hw *hw)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	bool enabled;
4562306a36Sopenharmony_ci	struct rtl8187_priv *priv = hw->priv;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	mutex_lock(&priv->conf_mutex);
4862306a36Sopenharmony_ci	enabled = rtl8187_is_radio_enabled(priv);
4962306a36Sopenharmony_ci	if (unlikely(enabled != priv->rfkill_off)) {
5062306a36Sopenharmony_ci		priv->rfkill_off = enabled;
5162306a36Sopenharmony_ci		printk(KERN_INFO "rtl8187: wireless radio switch turned %s\n",
5262306a36Sopenharmony_ci		       enabled ? "on" : "off");
5362306a36Sopenharmony_ci		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci	mutex_unlock(&priv->conf_mutex);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_civoid rtl8187_rfkill_exit(struct ieee80211_hw *hw)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	wiphy_rfkill_stop_polling(hw->wiphy);
6162306a36Sopenharmony_ci}
62