// SPDX-License-Identifier: GPL-2.0-only
/*
 * Device probe and register.
 *
 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
 * Copyright (c) 2010, ST-Ericsson
 * Copyright (c) 2008, Johannes Berg <johannes@sipsolutions.net>
 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
 * Copyright (c) 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
 */
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/gpio/consumer.h>
#include <linux/mmc/sdio_func.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>

#include "main.h"
#include "wfx.h"
#include "fwio.h"
#include "hwio.h"
#include "bus.h"
#include "bh.h"
#include "sta.h"
#include "key.h"
#include "scan.h"
#include "debug.h"
#include "data_tx.h"
#include "hif_tx_mib.h"
#include "hif_api_cmd.h"

#define WFX_PDS_TLV_TYPE 0x4450 // "PD" (Platform Data) in ascii little-endian
#define WFX_PDS_MAX_CHUNK_SIZE 1500

MODULE_DESCRIPTION("Silicon Labs 802.11 Wireless LAN driver for WF200");
MODULE_AUTHOR("Jérôme Pouiller <jerome.pouiller@silabs.com>");
MODULE_LICENSE("GPL");

#define RATETAB_ENT(_rate, _rateid, _flags) { \
	.bitrate  = (_rate),   \
	.hw_value = (_rateid), \
	.flags    = (_flags),  \
}

static struct ieee80211_rate wfx_rates[] = {
	RATETAB_ENT(10,  0,  0),
	RATETAB_ENT(20,  1,  IEEE80211_RATE_SHORT_PREAMBLE),
	RATETAB_ENT(55,  2,  IEEE80211_RATE_SHORT_PREAMBLE),
	RATETAB_ENT(110, 3,  IEEE80211_RATE_SHORT_PREAMBLE),
	RATETAB_ENT(60,  6,  0),
	RATETAB_ENT(90,  7,  0),
	RATETAB_ENT(120, 8,  0),
	RATETAB_ENT(180, 9,  0),
	RATETAB_ENT(240, 10, 0),
	RATETAB_ENT(360, 11, 0),
	RATETAB_ENT(480, 12, 0),
	RATETAB_ENT(540, 13, 0),
};

#define CHAN2G(_channel, _freq, _flags) { \
	.band = NL80211_BAND_2GHZ, \
	.center_freq = (_freq),    \
	.hw_value = (_channel),    \
	.flags = (_flags),         \
	.max_antenna_gain = 0,     \
	.max_power = 30,           \
}

static struct ieee80211_channel wfx_2ghz_chantable[] = {
	CHAN2G(1,  2412, 0),
	CHAN2G(2,  2417, 0),
	CHAN2G(3,  2422, 0),
	CHAN2G(4,  2427, 0),
	CHAN2G(5,  2432, 0),
	CHAN2G(6,  2437, 0),
	CHAN2G(7,  2442, 0),
	CHAN2G(8,  2447, 0),
	CHAN2G(9,  2452, 0),
	CHAN2G(10, 2457, 0),
	CHAN2G(11, 2462, 0),
	CHAN2G(12, 2467, 0),
	CHAN2G(13, 2472, 0),
	CHAN2G(14, 2484, 0),
};

static const struct ieee80211_supported_band wfx_band_2ghz = {
	.channels = wfx_2ghz_chantable,
	.n_channels = ARRAY_SIZE(wfx_2ghz_chantable),
	.bitrates = wfx_rates,
	.n_bitrates = ARRAY_SIZE(wfx_rates),
	.ht_cap = {
		/* Receive caps */
		.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
		       IEEE80211_HT_CAP_MAX_AMSDU | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT),
		.ht_supported = 1,
		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
		.mcs = {
			.rx_mask = { 0xFF }, /* MCS0 to MCS7 */
			.rx_highest = cpu_to_le16(72),
			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
		},
	},
};

static const struct ieee80211_iface_limit wdev_iface_limits[] = {
	{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION) },
	{ .max = 1, .types = BIT(NL80211_IFTYPE_AP) },
};

static const struct ieee80211_iface_combination wfx_iface_combinations[] = {
	{
		.num_different_channels = 2,
		.max_interfaces = 2,
		.limits = wdev_iface_limits,
		.n_limits = ARRAY_SIZE(wdev_iface_limits),
	}
};

