// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2021 Hisilicon Limited.

#include <linux/skbuff.h>
#include "hclge_main.h"
#include "hnae3.h"

static int hclge_ptp_get_cycle(struct hclge_dev *hdev)
{
	struct hclge_ptp *ptp = hdev->ptp;

	ptp->cycle.quo = readl(hdev->ptp->io_base + HCLGE_PTP_CYCLE_QUO_REG) &
			 HCLGE_PTP_CYCLE_QUO_MASK;
	ptp->cycle.numer = readl(hdev->ptp->io_base + HCLGE_PTP_CYCLE_NUM_REG);
	ptp->cycle.den = readl(hdev->ptp->io_base + HCLGE_PTP_CYCLE_DEN_REG);

	if (ptp->cycle.den == 0) {
		dev_err(&hdev->pdev->dev, "invalid ptp cycle denominator!\n");
		return -EINVAL;
	}

	return 0;
}

static int hclge_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
	struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp);
	struct hclge_ptp_cycle *cycle = &hdev->ptp->cycle;
	u64 adj_val, adj_base;
	unsigned long flags;
	u32 quo, numerator;

	adj_base = (u64)cycle->quo * (u64)cycle->den + (u64)cycle->numer;
	adj_val = adjust_by_scaled_ppm(adj_base, scaled_ppm);

	/* This clock cycle is defined by three part: quotient, numerator
	 * and denominator. For example, 2.5ns, the quotient is 2,
	 * denominator is fixed to ptp->cycle.den, and numerator
	 * is 0.5 * ptp->cycle.den.
	 */
	quo = div_u64_rem(adj_val, cycle->den, &numerator);

	spin_lock_irqsave(&hdev->ptp->lock, flags);
	writel(quo & HCLGE_PTP_CYCLE_QUO_MASK,
	       hdev->ptp->io_base + HCLGE_PTP_CYCLE_QUO_REG);
	writel(numerator, hdev->ptp->io_base + HCLGE_PTP_CYCLE_NUM_REG);
	writel(cycle->den, hdev->ptp->io_base + HCLGE_PTP_CYCLE_DEN_REG);
	writel(HCLGE_PTP_CYCLE_ADJ_EN,
	       hdev->ptp->io_base + HCLGE_PTP_CYCLE_CFG_REG);
	spin_unlock_irqrestore(&hdev->ptp->lock, flags);

	return 0;
}

bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	struct hclge_ptp *ptp = hdev->ptp;

	if (!test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) ||
	    test_and_set_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state)) {
		ptp->tx_skipped++;
		return false;
	}

	ptp->tx_start = jiffies;
	ptp->tx_skb = skb_get(skb);
	ptp->tx_cnt++;

	return true;
}

void hclge_ptp_clean_tx_hwts(struct hclge_dev *hdev)
{
	struct sk_buff *skb = hdev->ptp->tx_skb;
	struct skb_shared_hwtstamps hwts;
	u32 hi, lo;
	u64 ns;

	ns = readl(hdev->ptp->io_base + HCLGE_PTP_TX_TS_NSEC_REG) &
	     HCLGE_PTP_TX_TS_NSEC_MASK;
	lo = readl(hdev->ptp->io_base + HCLGE_PTP_TX_TS_SEC_L_REG);
	hi = readl(hdev->ptp->io_base + HCLGE_PTP_TX_TS_SEC_H_REG) &
	     HCLGE_PTP_TX_TS_SEC_H_MASK;
	hdev->ptp->last_tx_seqid = readl(hdev->ptp->io_base +
		HCLGE_PTP_TX_TS_SEQID_REG);

	if (skb) {
		hdev->ptp->tx_skb = NULL;
		hdev->ptp->tx_cleaned++;

		ns += (((u64)hi) << 32 | lo) * NSEC_PER_SEC;
		hwts.hwtstamp = ns_to_ktime(ns);
		skb_tstamp_tx(skb, &hwts);
		dev_kfree_skb_any(skb);
	}

	clear_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state);
}

void hclge_ptp_get_rx_hwts(struct hnae3_handle *handle, struct sk_buff *skb,
			   u32 nsec, u32 sec)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	unsigned long flags;
	u64 ns = nsec;
	u32 sec_h;

	if (!hdev->ptp || !test_bit(HCLGE_PTP_FLAG_RX_EN, &hdev->ptp->flags))
		return;

	/* Since the BD does not have enough space for the higher 16 bits of
	 * second, and this part will not change frequently, so read it
	 * from register.
	 */
	spin_lock_irqsave(&hdev->ptp->lock, flags);
	sec_h = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_SEC_H_REG);
	spin_unlock_irqrestore(&hdev->ptp->lock, flags);

	ns += (((u64)sec_h) << HCLGE_PTP_SEC_H_OFFSET | sec) * NSEC_PER_SEC;
	skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
	hdev->ptp->last_rx = jiffies;
	hdev->ptp->rx_cnt++;
}

