// SPDX-License-Identifier: ISC
/* Copyright (C) 2022 MediaTek Inc.
 *
 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>

#include "mt7921.h"
#include "mcu.h"
#include "../mt76_connac2_mac.h"

static const struct usb_device_id mt7921u_device_table[] = {
	{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
	/* Comfast CF-952AX */
	{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff),
		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
	/* Netgear, Inc. [A8000,AXE3000] */
	{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff),
		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
	{ },
};

static int
mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
			 int cmd, int *seq)
{
	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
	u32 pad, ep;
	int ret;

	ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
	if (ret)
		return ret;

	mdev->mcu.timeout = 3 * HZ;

	if (cmd != MCU_CMD(FW_SCATTER))
		ep = MT_EP_OUT_INBAND_CMD;
	else
		ep = MT_EP_OUT_AC_BE;

	mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
	pad = round_up(skb->len, 4) + 4 - skb->len;
	__skb_put_zero(skb, pad);

	ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
			     1000, ep);
	dev_kfree_skb(skb);

	return ret;
}

static int mt7921u_mcu_init(struct mt792x_dev *dev)
{
	static const struct mt76_mcu_ops mcu_ops = {
		.headroom = MT_SDIO_HDR_SIZE +
			    sizeof(struct mt76_connac2_mcu_txd),
		.tailroom = MT_USB_TAIL_SIZE,
		.mcu_skb_send_msg = mt7921u_mcu_send_message,
		.mcu_parse_response = mt7921_mcu_parse_response,
	};
	int ret;

	dev->mt76.mcu_ops = &mcu_ops;

	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
	ret = mt7921_run_firmware(dev);
	if (ret)
		return ret;

	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);

	return 0;
}

static int mt7921u_mac_reset(struct mt792x_dev *dev)
{
	int err;

	mt76_txq_schedule_all(&dev->mphy);
	mt76_worker_disable(&dev->mt76.tx_worker);

	set_bit(MT76_RESET, &dev->mphy.state);
	set_bit(MT76_MCU_RESET, &dev->mphy.state);

	wake_up(&dev->mt76.mcu.wait);
	skb_queue_purge(&dev->mt76.mcu.res_q);

	mt76u_stop_rx(&dev->mt76);
	mt76u_stop_tx(&dev->mt76);

	mt792xu_wfsys_reset(dev);

	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
	err = mt76u_resume_rx(&dev->mt76);
	if (err)
		goto out;

	err = mt792xu_mcu_power_on(dev);
	if (err)
		goto out;

	err = mt792xu_dma_init(dev, false);
	if (err)
		goto out;

	mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);

	err = mt7921_run_firmware(dev);
	if (err)
		goto out;

	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);

	err = mt7921_mcu_set_eeprom(dev);
	if (err)
		goto out;

	err = mt7921_mac_init(dev);
	if (err)
		goto out;

	err = __mt7921_start(&dev->phy);
out:
	clear_bit(MT76_RESET, &dev->mphy.state);

	mt76_worker_enable(&dev->mt76.tx_worker);

	return err;
}