static const struct ieee80211_ops wfx_ops = {
	.start                   = wfx_start,
	.stop                    = wfx_stop,
	.add_interface           = wfx_add_interface,
	.remove_interface        = wfx_remove_interface,
	.config                  = wfx_config,
	.tx                      = wfx_tx,
	.wake_tx_queue           = ieee80211_handle_wake_tx_queue,
	.join_ibss               = wfx_join_ibss,
	.leave_ibss              = wfx_leave_ibss,
	.conf_tx                 = wfx_conf_tx,
	.hw_scan                 = wfx_hw_scan,
	.cancel_hw_scan          = wfx_cancel_hw_scan,
	.start_ap                = wfx_start_ap,
	.stop_ap                 = wfx_stop_ap,
	.sta_add                 = wfx_sta_add,
	.sta_remove              = wfx_sta_remove,
	.set_tim                 = wfx_set_tim,
	.set_key                 = wfx_set_key,
	.set_rts_threshold       = wfx_set_rts_threshold,
	.set_default_unicast_key = wfx_set_default_unicast_key,
	.bss_info_changed        = wfx_bss_info_changed,
	.configure_filter        = wfx_configure_filter,
	.ampdu_action            = wfx_ampdu_action,
	.flush                   = wfx_flush,
	.add_chanctx             = wfx_add_chanctx,
	.remove_chanctx          = wfx_remove_chanctx,
	.change_chanctx          = wfx_change_chanctx,
	.assign_vif_chanctx      = wfx_assign_vif_chanctx,
	.unassign_vif_chanctx    = wfx_unassign_vif_chanctx,
	.remain_on_channel       = wfx_remain_on_channel,
	.cancel_remain_on_channel = wfx_cancel_remain_on_channel,
};

bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor)
{
	if (wdev->hw_caps.api_version_major < major)
		return true;
	if (wdev->hw_caps.api_version_major > major)
		return false;
	if (wdev->hw_caps.api_version_minor < minor)
		return true;
	return false;
}

/* The device needs data about the antenna configuration. This information in provided by PDS
 * (Platform Data Set, this is the wording used in WF200 documentation) files. For hardware
 * integrators, the full process to create PDS files is described here:
 *   https://github.com/SiliconLabs/wfx-firmware/blob/master/PDS/README.md
 *
 * The PDS file is an array of Time-Length-Value structs.
 */
int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len)
{
	int ret, chunk_type, chunk_len, chunk_num = 0;

	if (*buf == '{') {
		dev_err(wdev->dev, "PDS: malformed file (legacy format?)\n");
		return -EINVAL;
	}
	while (len > 0) {
		chunk_type = get_unaligned_le16(buf + 0);
		chunk_len = get_unaligned_le16(buf + 2);
		if (chunk_len < 4 || chunk_len > len) {
			dev_err(wdev->dev, "PDS:%d: corrupted file\n", chunk_num);
			return -EINVAL;
		}
		if (chunk_type != WFX_PDS_TLV_TYPE) {
			dev_info(wdev->dev, "PDS:%d: skip unknown data\n", chunk_num);
			goto next;
		}
		if (chunk_len > WFX_PDS_MAX_CHUNK_SIZE)
			dev_warn(wdev->dev, "PDS:%d: unexpectedly large chunk\n", chunk_num);
		if (buf[4] != '{' || buf[chunk_len - 1] != '}')
			dev_warn(wdev->dev, "PDS:%d: unexpected content\n", chunk_num);

		ret = wfx_hif_configuration(wdev, buf + 4, chunk_len - 4);
		if (ret > 0) {
			dev_err(wdev->dev, "PDS:%d: invalid data (unsupported options?)\n", chunk_num);
			return -EINVAL;
		}
		if (ret == -ETIMEDOUT) {
			dev_err(wdev->dev, "PDS:%d: chip didn't reply (corrupted file?)\n", chunk_num);
			return ret;
		}
		if (ret) {
			dev_err(wdev->dev, "PDS:%d: chip returned an unknown error\n", chunk_num);
			return -EIO;
		}
next:
		chunk_num++;
		len -= chunk_len;
		buf += chunk_len;
	}
	return 0;
}

static int wfx_send_pdata_pds(struct wfx_dev *wdev)
{
	int ret = 0;
	const struct firmware *pds;
	u8 *tmp_buf;

	ret = request_firmware(&pds, wdev->pdata.file_pds, wdev->dev);
	if (ret) {
		dev_err(wdev->dev, "can't load antenna parameters (PDS file %s). The device may be unstable.\n",
			wdev->pdata.file_pds);
		return ret;
	}
	tmp_buf = kmemdup(pds->data, pds->size, GFP_KERNEL);
	if (!tmp_buf) {
		ret = -ENOMEM;
		goto release_fw;
	}
	ret = wfx_send_pds(wdev, tmp_buf, pds->size);
	kfree(tmp_buf);
release_fw:
	release_firmware(pds);
	return ret;
}

static void wfx_free_common(void *data)
{
	struct wfx_dev *wdev = data;

	mutex_destroy(&wdev->tx_power_loop_info_lock);
	mutex_destroy(&wdev->rx_stats_lock);
	mutex_destroy(&wdev->scan_lock);
	mutex_destroy(&wdev->conf_mutex);
	ieee80211_free_hw(wdev->hw);
}

struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_data *pdata,
				const struct wfx_hwbus_ops *hwbus_ops, void *hwbus_priv)
{
	struct ieee80211_hw *hw;
	struct wfx_dev *wdev;

	hw = ieee80211_alloc_hw(sizeof(struct wfx_dev), &wfx_ops);
	if (!hw)
		return NULL;

	SET_IEEE80211_DEV(hw, dev);

	ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
	ieee80211_hw_set(hw, CONNECTION_MONITOR);
	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
	ieee80211_hw_set(hw, SIGNAL_DBM);
	ieee80211_hw_set(hw, SUPPORTS_PS);
	ieee80211_hw_set(hw, MFP_CAPABLE);

	hw->vif_data_size = sizeof(struct wfx_vif);
	hw->sta_data_size = sizeof(struct wfx_sta_priv);
	hw->queues = 4;
	hw->max_rates = 8;
	hw->max_rate_tries = 8;
	hw->extra_tx_headroom = sizeof(struct wfx_hif_msg) + sizeof(struct wfx_hif_req_tx) +
				4 /* alignment */ + 8 /* TKIP IV */;
	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
				     BIT(NL80211_IFTYPE_ADHOC) |
				     BIT(NL80211_IFTYPE_AP);
	hw->wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
					NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
					NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
					NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
	hw->wiphy->features |= NL80211_FEATURE_AP_SCAN;
	hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
	hw->wiphy->max_remain_on_channel_duration = 5000;
	hw->wiphy->max_ap_assoc_sta = HIF_LINK_ID_MAX;
	hw->wiphy->max_scan_ssids = 2;
	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
	hw->wiphy->n_iface_combinations = ARRAY_SIZE(wfx_iface_combinations);
	hw->wiphy->iface_combinations = wfx_iface_combinations;
	/* FIXME: also copy wfx_rates and wfx_2ghz_chantable */
	hw->wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(dev, &wfx_band_2ghz,
							   sizeof(wfx_band_2ghz), GFP_KERNEL);
	if (!hw->wiphy->bands[NL80211_BAND_2GHZ])
		goto err;

	wdev = hw->priv;
	wdev->hw = hw;
	wdev->dev = dev;
	wdev->hwbus_ops = hwbus_ops;
	wdev->hwbus_priv = hwbus_priv;
	memcpy(&wdev->pdata, pdata, sizeof(*pdata));
	of_property_read_string(dev->of_node, "silabs,antenna-config-file", &wdev->pdata.file_pds);
	wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup", GPIOD_OUT_LOW);
	if (IS_ERR(wdev->pdata.gpio_wakeup))
		goto err;

	if (wdev->pdata.gpio_wakeup)
		gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup");

	mutex_init(&wdev->conf_mutex);
	mutex_init(&wdev->scan_lock);
	mutex_init(&wdev->rx_stats_lock);
	mutex_init(&wdev->tx_power_loop_info_lock);
	init_completion(&wdev->firmware_ready);
	INIT_DELAYED_WORK(&wdev->cooling_timeout_work, wfx_cooling_timeout_work);
	skb_queue_head_init(&wdev->tx_pending);
	init_waitqueue_head(&wdev->tx_dequeue);
	wfx_init_hif_cmd(&wdev->hif_cmd);

	if (devm_add_action_or_reset(dev, wfx_free_common, wdev))
		return NULL;

	return wdev;

err:
	ieee80211_free_hw(hw);
	return NULL;
}

