/*
 * Copyright 2022 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(nxp_s32_eth_psi);

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/mbox.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_pkt.h>
#include <zephyr/net/phy.h>
#include <ethernet/eth_stats.h>

#include <soc.h>
#include <Netc_Eth_Ip.h>
#include <Netc_Eth_Ip_Irq.h>
#include <Netc_EthSwt_Ip.h>

#include "eth.h"
#include "eth_nxp_s32_netc_priv.h"

#define PSI_NODE	DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_psi)
#define PHY_NODE	DT_PHANDLE(PSI_NODE, phy_handle)
#define INIT_VSIS	DT_NODE_HAS_PROP(PSI_NODE, vsis)
#define TX_RING_IDX	1
#define RX_RING_IDX	0

static void nxp_s32_eth_configure_port(uint8_t port_idx, enum phy_link_speed speed)
{
	EthTrcv_BaudRateType baudrate;
	Netc_EthSwt_Ip_PortDuplexType duplex;
	Std_ReturnType status;

	(void)Netc_EthSwt_Ip_SetPortMode(NETC_SWITCH_IDX, port_idx, false);

	baudrate = PHY_TO_NETC_SPEED(speed);
	status = Netc_EthSwt_Ip_SetPortSpeed(NETC_SWITCH_IDX, port_idx, baudrate);
	if (status != E_OK) {
		LOG_ERR("Failed to set port %d speed: %d", port_idx, status);
		return;
	}

	duplex = PHY_TO_NETC_DUPLEX_MODE(speed);
	status = Netc_EthSwt_Ip_SetPortMacLayerDuplexMode(NETC_SWITCH_IDX, port_idx, duplex);
	if (status != E_OK) {
		LOG_ERR("Failed to set port %d duplex mode: %d", port_idx, status);
		return;
	}

	(void)Netc_EthSwt_Ip_SetPortMode(NETC_SWITCH_IDX, port_idx, true);
}

static void phy_link_state_changed(const struct device *pdev,
				   struct phy_link_state *state,
				   void *user_data)
{
	const struct device *dev = (struct device *)user_data;
	const struct nxp_s32_eth_config *cfg = dev->config;
	const struct nxp_s32_eth_data *ctx = dev->data;

	ARG_UNUSED(pdev);

	if (state->is_up) {
		LOG_DBG("Link up");
		nxp_s32_eth_configure_port(cfg->port_idx, state->speed);
		net_eth_carrier_on(ctx->iface);
	} else {
		LOG_DBG("Link down");
		net_eth_carrier_off(ctx->iface);
	}
}

/* Configure ETHx_EXT_RX_CLK @ 125 MHz as source of ETH_x_RGMII_RX_CLK */
static int nxp_s32_eth_configure_cgm(uint8_t port_idx)
{
	uint32_t tout = 0xFFFFFFFF;

	if (port_idx == 0) {
		IP_MC_CGM_1->MUX_7_CSC = (IP_MC_CGM_1->MUX_7_CSC & ~MC_CGM_MUX_7_CSC_SELCTL_MASK)
					| MC_CGM_MUX_7_CSC_SELCTL(NETC_ETH_0_RX_CLK_IDX);
		IP_MC_CGM_1->MUX_7_CSC = (IP_MC_CGM_1->MUX_7_CSC & ~MC_CGM_MUX_7_CSC_CLK_SW_MASK)
					| MC_CGM_MUX_7_CSC_CLK_SW(1);

		while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_CLK_SW_MASK) == 0)
				&& (tout > 0)) {
			tout--;
		}
		while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWIP_MASK) != 0)
				&& (tout > 0)) {
			tout--;
		}
		while (((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SWTRG_MASK)
				>> MC_CGM_MUX_7_CSS_SWTRG_SHIFT != 1) && (tout > 0)) {
			tout--;
		}

		__ASSERT_NO_MSG(((IP_MC_CGM_1->MUX_7_CSS & MC_CGM_MUX_7_CSS_SELSTAT_MASK)
				 >> MC_CGM_MUX_7_CSS_SELSTAT_SHIFT) == NETC_ETH_0_RX_CLK_IDX);

	} else if (port_idx == 1) {
		IP_MC_CGM_1->MUX_9_CSC = (IP_MC_CGM_1->MUX_9_CSC & ~MC_CGM_MUX_9_CSC_SELCTL_MASK)
					| MC_CGM_MUX_9_CSC_SELCTL(NETC_ETH_1_RX_CLK_IDX);
		IP_MC_CGM_1->MUX_9_CSC = (IP_MC_CGM_1->MUX_9_CSC & ~MC_CGM_MUX_9_CSC_CLK_SW_MASK)
					| MC_CGM_MUX_9_CSC_CLK_SW(1);

		while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_CLK_SW_MASK) == 0)
				&& (tout > 0)) {
			tout--;
		}
		while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWIP_MASK) != 0)
				&& (tout > 0)) {
			tout--;
		}
		while (((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SWTRG_MASK)
				>> MC_CGM_MUX_9_CSS_SWTRG_SHIFT != 1) && (tout > 0)) {
			tout--;
		}

		__ASSERT_NO_MSG(((IP_MC_CGM_1->MUX_9_CSS & MC_CGM_MUX_9_CSS_SELSTAT_MASK)
				 >> MC_CGM_MUX_9_CSS_SELSTAT_SHIFT) == NETC_ETH_1_RX_CLK_IDX);
	} else {
		return -EINVAL;
	}

	return 0;
}