static int hclge_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
			      struct ptp_system_timestamp *sts)
{
	struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp);
	unsigned long flags;
	u32 hi, lo;
	u64 ns;

	spin_lock_irqsave(&hdev->ptp->lock, flags);
	ns = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_NSEC_REG);
	hi = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_SEC_H_REG);
	lo = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_SEC_L_REG);
	spin_unlock_irqrestore(&hdev->ptp->lock, flags);

	ns += (((u64)hi) << HCLGE_PTP_SEC_H_OFFSET | lo) * NSEC_PER_SEC;
	*ts = ns_to_timespec64(ns);

	return 0;
}

static int hclge_ptp_settime(struct ptp_clock_info *ptp,
			     const struct timespec64 *ts)
{
	struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp);
	unsigned long flags;

	spin_lock_irqsave(&hdev->ptp->lock, flags);
	writel(ts->tv_nsec, hdev->ptp->io_base + HCLGE_PTP_TIME_NSEC_REG);
	writel(ts->tv_sec >> HCLGE_PTP_SEC_H_OFFSET,
	       hdev->ptp->io_base + HCLGE_PTP_TIME_SEC_H_REG);
	writel(ts->tv_sec & HCLGE_PTP_SEC_L_MASK,
	       hdev->ptp->io_base + HCLGE_PTP_TIME_SEC_L_REG);
	/* synchronize the time of phc */
	writel(HCLGE_PTP_TIME_SYNC_EN,
	       hdev->ptp->io_base + HCLGE_PTP_TIME_SYNC_REG);
	spin_unlock_irqrestore(&hdev->ptp->lock, flags);

	return 0;
}

static int hclge_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
	struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp);
	unsigned long flags;
	bool is_neg = false;
	u32 adj_val = 0;

	if (delta < 0) {
		adj_val |= HCLGE_PTP_TIME_NSEC_NEG;
		delta = -delta;
		is_neg = true;
	}

	if (delta > HCLGE_PTP_TIME_NSEC_MASK) {
		struct timespec64 ts;
		s64 ns;

		hclge_ptp_gettimex(ptp, &ts, NULL);
		ns = timespec64_to_ns(&ts);
		ns = is_neg ? ns - delta : ns + delta;
		ts = ns_to_timespec64(ns);
		return hclge_ptp_settime(ptp, &ts);
	}

	adj_val |= delta & HCLGE_PTP_TIME_NSEC_MASK;

	spin_lock_irqsave(&hdev->ptp->lock, flags);
	writel(adj_val, hdev->ptp->io_base + HCLGE_PTP_TIME_NSEC_REG);
	writel(HCLGE_PTP_TIME_ADJ_EN,
	       hdev->ptp->io_base + HCLGE_PTP_TIME_ADJ_REG);
	spin_unlock_irqrestore(&hdev->ptp->lock, flags);

	return 0;
}

int hclge_ptp_get_cfg(struct hclge_dev *hdev, struct ifreq *ifr)
{
	if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state))
		return -EOPNOTSUPP;

	return copy_to_user(ifr->ifr_data, &hdev->ptp->ts_cfg,
		sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
}

static int hclge_ptp_int_en(struct hclge_dev *hdev, bool en)
{
	struct hclge_ptp_int_cmd *req;
	struct hclge_desc desc;
	int ret;

	req = (struct hclge_ptp_int_cmd *)desc.data;
	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PTP_INT_EN, false);
	req->int_en = en ? 1 : 0;

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"failed to %s ptp interrupt, ret = %d\n",
			en ? "enable" : "disable", ret);

	return ret;
}

int hclge_ptp_cfg_qry(struct hclge_dev *hdev, u32 *cfg)
{
	struct hclge_ptp_cfg_cmd *req;
	struct hclge_desc desc;
	int ret;

	req = (struct hclge_ptp_cfg_cmd *)desc.data;
	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PTP_MODE_CFG, true);
	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"failed to query ptp config, ret = %d\n", ret);
		return ret;
	}

	*cfg = le32_to_cpu(req->cfg);

	return 0;
}