int wfx_probe(struct wfx_dev *wdev)
{
	int i;
	int err;
	struct gpio_desc *gpio_saved;

	/* During first part of boot, gpio_wakeup cannot yet been used. So prevent bh() to touch
	 * it.
	 */
	gpio_saved = wdev->pdata.gpio_wakeup;
	wdev->pdata.gpio_wakeup = NULL;
	wdev->poll_irq = true;

	wdev->bh_wq = alloc_workqueue("wfx_bh_wq", WQ_HIGHPRI, 0);
	if (!wdev->bh_wq)
		return -ENOMEM;

	wfx_bh_register(wdev);

	err = wfx_init_device(wdev);
	if (err)
		goto bh_unregister;

	wfx_bh_poll_irq(wdev);
	err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ);
	if (err == 0) {
		dev_err(wdev->dev, "timeout while waiting for startup indication\n");
		err = -ETIMEDOUT;
		goto bh_unregister;
	}

	/* FIXME: fill wiphy::hw_version */
	dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n",
		 wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor,
		 wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label,
		 wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor,
		 wdev->keyset, wdev->hw_caps.link_mode);
	snprintf(wdev->hw->wiphy->fw_version,
		 sizeof(wdev->hw->wiphy->fw_version),
		 "%d.%d.%d",
		 wdev->hw_caps.firmware_major,
		 wdev->hw_caps.firmware_minor,
		 wdev->hw_caps.firmware_build);

	if (wfx_api_older_than(wdev, 1, 0)) {
		dev_err(wdev->dev, "unsupported firmware API version (expect 1 while firmware returns %d)\n",
			wdev->hw_caps.api_version_major);
		err = -EOPNOTSUPP;
		goto bh_unregister;
	}

	if (wdev->hw_caps.link_mode == SEC_LINK_ENFORCED) {
		dev_err(wdev->dev, "chip require secure_link, but can't negotiate it\n");
		goto bh_unregister;
	}

	if (wdev->hw_caps.region_sel_mode) {
		wdev->hw->wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
		wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[11].flags |=
			IEEE80211_CHAN_NO_IR;
		wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[12].flags |=
			IEEE80211_CHAN_NO_IR;
		wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[13].flags |=
			IEEE80211_CHAN_DISABLED;
	}

	dev_dbg(wdev->dev, "sending configuration file %s\n", wdev->pdata.file_pds);
	err = wfx_send_pdata_pds(wdev);
	if (err < 0 && err != -ENOENT)
		goto bh_unregister;

	wdev->poll_irq = false;
	err = wdev->hwbus_ops->irq_subscribe(wdev->hwbus_priv);
	if (err)
		goto bh_unregister;

	err = wfx_hif_use_multi_tx_conf(wdev, true);
	if (err)
		dev_err(wdev->dev, "misconfigured IRQ?\n");

	wdev->pdata.gpio_wakeup = gpio_saved;
	if (wdev->pdata.gpio_wakeup) {
		dev_dbg(wdev->dev, "enable 'quiescent' power mode with wakeup GPIO and PDS file %s\n",
			wdev->pdata.file_pds);
		gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1);
		wfx_control_reg_write(wdev, 0);
		wfx_hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT);
	} else {
		wfx_hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE);
	}

	for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) {
		eth_zero_addr(wdev->addresses[i].addr);
		err = of_get_mac_address(wdev->dev->of_node, wdev->addresses[i].addr);
		if (!err)
			wdev->addresses[i].addr[ETH_ALEN - 1] += i;
		else
			ether_addr_copy(wdev->addresses[i].addr, wdev->hw_caps.mac_addr[i]);
		if (!is_valid_ether_addr(wdev->addresses[i].addr)) {
			dev_warn(wdev->dev, "using random MAC address\n");
			eth_random_addr(wdev->addresses[i].addr);
		}
		dev_info(wdev->dev, "MAC address %d: %pM\n", i, wdev->addresses[i].addr);
	}
	wdev->hw->wiphy->n_addresses = ARRAY_SIZE(wdev->addresses);
	wdev->hw->wiphy->addresses = wdev->addresses;

	if (!wfx_api_older_than(wdev, 3, 8))
		wdev->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;

	err = ieee80211_register_hw(wdev->hw);
	if (err)
		goto irq_unsubscribe;

	err = wfx_debug_init(wdev);
	if (err)
		goto ieee80211_unregister;

	return 0;

ieee80211_unregister:
	ieee80211_unregister_hw(wdev->hw);
irq_unsubscribe:
	wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv);
bh_unregister:
	wfx_bh_unregister(wdev);
	destroy_workqueue(wdev->bh_wq);
	return err;
}

void wfx_release(struct wfx_dev *wdev)
{
	ieee80211_unregister_hw(wdev->hw);
	wfx_hif_shutdown(wdev);
	wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv);
	wfx_bh_unregister(wdev);
	destroy_workqueue(wdev->bh_wq);
}

static int __init wfx_core_init(void)
{
	int ret = 0;

	if (IS_ENABLED(CONFIG_SPI)) {
		ret = spi_register_driver(&wfx_spi_driver);
		if (ret)
			goto out;
	}
	if (IS_ENABLED(CONFIG_MMC)) {
		ret = sdio_register_driver(&wfx_sdio_driver);
		if (ret)
			goto unregister_spi;
	}

	return 0;

unregister_spi:
	if (IS_ENABLED(CONFIG_SPI))
		spi_unregister_driver(&wfx_spi_driver);
out:
	return ret;
}
module_init(wfx_core_init);

static void __exit wfx_core_exit(void)
{
	if (IS_ENABLED(CONFIG_MMC))
		sdio_unregister_driver(&wfx_sdio_driver);
	if (IS_ENABLED(CONFIG_SPI))
		spi_unregister_driver(&wfx_spi_driver);
}
module_exit(wfx_core_exit);