static int nxp_s32_eth_initialize(const struct device *dev)
{
	const struct nxp_s32_eth_config *cfg = dev->config;
	int err;

	err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
	if (err != 0) {
		return err;
	}

	err = nxp_s32_eth_configure_cgm(cfg->port_idx);
	if (err != 0) {
		LOG_ERR("Failed to configure NETC Switch CGM");
		return -EIO;
	}

	return nxp_s32_eth_initialize_common(dev);
}

static void nxp_s32_eth_iface_init(struct net_if *iface)
{
	const struct device *dev = net_if_get_device(iface);
	struct nxp_s32_eth_data *ctx = dev->data;
	const struct nxp_s32_eth_config *cfg = dev->config;
	const struct nxp_s32_eth_msix *msix;
#if defined(CONFIG_NET_IPV6)
	static struct net_if_mcast_monitor mon;

	net_if_mcast_mon_register(&mon, iface, nxp_s32_eth_mcast_cb);
#endif /* CONFIG_NET_IPV6 */

	/*
	 * For VLAN, this value is only used to get the correct L2 driver.
	 * The iface pointer in context should contain the main interface
	 * if the VLANs are enabled.
	 */
	if (ctx->iface == NULL) {
		ctx->iface = iface;
	}

	Netc_Eth_Ip_SetMacAddr(cfg->si_idx, (const uint8_t *)ctx->mac_addr);
	net_if_set_link_addr(iface, ctx->mac_addr, sizeof(ctx->mac_addr), NET_LINK_ETHERNET);

	LOG_INF("SI%d MAC: %02x:%02x:%02x:%02x:%02x:%02x", cfg->si_idx,
		ctx->mac_addr[0], ctx->mac_addr[1], ctx->mac_addr[2],
		ctx->mac_addr[3], ctx->mac_addr[4], ctx->mac_addr[5]);

	ethernet_init(iface);

	/*
	 * PSI controls the PHY. If PHY is configured either as fixed
	 * link or autoneg, the callback is executed at least once
	 * immediately after setting it.
	 */
	if (!device_is_ready(cfg->phy_dev)) {
		LOG_ERR("PHY device (%p) is not ready, cannot init iface",
			cfg->phy_dev);
		return;
	}
	phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev);

	/* Do not start the interface until PHY link is up */
	net_if_carrier_off(iface);

	for (int i = 0; i < NETC_MSIX_EVENTS_COUNT; i++) {
		msix = &cfg->msix[i];
		if (msix->mbox_channel.dev != NULL) {
			if (mbox_set_enabled(&msix->mbox_channel, true)) {
				LOG_ERR("Failed to enable MRU channel %u", msix->mbox_channel.id);
			}
		}
	}
}

