/*
 * Copyright (c) 2018, 2020-2021, The Linux Foundation. All rights reserved.
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all copies.
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "sw.h"
#include "fal_port_ctrl.h"
#include "adpt.h"
#include "hsl_api.h"
#include "hsl.h"
#include "sfp_phy.h"
#include "aos_timer.h"
#include "hsl_phy.h"
#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/phy.h>
#include "ssdk_plat.h"
#include "ssdk_phy_i2c.h"
#include "ssdk_dts.h"

/******************************************************************************
*
* sfp_phy_init -
*
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION (5, 0, 0))
#define SFP_PHY_FEATURES        (SUPPORTED_FIBRE | \
                                SUPPORTED_1000baseT_Full | \
                                SUPPORTED_10000baseT_Full | \
                                SUPPORTED_Pause | \
                                SUPPORTED_Asym_Pause) | \
                                SUPPORTED_2500baseX_Full
#else
__ETHTOOL_DECLARE_LINK_MODE_MASK(SFP_PHY_FEATURES) __ro_after_init;
#endif

static int
sfp_phy_probe(struct phy_device *pdev)
{
	pdev->autoneg = AUTONEG_DISABLE;
	SSDK_INFO("sfp phy is probed!\n");
	return 0;
}

static void
sfp_phy_remove(struct phy_device *pdev)
{
	return;
}

static int
sfp_phy_config_aneg(struct phy_device *pdev)
{

	return 0;
}

static int
sfp_phy_aneg_done(struct phy_device *pdev)
{

	return SFP_ANEG_DONE;
}

static int
sfp_read_status(struct phy_device *pdev)
{
	fal_port_t port;
	a_uint32_t addr;
	struct qca_phy_priv *priv = pdev->priv;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0))
	addr = pdev->mdio.addr;
#else
	addr = pdev->addr;
#endif
	port = qca_ssdk_phy_addr_to_port(priv->device_id, addr);
	pdev->link = priv->port_old_link[port - 1];
	pdev->speed = priv->port_old_speed[port - 1];
	pdev->duplex = priv->port_old_duplex[port - 1];

	return 0;
}

#if (LINUX_VERSION_CODE < KERNEL_VERSION (5, 0, 0))
static int
sfp_phy_update_link(struct phy_device *pdev)
{
	int ret;

	ret = sfp_read_status(pdev);

	return ret;
}
#endif

static struct phy_driver sfp_phy_driver = {
	.name		= "QCA SFP",
	.phy_id		= SFP_PHY,
	.phy_id_mask = SFP_PHY_MASK,
	.probe		= sfp_phy_probe,
	.remove		= sfp_phy_remove,
	.config_aneg	= sfp_phy_config_aneg,
	.aneg_done	= sfp_phy_aneg_done,
	.read_status	= sfp_read_status,
	.features	= SFP_PHY_FEATURES,
#if (LINUX_VERSION_CODE < KERNEL_VERSION (5, 0, 0))
	.update_link	= sfp_phy_update_link,
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0))
	.mdiodrv.driver	= { .owner = THIS_MODULE },
#else
	.driver		= { .owner = THIS_MODULE },
#endif
};

int sfp_phy_device_setup(a_uint32_t dev_id, a_uint32_t port, a_uint32_t phy_id)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
	struct phy_device *phydev;
	struct qca_phy_priv *priv;
	a_uint32_t addr = 0;
	struct mii_bus *bus;

	priv = ssdk_phy_priv_data_get(dev_id);
	/*create phy device*/
#if defined(IN_PHY_I2C_MODE)
	if (hsl_port_phy_access_type_get(dev_id, port) == PHY_I2C_ACCESS) {
		addr = qca_ssdk_port_to_phy_mdio_fake_addr(dev_id, port);
	} else
#endif
	{
		addr = qca_ssdk_port_to_phy_addr(dev_id, port);
	}
	bus = ssdk_miibus_get_by_device(dev_id);
	phydev = phy_device_create(bus, addr, phy_id, false, NULL);
	if (IS_ERR(phydev) || phydev == NULL) {
		SSDK_ERROR("Failed to create phy device!\n");
		return SW_NOT_SUPPORTED;
	}
	/*register phy device*/
	phy_device_register(phydev);

	phydev->priv = priv;
#endif
	return 0;
}

void sfp_phy_device_remove(a_uint32_t dev_id, a_uint32_t port)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
	struct phy_device *phydev = NULL;
	a_uint32_t addr = 0;
	struct mii_bus *bus;

	bus = ssdk_miibus_get_by_device(dev_id);
#if defined(IN_PHY_I2C_MODE)
	if (hsl_port_phy_access_type_get(dev_id, port) == PHY_I2C_ACCESS) {
		addr = qca_ssdk_port_to_phy_mdio_fake_addr(dev_id, port);
	} else
