#include "lip/phy/lip_phy_cfg_defs.h"
#if LIP_PHY_SUPPORT_RTL8211F
#include "rtl8211f_regs.h"
#include "lip/phy/lip_phy_defs.h"

static t_lip_errs f_spec_cfg(const t_lip_phy_mdio_acc *regs_acc, const t_lip_phy_cfg *cfg);
static t_lip_errs f_get_mode(const t_lip_phy_mdio_acc *regs_acc, t_lip_phy_mode *mode);
static t_lip_errs f_rd_intflags(const t_lip_phy_mdio_acc *regs_acc, uint32_t *intflags);
#if LIP_PHY_USE_STATS
static t_lip_errs f_upd_stats(const t_lip_phy_mdio_acc *regs_acc, const t_lip_phy_state *state, t_lip_phy_stats *stats);
#endif

t_lip_phy_info lip_phy_rtl8211f = {
    .name = "RTL8211F",
    .model_id  = LIP_PHY_MODEL_ID(RTL8211F_ID_VENDOR, RTL8211F_ID_MODEL),
    .an_features = LIP_PHY_AN_FEAT_MODE_10_T_FD | LIP_PHY_AN_FEAT_MODE_10_T_HD
                   | LIP_PHY_AN_FEAT_MODE_100_TX_FD | LIP_PHY_AN_FEAT_MODE_100_TX_HD
                   | LIP_PHY_AN_FEAT_MODE_1000_T_FD
                   | LIP_PHY_AN_FEAT_PAUSE_SYM | LIP_PHY_AN_FEAT_PAUSE_ASYM
                   | LIP_PHY_AN_FEAT_EEE_100_TX | LIP_PHY_AN_FEAT_EEE_1000_T,
    .spec_features = 0,
    .spec_cfg = f_spec_cfg,
    .get_mode = f_get_mode,
    .rd_intflags = f_rd_intflags,
#if LIP_PHY_USE_STATS
    .update_stats =  f_upd_stats,
#endif
};


static t_lip_errs f_spec_cfg(const t_lip_phy_mdio_acc *regs_acc, const t_lip_phy_cfg *cfg) {
    t_lip_errs err = LIP_ERR_SUCCESS;
    uint16_t regval;
    err  = lip_phy_mdio_reg_read(regs_acc, RTL8211F_REGADDR_MIICR1, &regval);
    if (err == LIP_ERR_SUCCESS) {
        /* настройка задержки в соответствии с конфигурацией */
        if (cfg->flags & LIP_PHY_CFG_FLAG_TXCLK_DLY_EN) {
            if (!(regval & RTL8211F_REGFLD_MIICR1_TXDLY_EN)) {
                err = lip_phy_mdio_reg_write(regs_acc, RTL8211F_REGADDR_MIICR1, regval | RTL8211F_REGFLD_MIICR1_TXDLY_EN);
            }
        } else {
            if (!(regval & RTL8211F_REGFLD_MIICR1_TXDLY_EN)) {
                err = lip_phy_mdio_reg_write(regs_acc, RTL8211F_REGADDR_MIICR1, regval & ~RTL8211F_REGFLD_MIICR1_TXDLY_EN);
            }
        }
    }
    return LIP_ERR_SUCCESS;
}

static t_lip_errs f_get_mode(const t_lip_phy_mdio_acc *regs_acc, t_lip_phy_mode *mode) {
    uint16_t stat;
    t_lip_errs err = lip_phy_mdio_reg_read(regs_acc, RTL8211F_REGADDR_PHYSR, &stat);
    mode->flags = 0;
    if (err == LIP_ERR_SUCCESS) {
        uint8_t speed = LBITFIELD_GET(stat, RTL8211F_REGFLD_PHYSR_SPEED);
        if (speed == RTL8211F_REGFLDVAL_PHYSR_SPEED_10) {
            mode->speed = LIP_PHY_SPEED_10;
        } else if (speed == RTL8211F_REGFLDVAL_PHYSR_SPEED_100) {
            mode->speed = LIP_PHY_SPEED_100;
        } else if (speed == RTL8211F_REGFLDVAL_PHYSR_SPEED_1000) {
            mode->speed = LIP_PHY_SPEED_1000;
            if (stat & RTL8211F_REGFLD_PHYSR_MASTER_MODE) {
               mode->flags |= LIP_PHY_MODE_FLAG_MASTER;
            }
        }

        if (stat & RTL8211F_REGFLD_PHYSR_DUPLEX) {
            mode->flags |= LIP_PHY_MODE_FLAG_DUPLEX_FULL;
        }
    }
    return err;
}

static t_lip_errs f_rd_intflags(const t_lip_phy_mdio_acc *regs_acc, uint32_t *intflags) {
    t_lip_errs err = LIP_ERR_SUCCESS;

    return err;
}
#if LIP_PHY_USE_STATS
static t_lip_errs f_upd_stats(const t_lip_phy_mdio_acc *regs_acc, const t_lip_phy_state *state, t_lip_phy_stats *stats) {
    t_lip_errs err = LIP_ERR_SUCCESS;


    return err;
}
#endif
#endif
