/*
 * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.

 * 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.
*/
#include <common.h>
#include <net.h>
#include <asm-generic/errno.h>
#include <asm/io.h>
#include <malloc.h>
#include <phy.h>
#include "ipq_gephy.h"
#include "ipq_phy.h"

extern int ipq5018_mdio_read(int mii_id,
		int regnum, ushort *data);
extern int ipq5018_mdio_write(int mii_id,
		int regnum, u16 data);

u16 gephy_phy_reg_read(u32 dev_id, u32 phy_id, u32 reg_id)
{
	return ipq5018_mdio_read(phy_id, reg_id, NULL);
}

u16 gephy_phy_reg_write(u32 dev_id, u32 phy_id, u32 reg_id, u16 value)
{
	return ipq5018_mdio_write(phy_id, reg_id, value);
}

u8 gephy_phy_get_link_status(u32 dev_id, u32 phy_id)
{
	u16 phy_data;
	phy_data = gephy_phy_reg_read(dev_id,
			phy_id, GEPHY_PHY_SPEC_STATUS);
	if (phy_data & GEPHY_STATUS_LINK_PASS)
		return 0;

	return 1;
}

u32 gephy_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex)
{
	u16 phy_data;

	phy_data = gephy_phy_reg_read(dev_id, phy_id,
				GEPHY_PHY_SPEC_STATUS);

	/*
	 * Read duplex
	 */
	if (phy_data & GEPHY_STATUS_FULL_DUPLEX)
		*duplex = FAL_FULL_DUPLEX;
	else
		*duplex = FAL_HALF_DUPLEX;

	return 0;
}

u32 gephy_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed)
{
	u16 phy_data;

	phy_data = gephy_phy_reg_read(dev_id,
			phy_id, GEPHY_PHY_SPEC_STATUS);

	switch (phy_data & GEPHY_STATUS_SPEED_MASK) {
	case GEPHY_STATUS_SPEED_2500MBS:
		*speed = FAL_SPEED_2500;
		break;
	case GEPHY_STATUS_SPEED_1000MBS:
		*speed = FAL_SPEED_1000;
		break;
	case GEPHY_STATUS_SPEED_100MBS:
		*speed = FAL_SPEED_100;
		break;
	case GEPHY_STATUS_SPEED_10MBS:
		*speed = FAL_SPEED_10;
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

int ipq_gephy_phy_init(struct phy_ops **ops, u32 phy_id)
{
	u16 phy_data;
	struct phy_ops *gephy_ops;

	gephy_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
	if (!gephy_ops)
		return -ENOMEM;
	gephy_ops->phy_get_link_status = gephy_phy_get_link_status;
	gephy_ops->phy_get_speed = gephy_phy_get_speed;
	gephy_ops->phy_get_duplex = gephy_phy_get_duplex;
	*ops = gephy_ops;

	phy_data = gephy_phy_reg_read(0x0, phy_id, GEPHY_PHY_ID1);
	printf ("PHY ID1: 0x%x\n", phy_data);
	phy_data = gephy_phy_reg_read(0x0, phy_id, GEPHY_PHY_ID2);
	printf ("PHY ID2: 0x%x\n", phy_data);

	/*enable vga when init napa to fix 8023az issue*/
	phy_data = gephy_phy_reg_read(0x0, phy_id, QCA808X_8023AZ_ENABLE_VGA);
	phy_data &= (~QCA808X_PHY_8023AZ_AFE_CTRL_MASK);
	phy_data |= QCA808X_PHY_8023AZ_AFE_EN;
	phy_data = gephy_phy_reg_write(0x0, phy_id, QCA808X_8023AZ_ENABLE_VGA, phy_data);
	if (phy_data != 0)
		return phy_data;

	/*special configuration for AZ under 1G speed mode*/
	phy_data = QCA808X_PHY_MMD3_AZ_TRAINING_VAL;
	phy_data = gephy_phy_reg_write(0x0, phy_id, QCA808X_AZ_CONFIG_UNDER_1G_SPEED,
					phy_data);
	return phy_data;
}
