/*
 * Copyright (c) 2016 Piotr Mienkowski
 * SPDX-License-Identifier: Apache-2.0
 */

/** @file
 * @brief Atmel SAM MCU family Ethernet PHY (GMAC) driver.
 */

#include <errno.h>
#include <kernel.h>
#include <net/mii.h>
#include "phy_sam_gmac.h"

#define SYS_LOG_DOMAIN "soc/soc_phy"
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_ETHERNET_LEVEL
#include <logging/sys_log.h>

/* Maximum time to establish a link through auto-negotiation for
 * 10BASE-T, 100BASE-TX is 3.7s, to add an extra margin the timeout
 * is set at 4s.
 */
#define PHY_AUTONEG_TIMEOUT_MS   4000

/* Enable MDIO serial bus between MAC and PHY. */
static void mdio_bus_enable(Gmac *gmac)
{
	gmac->GMAC_NCR |= GMAC_NCR_MPE;
}

/* Disable MDIO serial bus between MAC and PHY. */
static void mdio_bus_disable(Gmac *gmac)
{
	gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
}

/* Wait PHY operation complete. */
static int mdio_bus_wait(Gmac *gmac)
{
	u32_t retries = 100;  /* will wait up to 1 s */

	while (!(gmac->GMAC_NSR & GMAC_NSR_IDLE))   {
		if (retries-- == 0) {
			SYS_LOG_ERR("timeout");
			return -ETIMEDOUT;
		}

		k_sleep(10);
	}

	return 0;
}

/* Send command to PHY over MDIO serial bus */
static int mdio_bus_send(Gmac *gmac, u8_t phy_addr, u8_t reg_addr,
			 u8_t rw, u16_t data)
{
	int retval;

	/* Write GMAC PHY maintenance register */
	gmac->GMAC_MAN =   GMAC_MAN_CLTTO
			 | (GMAC_MAN_OP(rw ? 0x2 : 0x1))
			 | GMAC_MAN_WTN(0x02)
			 | GMAC_MAN_PHYA(phy_addr)
			 | GMAC_MAN_REGA(reg_addr)
			 | GMAC_MAN_DATA(data);

	/* Wait until PHY is ready */
	retval = mdio_bus_wait(gmac);
	if (retval < 0) {
		return retval;
	}

	return 0;
}

/* Read PHY register. */
static int phy_read(const struct phy_sam_gmac_dev *phy, u8_t reg_addr,
		    u32_t *value)
{
	Gmac *const gmac = phy->regs;
	u8_t phy_addr = phy->address;
	int retval;

	retval = mdio_bus_send(gmac, phy_addr, reg_addr, 1, 0);
	if (retval < 0) {
		return retval;
	}

	/* Read data */
	*value = gmac->GMAC_MAN & GMAC_MAN_DATA_Msk;

	return 0;
}

/* Write PHY register. */
static int phy_write(const struct phy_sam_gmac_dev *phy, u8_t reg_addr,
		     u32_t value)
{
	Gmac *const gmac = phy->regs;
	u8_t phy_addr = phy->address;

	return mdio_bus_send(gmac, phy_addr, reg_addr, 0, value);
}

/* Issue a PHY soft reset. */
static int phy_soft_reset(const struct phy_sam_gmac_dev *phy)
{
	u32_t phy_reg;
	u32_t retries = 12;
	int retval;

	/* Issue a soft reset */
	retval = phy_write(phy, MII_BMCR, MII_BMCR_RESET);
	if (retval < 0) {
		return retval;
	}

	/* Wait up to 0.6s for the reset sequence to finish. According to
	 * IEEE 802.3, Section 2, Subsection 22.2.4.1.1 a PHY reset may take
	 * up to 0.5 s.
	 */
	do {
		if (retries-- == 0) {
			return -ETIMEDOUT;
		}

		k_sleep(50);

		retval = phy_read(phy, MII_BMCR, &phy_reg);
		if (retval < 0) {
			return retval;
		}
	} while (phy_reg & MII_BMCR_RESET);

	return 0;
}