static void nxp_s32_eth0_rx_callback(const uint8_t unused, const uint8_t ring)
{
	const struct device *dev = DEVICE_DT_GET(PSI_NODE);
	const struct nxp_s32_eth_config *cfg = dev->config;
	struct nxp_s32_eth_data *ctx = dev->data;

	ARG_UNUSED(unused);

	if (ring == cfg->rx_ring_idx) {
		k_sem_give(&ctx->rx_sem);
	}
}

static const struct ethernet_api nxp_s32_eth_api = {
	.iface_api.init = nxp_s32_eth_iface_init,
	.get_capabilities = nxp_s32_eth_get_capabilities,
	.set_config = nxp_s32_eth_set_config,
	.send = nxp_s32_eth_tx
};

BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nxp_s32_netc_psi) == 1, "Only one PSI enabled supported");

#define NETC_VSI_GENERAL_CFG(node, prop, idx)					\
	[DT_PROP_BY_IDX(node, prop, idx)] = {					\
		.siId = DT_PROP_BY_IDX(node, prop, idx),			\
		.enableSi = true,						\
		.NumberOfRxBDR = 1,						\
		.NumberOfTxBDR = 1,						\
		.SIVlanControl = (NETC_F3_PSICFGR0_SIVC_CVLAN_BIT		\
				| NETC_F3_PSICFGR0_SIVC_SVLAN_BIT),		\
	}

#define NETC_VSI_RX_MSG_BUF(node, prop, idx)							\
	BUILD_ASSERT((DT_PROP_BY_IDX(node, prop, idx) > NETC_ETH_IP_PSI_INDEX)			\
		&& (DT_PROP_BY_IDX(node, prop, idx) <= FEATURE_NETC_ETH_NUM_OF_VIRTUAL_CTRLS),	\
		"Invalid VSI index");								\
	static Netc_Eth_Ip_VsiToPsiMsgType							\
	_CONCAT3(nxp_s32_eth0_vsi, DT_PROP_BY_IDX(node, prop, idx), _rx_msg_buf)		\
		__aligned(FEATURE_NETC_ETH_VSI_MSG_ALIGNMENT)

#define NETC_VSI_RX_MSG_BUF_ARRAY(node, prop, idx)						\
	[DT_PROP_BY_IDX(node, prop, idx) - 1] =							\
		&_CONCAT3(nxp_s32_eth0_vsi, DT_PROP_BY_IDX(node, prop, idx), _rx_msg_buf)

#define NETC_SWITCH_PORT_CFG(_, __)						\
	{									\
		.ePort = &nxp_s32_eth0_switch_port_egress_cfg,			\
		.iPort = &nxp_s32_eth0_switch_port_ingress_cfg,			\
		.EthSwtPortMacLayerPortEnable = true,				\
		.EthSwtPortMacLayerSpeed = ETHTRCV_BAUD_RATE_1000MBIT,		\
		.EthSwtPortMacLayerDuplexMode = NETC_ETHSWT_PORT_FULL_DUPLEX,	\
		.EthSwtPortPhysicalLayerType = NETC_ETHSWT_RGMII_MODE,		\
		.EthSwtPortPruningEnable = true,				\
	}

static Netc_Eth_Ip_StateType nxp_s32_eth0_state;

static Netc_Eth_Ip_MACFilterHashTableEntryType
nxp_s32_eth0_mac_filter_hash_table[CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE];

NETC_TX_RING(0, 0, NETC_MIN_RING_LEN, NETC_MIN_RING_BUF_SIZE);
NETC_TX_RING(0, TX_RING_IDX,
	     CONFIG_ETH_NXP_S32_TX_RING_LEN, CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE);
NETC_RX_RING(0, RX_RING_IDX,
	     CONFIG_ETH_NXP_S32_RX_RING_LEN, CONFIG_ETH_NXP_S32_RX_RING_BUF_SIZE);

static const Netc_Eth_Ip_RxRingConfigType nxp_s32_eth0_rxring_cfg[1] = {
	{
		.RingDesc = nxp_s32_eth0_rxring0_desc,
		.Buffer = nxp_s32_eth0_rxring0_buf,
		.ringSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,
		.maxRingSize = CONFIG_ETH_NXP_S32_RX_RING_LEN,
		.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
		.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
		.TimerThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_TIMER_THRESHOLD,
		.PacketsThreshold = CONFIG_ETH_NXP_S32_RX_IRQ_PACKET_THRESHOLD,
		.Callback = nxp_s32_eth0_rx_callback,
	}
};