static int hclge_ptp_cfg(struct hclge_dev *hdev, u32 cfg)
{
	struct hclge_ptp_cfg_cmd *req;
	struct hclge_desc desc;
	int ret;

	req = (struct hclge_ptp_cfg_cmd *)desc.data;
	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PTP_MODE_CFG, false);
	req->cfg = cpu_to_le32(cfg);
	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"failed to config ptp, ret = %d\n", ret);

	return ret;
}

static int hclge_ptp_set_tx_mode(struct hwtstamp_config *cfg,
				 unsigned long *flags, u32 *ptp_cfg)
{
	switch (cfg->tx_type) {
	case HWTSTAMP_TX_OFF:
		clear_bit(HCLGE_PTP_FLAG_TX_EN, flags);
		break;
	case HWTSTAMP_TX_ON:
		set_bit(HCLGE_PTP_FLAG_TX_EN, flags);
		*ptp_cfg |= HCLGE_PTP_TX_EN_B;
		break;
	default:
		return -ERANGE;
	}

	return 0;
}

static int hclge_ptp_set_rx_mode(struct hwtstamp_config *cfg,
				 unsigned long *flags, u32 *ptp_cfg)
{
	int rx_filter = cfg->rx_filter;

	switch (cfg->rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		clear_bit(HCLGE_PTP_FLAG_RX_EN, flags);
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
		set_bit(HCLGE_PTP_FLAG_RX_EN, flags);
		*ptp_cfg |= HCLGE_PTP_RX_EN_B;
		*ptp_cfg |= HCLGE_PTP_UDP_FULL_TYPE << HCLGE_PTP_UDP_EN_SHIFT;
		rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
		break;
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
		set_bit(HCLGE_PTP_FLAG_RX_EN, flags);
		*ptp_cfg |= HCLGE_PTP_RX_EN_B;
		*ptp_cfg |= HCLGE_PTP_UDP_FULL_TYPE << HCLGE_PTP_UDP_EN_SHIFT;
		*ptp_cfg |= HCLGE_PTP_MSG1_V2_DEFAULT << HCLGE_PTP_MSG1_SHIFT;
		*ptp_cfg |= HCLGE_PTP_MSG0_V2_EVENT << HCLGE_PTP_MSG0_SHIFT;
		*ptp_cfg |= HCLGE_PTP_MSG_TYPE_V2 << HCLGE_PTP_MSG_TYPE_SHIFT;
		rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
		break;
	case HWTSTAMP_FILTER_ALL:
	default:
		return -ERANGE;
	}

	cfg->rx_filter = rx_filter;

	return 0;
}

static int hclge_ptp_set_ts_mode(struct hclge_dev *hdev,
				 struct hwtstamp_config *cfg)
{
	unsigned long flags = hdev->ptp->flags;
	u32 ptp_cfg = 0;
	int ret;

	if (test_bit(HCLGE_PTP_FLAG_EN, &hdev->ptp->flags))
		ptp_cfg |= HCLGE_PTP_EN_B;

	ret = hclge_ptp_set_tx_mode(cfg, &flags, &ptp_cfg);
	if (ret)
		return ret;

	ret = hclge_ptp_set_rx_mode(cfg, &flags, &ptp_cfg);
	if (ret)
		return ret;

	ret = hclge_ptp_cfg(hdev, ptp_cfg);
	if (ret)
		return ret;

	hdev->ptp->flags = flags;
	hdev->ptp->ptp_cfg = ptp_cfg;

	return 0;
}

int hclge_ptp_set_cfg(struct hclge_dev *hdev, struct ifreq *ifr)
{
	struct hwtstamp_config cfg;
	int ret;

	if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) {
		dev_err(&hdev->pdev->dev, "phc is unsupported\n");
		return -EOPNOTSUPP;
	}

	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
		return -EFAULT;

	ret = hclge_ptp_set_ts_mode(hdev, &cfg);
	if (ret)
		return ret;

	hdev->ptp->ts_cfg = cfg;

	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}

int hclge_ptp_get_ts_info(struct hnae3_handle *handle,
			  struct kernel_ethtool_ts_info *info)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;

	if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) {
		dev_err(&hdev->pdev->dev, "phc is unsupported\n");
		return -EOPNOTSUPP;
	}

	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
				SOF_TIMESTAMPING_TX_HARDWARE |
				SOF_TIMESTAMPING_RX_HARDWARE |
				SOF_TIMESTAMPING_RAW_HARDWARE;

	if (hdev->ptp->clock)
		info->phc_index = ptp_clock_index(hdev->ptp->clock);

	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);

	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ);

	info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
			    BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
			    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
			    BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
			    BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) |
			    BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
			    BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
			    BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);

	return 0;
}