static int mt7921u_probe(struct usb_interface *usb_intf,
			 const struct usb_device_id *id)
{
	static const struct mt76_driver_ops drv_ops = {
		.txwi_size = MT_SDIO_TXD_SIZE,
		.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ |
			     MT_DRV_AMSDU_OFFLOAD,
		.survey_flags = SURVEY_INFO_TIME_TX |
				SURVEY_INFO_TIME_RX |
				SURVEY_INFO_TIME_BSS_RX,
		.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
		.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
		.tx_status_data = mt7921_usb_sdio_tx_status_data,
		.rx_skb = mt7921_queue_rx_skb,
		.rx_check = mt7921_rx_check,
		.sta_add = mt7921_mac_sta_add,
		.sta_event = mt7921_mac_sta_event,
		.sta_remove = mt7921_mac_sta_remove,
		.update_survey = mt792x_update_channel,
		.set_channel = mt7921_set_channel,
	};
	static const struct mt792x_hif_ops hif_ops = {
		.mcu_init = mt7921u_mcu_init,
		.init_reset = mt792xu_init_reset,
		.reset = mt7921u_mac_reset,
	};
	static struct mt76_bus_ops bus_ops = {
		.rr = mt792xu_rr,
		.wr = mt792xu_wr,
		.rmw = mt792xu_rmw,
		.read_copy = mt76u_read_copy,
		.write_copy = mt792xu_copy,
		.type = MT76_BUS_USB,
	};
	struct usb_device *udev = interface_to_usbdev(usb_intf);
	struct ieee80211_ops *ops;
	struct ieee80211_hw *hw;
	struct mt792x_dev *dev;
	struct mt76_dev *mdev;
	u8 features;
	int ret;

	ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops,
				      (void *)id->driver_info, &features);
	if (!ops)
		return -ENOMEM;

	ops->stop = mt792xu_stop;
	mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
	if (!mdev)
		return -ENOMEM;

	dev = container_of(mdev, struct mt792x_dev, mt76);
	dev->fw_features = features;
	dev->hif_ops = &hif_ops;

	udev = usb_get_dev(udev);
	usb_reset_device(udev);

	usb_set_intfdata(usb_intf, dev);

	ret = __mt76u_init(mdev, usb_intf, &bus_ops);
	if (ret < 0)
		goto error;

	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
		    (mt76_rr(dev, MT_HW_REV) & 0xff);
	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);

	if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
		ret = mt792xu_wfsys_reset(dev);
		if (ret)
			goto error;
	}

	ret = mt792xu_mcu_power_on(dev);
	if (ret)
		goto error;

	ret = mt76u_alloc_mcu_queue(&dev->mt76);
	if (ret)
		goto error;

	ret = mt76u_alloc_queues(&dev->mt76);
	if (ret)
		goto error;

	ret = mt792xu_dma_init(dev, false);
	if (ret)
		goto error;

	hw = mt76_hw(dev);
	/* check hw sg support in order to enable AMSDU */
	hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;

	ret = mt7921_register_device(dev);
	if (ret)
		goto error;

	return 0;

error:
	mt76u_queues_deinit(&dev->mt76);

	usb_set_intfdata(usb_intf, NULL);
	usb_put_dev(interface_to_usbdev(usb_intf));

	mt76_free_device(&dev->mt76);

	return ret;
}

#ifdef CONFIG_PM
static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
{
	struct mt792x_dev *dev = usb_get_intfdata(intf);
	struct mt76_connac_pm *pm = &dev->pm;
	int err;

	pm->suspended = true;
	flush_work(&dev->reset_work);

	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
	if (err)
		goto failed;

	mt76u_stop_rx(&dev->mt76);
	mt76u_stop_tx(&dev->mt76);

	return 0;

failed:
	pm->suspended = false;

	if (err < 0)
		mt792x_reset(&dev->mt76);

	return err;
}

static int mt7921u_resume(struct usb_interface *intf)
{
	struct mt792x_dev *dev = usb_get_intfdata(intf);
	struct mt76_connac_pm *pm = &dev->pm;
	bool reinit = true;
	int err, i;

	for (i = 0; i < 10; i++) {
		u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);

		if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
			reinit = false;
			break;
		}
		if (val & MT_WF_SW_SER_DONE_SUSPEND) {
			mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
			break;
		}

		msleep(20);
	}

	if (reinit || mt792x_dma_need_reinit(dev)) {
		err = mt792xu_dma_init(dev, true);
		if (err)
			goto failed;
	}

	err = mt76u_resume_rx(&dev->mt76);
	if (err < 0)
		goto failed;

	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
failed:
	pm->suspended = false;

	if (err < 0)
		mt792x_reset(&dev->mt76);

	return err;
}
#endif /* CONFIG_PM */

MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
MODULE_FIRMWARE(MT7921_ROM_PATCH);

static struct usb_driver mt7921u_driver = {
	.name		= KBUILD_MODNAME,
	.id_table	= mt7921u_device_table,
	.probe		= mt7921u_probe,
	.disconnect	= mt792xu_disconnect,
#ifdef CONFIG_PM
	.suspend	= mt7921u_suspend,
	.resume		= mt7921u_resume,
	.reset_resume	= mt7921u_resume,
#endif /* CONFIG_PM */
	.soft_unbind	= 1,
	.disable_hub_initiated_lpm = 1,
};
module_usb_driver(mt7921u_driver);

MODULE_DESCRIPTION("MediaTek MT7921U (USB) wireless driver");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_LICENSE("Dual BSD/GPL");