static const Netc_Eth_Ip_TxRingConfigType nxp_s32_eth0_txring_cfg[2] = {
	{
		.RingDesc = nxp_s32_eth0_txring0_desc,
		.Buffer = nxp_s32_eth0_txring0_buf,
		.ringSize = NETC_MIN_RING_LEN,
		.maxRingSize = NETC_MIN_RING_LEN,
		.bufferLen = NETC_MIN_RING_BUF_SIZE,
		.maxBuffLen = NETC_MIN_RING_BUF_SIZE,
	},
	{
		.RingDesc = nxp_s32_eth0_txring1_desc,
		.Buffer = nxp_s32_eth0_txring1_buf,
		.ringSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,
		.maxRingSize = CONFIG_ETH_NXP_S32_TX_RING_LEN,
		.bufferLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
		.maxBuffLen = CONFIG_ETH_NXP_S32_TX_RING_BUF_SIZE,
	}
};

static const Netc_Eth_Ip_GeneralSIConfigType
nxp_s32_eth0_psi_cfg[FEATURE_NETC_ETH_NUMBER_OF_CTRLS] = {
	[NETC_ETH_IP_PSI_INDEX] = {
		.siId = NETC_ETH_IP_PSI_INDEX,
		.enableSi = true,
		.NumberOfRxBDR = 1,
		.NumberOfTxBDR = 2,
		.SIVlanControl = (NETC_F3_PSICFGR0_SIVC_CVLAN_BIT
				| NETC_F3_PSICFGR0_SIVC_SVLAN_BIT),
	},
	COND_CODE_1(INIT_VSIS,
		(DT_FOREACH_PROP_ELEM_SEP(PSI_NODE, vsis, NETC_VSI_GENERAL_CFG, (,))),
		(EMPTY))
};

COND_CODE_1(INIT_VSIS,
	(DT_FOREACH_PROP_ELEM_SEP(PSI_NODE, vsis, NETC_VSI_RX_MSG_BUF, (;))),
	(EMPTY));

static const Netc_Eth_Ip_EnetcGeneralConfigType nxp_s32_eth0_enetc_general_cfg = {
	.numberOfConfiguredSis = FEATURE_NETC_ETH_NUMBER_OF_CTRLS,
	.stationInterfaceGeneralConfig = &nxp_s32_eth0_psi_cfg,
#if defined(CONFIG_NET_PROMISCUOUS_MODE)
	.maskMACPromiscuousMulticastEnable = (uint16_t)true,
	.maskMACPromiscuousUnicastEnable = (uint16_t)true,
#endif
	.RxVsiMsgCmdToPsi = {
		COND_CODE_1(INIT_VSIS,
			(DT_FOREACH_PROP_ELEM_SEP(PSI_NODE, vsis,
				NETC_VSI_RX_MSG_BUF_ARRAY, (,))),
			(EMPTY))
	},
};

static const Netc_Eth_Ip_StationInterfaceConfigType nxp_s32_eth0_si_cfg = {
	.NumberOfRxBDR = 1,
	.NumberOfTxBDR = 2,
	.txMruMailboxAddr = NULL,
	.rxMruMailboxAddr = (uint32_t *)MRU_MBOX_ADDR(PSI_NODE, rx),
	.siMsgMruMailboxAddr = COND_CODE_1(INIT_VSIS,
		((uint32_t *)MRU_MBOX_ADDR(PSI_NODE, vsi_msg)), (NULL)),
	.RxInterrupts = (uint32_t)true,
	.TxInterrupts = (uint32_t)false,
	.MACFilterTableMaxNumOfEntries = CONFIG_ETH_NXP_S32_MAC_FILTER_TABLE_SIZE,
};