static int hclge_ptp_create_clock(struct hclge_dev *hdev)
{
	struct hclge_ptp *ptp;

	ptp = devm_kzalloc(&hdev->pdev->dev, sizeof(*ptp), GFP_KERNEL);
	if (!ptp)
		return -ENOMEM;

	ptp->hdev = hdev;
	snprintf(ptp->info.name, sizeof(ptp->info.name), "%s",
		 HCLGE_DRIVER_NAME);
	ptp->info.owner = THIS_MODULE;
	ptp->info.max_adj = HCLGE_PTP_CYCLE_ADJ_MAX;
	ptp->info.n_ext_ts = 0;
	ptp->info.pps = 0;
	ptp->info.adjfine = hclge_ptp_adjfine;
	ptp->info.adjtime = hclge_ptp_adjtime;
	ptp->info.gettimex64 = hclge_ptp_gettimex;
	ptp->info.settime64 = hclge_ptp_settime;

	ptp->info.n_alarm = 0;
	ptp->clock = ptp_clock_register(&ptp->info, &hdev->pdev->dev);
	if (IS_ERR(ptp->clock)) {
		dev_err(&hdev->pdev->dev,
			"%d failed to register ptp clock, ret = %ld\n",
			ptp->info.n_alarm, PTR_ERR(ptp->clock));
		return -ENODEV;
	} else if (!ptp->clock) {
		dev_err(&hdev->pdev->dev, "failed to register ptp clock\n");
		return -ENODEV;
	}

	spin_lock_init(&ptp->lock);
	ptp->io_base = hdev->hw.hw.io_base + HCLGE_PTP_REG_OFFSET;
	ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
	ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF;
	hdev->ptp = ptp;

	return 0;
}

static void hclge_ptp_destroy_clock(struct hclge_dev *hdev)
{
	ptp_clock_unregister(hdev->ptp->clock);
	hdev->ptp->clock = NULL;
	devm_kfree(&hdev->pdev->dev, hdev->ptp);
	hdev->ptp = NULL;
}

int hclge_ptp_init(struct hclge_dev *hdev)
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
	struct timespec64 ts;
	int ret;

	if (!test_bit(HNAE3_DEV_SUPPORT_PTP_B, ae_dev->caps))
		return 0;

	if (!hdev->ptp) {
		ret = hclge_ptp_create_clock(hdev);
		if (ret)
			return ret;

		ret = hclge_ptp_get_cycle(hdev);
		if (ret)
			return ret;
	}

	ret = hclge_ptp_int_en(hdev, true);
	if (ret)
		goto out;

	set_bit(HCLGE_PTP_FLAG_EN, &hdev->ptp->flags);
	ret = hclge_ptp_adjfine(&hdev->ptp->info, 0);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"failed to init freq, ret = %d\n", ret);
		goto out;
	}

	ret = hclge_ptp_set_ts_mode(hdev, &hdev->ptp->ts_cfg);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"failed to init ts mode, ret = %d\n", ret);
		goto out;
	}

	ktime_get_real_ts64(&ts);
	ret = hclge_ptp_settime(&hdev->ptp->info, &ts);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"failed to init ts time, ret = %d\n", ret);
		goto out;
	}

	set_bit(HCLGE_STATE_PTP_EN, &hdev->state);
	dev_info(&hdev->pdev->dev, "phc initializes ok!\n");

	return 0;

out:
	hclge_ptp_destroy_clock(hdev);

	return ret;
}

void hclge_ptp_uninit(struct hclge_dev *hdev)
{
	struct hclge_ptp *ptp = hdev->ptp;

	if (!ptp)
		return;

	hclge_ptp_int_en(hdev, false);
	clear_bit(HCLGE_STATE_PTP_EN, &hdev->state);
	clear_bit(HCLGE_PTP_FLAG_EN, &ptp->flags);
	ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
	ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF;

	if (hclge_ptp_set_ts_mode(hdev, &ptp->ts_cfg))
		dev_err(&hdev->pdev->dev, "failed to disable phc\n");

	if (ptp->tx_skb) {
		struct sk_buff *skb = ptp->tx_skb;

		ptp->tx_skb = NULL;
		dev_kfree_skb_any(skb);
	}

	hclge_ptp_destroy_clock(hdev);
}