int phy_sam_gmac_init(const struct phy_sam_gmac_dev *phy)
{
	Gmac *const gmac = phy->regs;
	int phy_id;

	mdio_bus_enable(gmac);

	SYS_LOG_INF("Soft Reset of ETH PHY");
	phy_soft_reset(phy);

	/* Verify that the PHY device is responding */
	phy_id = phy_sam_gmac_id_get(phy);
	if (phy_id == 0xFFFFFFFF) {
		SYS_LOG_ERR("Unable to detect a valid PHY");
		return -1;
	}

	SYS_LOG_INF("PHYID: 0x%X at addr: %d", phy_id, phy->address);

	mdio_bus_disable(gmac);

	return 0;
}

u32_t phy_sam_gmac_id_get(const struct phy_sam_gmac_dev *phy)
{
	Gmac *const gmac = phy->regs;
	u32_t phy_reg;
	u32_t phy_id;

	mdio_bus_enable(gmac);

	if (phy_read(phy, MII_PHYID1R, &phy_reg) < 0) {
		return 0xFFFFFFFF;
	}

	phy_id = (phy_reg & 0xFFFF) << 16;

	if (phy_read(phy, MII_PHYID2R, &phy_reg) < 0) {
		return 0xFFFFFFFF;
	}

	phy_id |= (phy_reg & 0xFFFF);

	mdio_bus_disable(gmac);

	return phy_id;
}

int phy_sam_gmac_auto_negotiate(const struct phy_sam_gmac_dev *phy,
				u32_t *status)
{
	Gmac *const gmac = phy->regs;
	u32_t val;
	u32_t ability_adv;
	u32_t ability_rcvd;
	u32_t retries = PHY_AUTONEG_TIMEOUT_MS / 100;
	int retval;

	mdio_bus_enable(gmac);

	SYS_LOG_DBG("Starting ETH PHY auto-negotiate sequence");

	/* Read PHY default advertising parameters */
	retval = phy_read(phy, MII_ANAR, &ability_adv);
	if (retval < 0) {
		goto auto_negotiate_exit;
	}

	/* Configure and start auto-negotiation process */
	retval = phy_read(phy, MII_BMCR, &val);
	if (retval < 0) {
		goto auto_negotiate_exit;
	}

	val |= MII_BMCR_AUTONEG_ENABLE | MII_BMCR_AUTONEG_RESTART;
	val &= ~MII_BMCR_ISOLATE;  /* Don't isolate the PHY */

	retval = phy_write(phy, MII_BMCR, val);
	if (retval < 0) {
		goto auto_negotiate_exit;
	}

	/* Wait for the auto-negotiation process to complete */
	do {
		if (retries-- == 0) {
			retval = -ETIMEDOUT;
			goto auto_negotiate_exit;
		}

		k_sleep(100);

		retval = phy_read(phy, MII_BMSR, &val);
		if (retval < 0) {
			goto auto_negotiate_exit;
		}
	} while (!(val & MII_BMSR_AUTONEG_COMPLETE));

	SYS_LOG_DBG("PHY auto-negotiate sequence completed");

	/* Read abilities of the remote device */
	retval = phy_read(phy, MII_ANLPAR, &ability_rcvd);
	if (retval < 0) {
		goto auto_negotiate_exit;
	}

	/* Determine the best possible mode of operation */
	if ((ability_adv & ability_rcvd) & MII_ADVERTISE_100_FULL) {
		*status = PHY_DUPLEX_FULL | PHY_SPEED_100M;
	} else if ((ability_adv & ability_rcvd) & MII_ADVERTISE_100_HALF) {
		*status = PHY_DUPLEX_HALF | PHY_SPEED_100M;
	} else if ((ability_adv & ability_rcvd) & MII_ADVERTISE_10_FULL) {
		*status = PHY_DUPLEX_FULL | PHY_SPEED_10M;
	} else {
		*status = PHY_DUPLEX_HALF | PHY_SPEED_10M;
	}

	SYS_LOG_INF("common abilities: speed %s Mb, %s duplex",
		    *status & PHY_SPEED_100M ? "100" : "10",
		    *status & PHY_DUPLEX_FULL ? "full" : "half");

auto_negotiate_exit:
	mdio_bus_disable(gmac);
	return retval;
}