static uint8_t nxp_s32_eth0_switch_vlandr2dei_cfg[NETC_ETHSWT_NUMBER_OF_DR];
static Netc_EthSwt_Ip_PortIngressType nxp_s32_eth0_switch_port_ingress_cfg;
static Netc_EthSwt_Ip_PortEgressType nxp_s32_eth0_switch_port_egress_cfg = {
	.vlanDrToDei = &nxp_s32_eth0_switch_vlandr2dei_cfg,
};
static Netc_EthSwt_Ip_PortType nxp_s32_eth0_switch_ports_cfg[NETC_ETHSWT_NUMBER_OF_PORTS] = {
	LISTIFY(NETC_ETHSWT_NUMBER_OF_PORTS, NETC_SWITCH_PORT_CFG, (,))
};

static const Netc_EthSwt_Ip_ConfigType nxp_s32_eth0_switch_cfg = {
	.port = &nxp_s32_eth0_switch_ports_cfg,
	.EthSwtArlTableEntryTimeout = NETC_SWITCH_PORT_AGING,
	.netcClockFrequency = DT_PROP(PSI_NODE, clock_frequency),
	.MacLearningOption = ETHSWT_MACLEARNINGOPTION_HWDISABLED,
	.MacForwardingOption = ETHSWT_NO_FDB_LOOKUP_FLOOD_FRAME,
	.Timer1588ClkSrc = ETHSWT_REFERENCE_CLOCK_DISABLED,
};

PINCTRL_DT_DEFINE(PSI_NODE);

NETC_GENERATE_MAC_ADDRESS(PSI_NODE, 0)

static const struct nxp_s32_eth_config nxp_s32_eth0_config = {
	.netc_cfg = {
		.SiType = NETC_ETH_IP_PHYSICAL_SI,
		.siConfig = &nxp_s32_eth0_si_cfg,
		.generalConfig = &nxp_s32_eth0_enetc_general_cfg,
		.stateStructure = &nxp_s32_eth0_state,
		.paCtrlRxRingConfig = &nxp_s32_eth0_rxring_cfg,
		.paCtrlTxRingConfig = &nxp_s32_eth0_txring_cfg,
	},
	.si_idx = NETC_ETH_IP_PSI_INDEX,
	.port_idx = NETC_SWITCH_PORT_IDX,
	.tx_ring_idx = TX_RING_IDX,
	.rx_ring_idx = RX_RING_IDX,
	.msix = {
		NETC_MSIX(PSI_NODE, rx, Netc_Eth_Ip_0_MSIX_RxEvent),
		COND_CODE_1(INIT_VSIS,
			(NETC_MSIX(PSI_NODE, vsi_msg, Netc_Eth_Ip_MSIX_SIMsgEvent)),
			(EMPTY))
	},
	.mac_filter_hash_table = &nxp_s32_eth0_mac_filter_hash_table[0],
	.generate_mac = nxp_s32_eth0_generate_mac,
	.phy_dev = DEVICE_DT_GET(PHY_NODE),
	.pincfg = PINCTRL_DT_DEV_CONFIG_GET(PSI_NODE),
};

static struct nxp_s32_eth_data nxp_s32_eth0_data = {
	.mac_addr = DT_PROP_OR(PSI_NODE, local_mac_address, {0}),
};

ETH_NET_DEVICE_DT_DEFINE(PSI_NODE,
			nxp_s32_eth_initialize,
			NULL,
			&nxp_s32_eth0_data,
			&nxp_s32_eth0_config,
			CONFIG_ETH_INIT_PRIORITY,
			&nxp_s32_eth_api,
			NET_ETH_MTU);

static int nxp_s32_eth_switch_init(void)
{
	Std_ReturnType swt_status;

	swt_status = Netc_EthSwt_Ip_Init(NETC_SWITCH_IDX, &nxp_s32_eth0_switch_cfg);
	if (swt_status != E_OK) {
		LOG_ERR("Failed to initialize NETC Switch %d (%d)",
			NETC_SWITCH_IDX, swt_status);
		return -EIO;
	}

	return 0;
}

/*
 * NETC Switch driver must be initialized before any other NETC component.
 * This is because Netc_EthSwt_Ip_Init() will not only initialize the Switch,
 * but also perform global initialization, enable the PCIe functions for MDIO
 * and ENETC, and initialize MDIO with a fixed configuration.
 */
SYS_INIT(nxp_s32_eth_switch_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
