Files
target_linux_generic/files/drivers/net/phy/rtl8261n/phy_patch.c
zhao bc08061046
All checks were successful
target_linux_generic / Update target_linux_generic (openwrt-25.12) (push) Successful in 9s
🎁 Sync 2026-02-01 20:01:25
2026-02-01 20:01:25 +00:00

191 lines
5.9 KiB
C

/*
* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
*/
/*
* Include Files
*/
#if defined(RTK_PHYDRV_IN_LINUX)
#include "rtk_osal.h"
#else
#include <common/rt_type.h>
#include <common/rt_error.h>
#include <common/debug/rt_log.h>
#include <hal/common/halctrl.h>
#include <hal/phy/phy_patch.h>
#endif
/*
* Function Declaration
*/
uint8 phy_patch_op_translate(uint8 patch_mode, uint8 patch_op, uint8 compare_op)
{
if (patch_mode != PHY_PATCH_MODE_CMP)
{
return patch_op;
}
else
{
switch (compare_op)
{
case RTK_PATCH_CMP_WS:
return RTK_PATCH_OP_SKIP;
case RTK_PATCH_CMP_W:
case RTK_PATCH_CMP_WC:
case RTK_PATCH_CMP_SWC:
default:
return RTK_PATCH_OP_TO_CMP(patch_op, compare_op);
}
}
}
int32 phy_patch_op(rt_phy_patch_db_t *pPhy_patchDb, uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_op, uint16 portmask, uint16 pagemmd, uint16 addr, uint8 msb, uint8 lsb, uint16 data, uint8 patch_mode)
{
rtk_hwpatch_t op;
op.patch_op = patch_op;
op.portmask = portmask;
op.pagemmd = pagemmd;
op.addr = addr;
op.msb = msb;
op.lsb = lsb;
op.data = data;
op.compare_op = RTK_PATCH_CMP_W;
return pPhy_patchDb->fPatch_op(unit, port, portOffset, &op, patch_mode);
}
static int32 _phy_patch_process(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_hwpatch_t *pPatch, int32 size, uint8 patch_mode)
{
int32 i = 0;
int32 ret = 0;
int32 chk_ret = RT_ERR_OK;
int32 n;
rtk_hwpatch_t *patch = pPatch;
rt_phy_patch_db_t *pPatchDb = NULL;
PHYPATCH_DB_GET(unit, port, pPatchDb);
if (size <= 0)
{
return RT_ERR_OK;
}
n = size / sizeof(rtk_hwpatch_t);
for (i = 0; i < n; i++)
{
ret = pPatchDb->fPatch_op(unit, port, portOffset, &patch[i], patch_mode);
if ((ret != RT_ERR_ABORT) && (ret != RT_ERR_OK))
{
if ((ret == RT_ERR_CHECK_FAILED) && (patch_mode == PHY_PATCH_MODE_CMP))
{
osal_printf("PATCH CHECK: Failed entry:%u|%u|0x%X|0x%X|%u|%u|0x%X\n",
i + 1, patch[i].patch_op, patch[i].pagemmd, patch[i].addr, patch[i].msb, patch[i].lsb, patch[i].data);
chk_ret = RT_ERR_CHECK_FAILED;
continue;
}
else
{
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u %s failed! %u[%u][0x%X][0x%X][0x%X] ret=0x%X\n", unit, port, __FUNCTION__,
i+1, patch[i].patch_op, patch[i].pagemmd, patch[i].addr, patch[i].data, ret);
return ret;
}
}
}
return (chk_ret == RT_ERR_CHECK_FAILED) ? chk_ret : RT_ERR_OK;
}
rtk_hwpatch_t rtl826XB_patch_rtk_conf[] = {
{RTK_PATCH_OP_PSDS0 , 0xff , 0x07 , 0x10 , 15, 0, 0x80aa, RTK_PATCH_CMP_WC , 0, 0, 0, 0},
{RTK_PATCH_OP_PSDS0 , 0xff , 0x06 , 0x12 , 15, 0, 0x5078, RTK_PATCH_CMP_WC , 0, 0, 0, 0},
};
/* Function Name:
* phy_patch
* Description:
* apply initial patch data to PHY
* Input:
* unit - unit id
* port - port id
* portOffset - the index offset of port based the base port in the PHY chip
* Output:
* None
* Return:
* RT_ERR_OK
* RT_ERR_FAILED
* RT_ERR_CHECK_FAILED
* RT_ERR_NOT_SUPPORTED
* Note:
* None
*/
int32 phy_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode)
{
int32 ret = RT_ERR_OK;
int32 chk_ret = RT_ERR_OK;
uint32 i = 0;
uint8 patch_type = 0;
rt_phy_patch_db_t *pPatchDb = NULL;
rtk_hwpatch_seq_t *table = NULL;
PHYPATCH_DB_GET(unit, port, pPatchDb);
if ((pPatchDb == NULL) || (pPatchDb->fPatch_op == NULL) || (pPatchDb->fPatch_flow == NULL))
{
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u phy_patch, db is NULL\n", unit, port);
return RT_ERR_DRIVER_NOT_SUPPORTED;
}
if (patch_mode == PHY_PATCH_MODE_CMP)
{
table = pPatchDb->cmp_table;
}
else
{
table = pPatchDb->seq_table;
}
RT_LOG(LOG_INFO, (MOD_HAL | MOD_PHY), "phy_patch: U%u P%u portOffset:%u patch_mode:%u\n", unit, port, portOffset, patch_mode);
for (i = 0; i < RTK_PATCH_SEQ_MAX; i++)
{
patch_type = table[i].patch_type;
RT_LOG(LOG_INFO, (MOD_HAL | MOD_PHY), "phy_patch: table[%u] patch_type:%u\n", i, patch_type);
if (RTK_PATCH_TYPE_IS_DATA(patch_type))
{
ret = _phy_patch_process(unit, port, portOffset, table[i].patch.data.conf, table[i].patch.data.size, patch_mode);
if (ret == RT_ERR_CHECK_FAILED)
chk_ret = ret;
else if (ret != RT_ERR_OK)
{
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_mode:%u id:%u patch-%u failed. ret:0x%X\n", unit, port, patch_mode, i, patch_type, ret);
return ret;
}
}
else if (RTK_PATCH_TYPE_IS_FLOW(patch_type))
{
RT_ERR_CHK_EHDL(pPatchDb->fPatch_flow(unit, port, portOffset, table[i].patch.flow_id, patch_mode),
ret, RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_mode:%u id:%u patch-%u failed. ret:0x%X\n", unit, port, patch_mode, i, patch_type, ret););
}
else
{
break;
}
}
#ifdef CONFIG_MACH_REALTEK_RTL
ret = _phy_patch_process(unit, port, portOffset, rtl826XB_patch_rtk_conf, sizeof(rtl826XB_patch_rtk_conf), patch_mode);
if (ret == RT_ERR_CHECK_FAILED)
chk_ret = ret;
else if (ret != RT_ERR_OK)
{
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_mode:%u id:%u patch-%u failed. ret:0x%X\n", unit, port, patch_mode, i, patch_type, ret);
return ret;
}
#endif
return (chk_ret == RT_ERR_CHECK_FAILED) ? chk_ret : RT_ERR_OK;
}