/*
   forward-ethernet.h - ethernet driver for SoftLab-NSK Forward boards

   Copyright (C) 2017 - 2024 SoftLab-NSK <forward@softlab.tv>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef FORWARD_ETHERNET_H
#define FORWARD_ETHERNET_H

#define FORWARD_ETHERNET_MAX_PORTS 2

#include "forward.h"
#include "forward-irq.h"

#include <linux/netdevice.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>

#define FORWARD_ETHERNET_MODULE_NAME "forward-ethernet"
#define FORWARD_ETHERNET_MODE_NAME "ethernet"

struct forward_ethernet;
struct ethtool_link_ksettings;

struct forward_ethernet_board {
	struct forward_dev *dev;
	int num_eth;
	const struct forward_ethernet_ops *ops;

	struct forward_ethernet *eths[FORWARD_ETHERNET_MAX_PORTS];

	struct ptp_clock *ptp_clock;
	struct ptp_clock_info ptp_clock_info;
	struct forward_sdma *sdma;
};

struct forward_ethernet_stats {
	u64 rx_packets;
	u64 rx_bytes;
	u64 rx_mac_errors;
	u64 rx_fifo_errors;

	u64 tx_packets;
	u64 tx_bytes;
};

struct forward_ethernet {
	struct forward_ethernet_board *board;
	struct forward_dev *dev;
	const struct forward_ethernet_ops *ops;
	int index;

	struct forward_sdma_io_ring *rx, *tx;
	struct net_device *net;
	struct napi_struct napi_rx, napi_tx;
	struct forward_irq_listener irq;
	spinlock_t lock;
	struct timespec64 irq_time;
	u16 rx_pointer, tx_pointer;
	u16 tx_queued;
	struct hwtstamp_config ts_config;
	spinlock_t stats_lock;
	struct forward_ethernet_stats stats;
	struct delayed_work watchdog;
};

struct forward_ethernet_ops {
	int num_eth;
	int sdma_size;
	int sdma_rings;

	int (*init)(struct forward_ethernet *eth);
	void (*fini)(struct forward_ethernet *eth);

	forward_irq_t (*irq_mask)(struct forward_ethernet *eth);
	void (*disable_irq)(struct forward_ethernet *eth, bool rx, bool tx);
	void (*enable_irq)(struct forward_ethernet *eth, bool rx, bool tx);
	void (*irq_info)(struct forward_ethernet *eth, const forward_irq_t *irq, bool *rx, bool *tx,
			 struct timespec64 *ts);

	int (*toggle_link)(struct forward_ethernet *eth, bool up);
	int (*toggle_mcast)(struct forward_ethernet *eth, bool mcast, bool promisc);
	int (*set_mac)(struct forward_ethernet *eth, u8 *addr);
	bool (*get_link_status)(struct forward_ethernet *eth);

	void (*get_link_ksettings)(struct forward_ethernet *eth,
				   struct ethtool_link_ksettings *cmd);
	int (*set_link_ksettings)(struct forward_ethernet *eth,
				  const struct ethtool_link_ksettings *cmd);

	void (*update_stats)(struct forward_ethernet *eth);

	int (*ptp_adjfine)(struct forward_ethernet_board *brd, s64 ppt);
	int (*ptp_adjtime)(struct forward_ethernet_board *brd, s64 delta);
	int (*ptp_gettimex)(struct forward_ethernet_board *brd, struct timespec64 *ts,
			    struct ptp_system_timestamp *sts);
	int (*ptp_settime)(struct forward_ethernet_board *brd, const struct timespec64 *ts);

	int (*sfp_read_reg)(struct forward_ethernet *eth, u16 address, u8 *data);
	void (*sfp_status)(struct forward_ethernet *eth, bool *absense, bool *rx_los,
			   bool *tx_fault);
};

void forward_ethernet_ptp_init(struct forward_ethernet_board *brd);
void forward_ethernet_ptp_remove(struct forward_ethernet_board *brd);

#endif