#endif
	{
		addr = qca_ssdk_port_to_phy_addr(dev_id, port);
	}

	if (addr < PHY_MAX_ADDR)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
		if (bus->mdio_map[addr])
			phydev = to_phy_device(&bus->mdio_map[addr]->dev);
#else
		phydev = bus->phy_map[addr];
#endif
	if (phydev)
		phy_device_remove(phydev);
#endif
}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
static void sfp_features_init(void)
{
	const int features[] = {
		ETHTOOL_LINK_MODE_FIBRE_BIT,
		ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
		ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
		ETHTOOL_LINK_MODE_Pause_BIT,
		ETHTOOL_LINK_MODE_Asym_Pause_BIT,
	};

	linkmode_set_bit_array(features,
		ARRAY_SIZE(features),
		SFP_PHY_FEATURES);
}
#endif

int sfp_phy_init(a_uint32_t dev_id, a_uint32_t port_bmp)
{
	a_uint32_t port_id = 0;

	SSDK_INFO("sfp phy init for port 0x%x!\n", port_bmp);

	for (port_id = 0; port_id < SW_MAX_NR_PORT; port_id ++) {
		if (port_bmp & (0x1 << port_id)) {
			sfp_phy_device_setup(dev_id, port_id, SFP_PHY);
		}
	}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
	sfp_features_init();
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0))
	phy_driver_register(&sfp_phy_driver, THIS_MODULE);
#else
	phy_driver_register(&sfp_phy_driver);
#endif
	return 0;
}

void sfp_phy_exit(a_uint32_t dev_id, a_uint32_t port_bmp)
{
	a_uint32_t port_id = 0;

	phy_driver_unregister(&sfp_phy_driver);

	for (port_id = 0; port_id < SW_MAX_NR_PORT; port_id ++) {
		if (port_bmp & (0x1 << port_id)) {
			sfp_phy_device_remove(dev_id, port_id);
		}
	}

}

sw_error_t sfp_phy_interface_get_mode_status(a_uint32_t dev_id,
	a_uint32_t port_id, fal_port_interface_mode_t *interface_mode_status)
{
	sw_error_t rv = SW_OK;
	a_uint16_t reg_data = 0, sfp_speed = 0;

	rv = qca_phy_i2c_mii_read(dev_id, SFP_E2PROM_ADDR, SFP_SPEED_ADDR,
		&reg_data);
	SW_RTN_ON_ERROR(rv);
	sfp_speed = SFP_TO_SFP_SPEED(reg_data);
	SSDK_DEBUG("sfp_speed:%d\n", sfp_speed);

	if(sfp_speed >= SFP_SPEED_1000M &&
		sfp_speed < SFP_SPEED_2500M)
	{
		*interface_mode_status =  PORT_SGMII_FIBER;
	}
	else if(sfp_speed >= SFP_SPEED_10000M)
	{
		*interface_mode_status =  PORT_10GBASE_R;
	}
	else if(sfp_speed >= SFP_SPEED_2500M &&
		sfp_speed < SFP_SPEED_5000M)
	{
		struct port_phy_status sfp_status= {0};
		adpt_api_t *p_api;
		struct phy_device *phydev;

		rv = hsl_port_phydev_get(dev_id, port_id, &phydev);
		SW_RTN_ON_ERROR(rv);
		SW_RTN_ON_NULL(p_api = adpt_api_ptr_get(dev_id));
		rv = p_api->adpt_port_phy_status_get(dev_id, port_id, &sfp_status);
		SW_RTN_ON_ERROR(rv);

		if (sfp_status.link_status == PORT_LINK_DOWN) {
			/*autoneg is for different speed switching on one SFP module*/
			if (phydev->autoneg == AUTONEG_ENABLE) {
				if (sfp_status.link_status == PORT_LINK_DOWN) {
					if (*interface_mode_status == PHY_SGMII_BASET) {
						*interface_mode_status = PORT_SGMII_PLUS;
					} else {
						*interface_mode_status = PHY_SGMII_BASET;
					}
				}
			} else {
				*interface_mode_status = PORT_SGMII_PLUS;
			}
			return SW_OK;
		}
		if (sfp_status.link_status == PORT_LINK_UP) {
			/*solution for SFP link up case under 10G-R mode*/
			if ((*interface_mode_status != PHY_SGMII_BASET) &&
				(*interface_mode_status != PORT_SGMII_PLUS)) {
				*interface_mode_status = PORT_SGMII_PLUS;
			}
			return SW_OK;
		}
	}
	else
	{
		return SW_NOT_SUPPORTED;
	}

	return SW_OK;
}
