mirror of
https://github.com/plappermaul/realtek-doc.git
synced 2026-01-27 15:37:17 +01:00
add missing phy drivers to hal/phy
This commit is contained in:
parent
ff2b2b9623
commit
c8b4dd54e7
31 changed files with 21560 additions and 0 deletions
10
sources/rtk-gp3000/src/hal/phy/Kconfig
Normal file
10
sources/rtk-gp3000/src/hal/phy/Kconfig
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
config RTK_MSSDK_PHY
|
||||||
|
tristate "Realtek MSSDK PHYs"
|
||||||
|
help
|
||||||
|
Currently supports the RTL8261N,RTL8264B PHYs.
|
||||||
|
|
||||||
28
sources/rtk-gp3000/src/hal/phy/Makefile
Normal file
28
sources/rtk-gp3000/src/hal/phy/Makefile
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
ccflags-y := -DRTK_PHYDRV_IN_LINUX
|
||||||
|
#ccflags-y += -DDEBUG
|
||||||
|
|
||||||
|
obj-$(CONFIG_RTK_MSSDK_PHY) += rtk-ms-phy.o
|
||||||
|
|
||||||
|
rtk-ms-phy-objs := rtk_phy.o
|
||||||
|
rtk-ms-phy-objs += rtk_phy_rtl8224.o
|
||||||
|
rtk-ms-phy-objs += rtk_osal.o
|
||||||
|
|
||||||
|
# files from SDK
|
||||||
|
rtk-ms-phy-objs += phy_patch.o
|
||||||
|
rtk-ms-phy-objs += phy_rtl826xb_patch.o
|
||||||
|
rtk-ms-phy-objs += phy_rtl8224_patch.o
|
||||||
|
|
||||||
|
# rtk phylib
|
||||||
|
rtk-ms-phy-objs += rtk_phylib.o
|
||||||
|
rtk-ms-phy-objs += rtk_phylib_rtl826xb.o
|
||||||
|
rtk-ms-phy-objs += rtk_phylib_rtl8224.o
|
||||||
|
|
||||||
|
ifdef CONFIG_MACSEC
|
||||||
|
rtk-ms-phy-objs += rtk_macsec.o
|
||||||
|
rtk-ms-phy-objs += rtk_phylib_macsec.o
|
||||||
|
endif
|
||||||
25
sources/rtk-gp3000/src/hal/phy/README
Normal file
25
sources/rtk-gp3000/src/hal/phy/README
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
the driver is based on linux 5.10.146
|
||||||
|
|
||||||
|
1. Copy the folder "drivers/net/phy/rtk" to your linux in the same path
|
||||||
|
|
||||||
|
2. Modify Kconfig: linux/drivers/net/phy/Kconfig for add menuconfig
|
||||||
|
|
||||||
|
if PHYLIB
|
||||||
|
......
|
||||||
|
source "drivers/net/phy/rtk/Kconfig"
|
||||||
|
endif # PHYLIB
|
||||||
|
|
||||||
|
3. Modify Makefile: linux/drivers/net/phy/Makefile for build code
|
||||||
|
|
||||||
|
obj-$(CONFIG_RTK_MSSDK_PHY) += rtk/
|
||||||
|
|
||||||
|
4. enable kernel config:
|
||||||
|
CONFIG_RTK_MSSDK_PHY=y
|
||||||
|
|
||||||
|
|
||||||
3160
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8224.c
Normal file
3160
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8224.c
Normal file
File diff suppressed because it is too large
Load diff
2803
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8261n_c.c
Normal file
2803
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8261n_c.c
Normal file
File diff suppressed because it is too large
Load diff
2902
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8261n_c_lp.c
Normal file
2902
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8261n_c_lp.c
Normal file
File diff suppressed because it is too large
Load diff
2331
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8264b.c
Normal file
2331
sources/rtk-gp3000/src/hal/phy/construct/conf_rtl8264b.c
Normal file
File diff suppressed because it is too large
Load diff
165
sources/rtk-gp3000/src/hal/phy/error.h
Normal file
165
sources/rtk-gp3000/src/hal/phy/error.h
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMMON_ERROR_H__
|
||||||
|
#define __COMMON_ERROR_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include "type.h"
|
||||||
|
#else
|
||||||
|
#include <common/type.h>
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Data Type Declaration
|
||||||
|
*/
|
||||||
|
typedef enum rt_error_common_e
|
||||||
|
{
|
||||||
|
RT_ERR_FAILED = -1, /* General Error */
|
||||||
|
|
||||||
|
/* 0x0000xxxx for common error code */
|
||||||
|
RT_ERR_OK = 0, /* 0x00000000, OK */
|
||||||
|
RT_ERR_INPUT = 0xF001, /* 0x0000F001, invalid input parameter */
|
||||||
|
RT_ERR_UNIT_ID, /* 0x0000F002, invalid unit id */
|
||||||
|
RT_ERR_PORT_ID, /* 0x0000F003, invalid port id */
|
||||||
|
RT_ERR_PORT_MASK, /* 0x0000F004, invalid port mask */
|
||||||
|
RT_ERR_PORT_LINKDOWN, /* 0x0000F005, link down port status */
|
||||||
|
RT_ERR_ENTRY_INDEX, /* 0x0000F006, invalid entry index */
|
||||||
|
RT_ERR_NULL_POINTER, /* 0x0000F007, input parameter is null pointer */
|
||||||
|
RT_ERR_QUEUE_ID, /* 0x0000F008, invalid queue id */
|
||||||
|
RT_ERR_QUEUE_NUM, /* 0x0000F009, invalid queue number */
|
||||||
|
RT_ERR_BUSYWAIT_TIMEOUT, /* 0x0000F00a, busy watting time out */
|
||||||
|
RT_ERR_MAC, /* 0x0000F00b, invalid mac address */
|
||||||
|
RT_ERR_OUT_OF_RANGE, /* 0x0000F00c, input parameter out of range */
|
||||||
|
RT_ERR_CHIP_NOT_SUPPORTED, /* 0x0000F00d, functions not supported by this chip model */
|
||||||
|
RT_ERR_SMI, /* 0x0000F00e, SMI error */
|
||||||
|
RT_ERR_NOT_INIT, /* 0x0000F00f, The module is not initial */
|
||||||
|
RT_ERR_CHIP_NOT_FOUND, /* 0x0000F010, The chip can not found */
|
||||||
|
RT_ERR_NOT_ALLOWED, /* 0x0000F011, actions not allowed by the function */
|
||||||
|
RT_ERR_DRIVER_NOT_FOUND, /* 0x0000F012, The driver can not found */
|
||||||
|
RT_ERR_SEM_LOCK_FAILED, /* 0x0000F013, Failed to lock semaphore */
|
||||||
|
RT_ERR_SEM_UNLOCK_FAILED, /* 0x0000F014, Failed to unlock semaphore */
|
||||||
|
RT_ERR_THREAD_EXIST, /* 0x0000F015, Thread exist */
|
||||||
|
RT_ERR_THREAD_CREATE_FAILED, /* 0x0000F016, Thread create fail */
|
||||||
|
RT_ERR_FWD_ACTION, /* 0x0000F017, Invalid forwarding Action */
|
||||||
|
RT_ERR_IPV4_ADDRESS, /* 0x0000F018, Invalid IPv4 address */
|
||||||
|
RT_ERR_IPV6_ADDRESS, /* 0x0000F019, Invalid IPv6 address */
|
||||||
|
RT_ERR_PRIORITY, /* 0x0000F01a, Invalid Priority value */
|
||||||
|
RT_ERR_FID, /* 0x0000F01b, invalid fid */
|
||||||
|
RT_ERR_ENTRY_NOTFOUND, /* 0x0000F01c, specified entry not found */
|
||||||
|
RT_ERR_DROP_PRECEDENCE, /* 0x0000F01d, invalid drop precedence */
|
||||||
|
RT_ERR_NOT_FINISH, /* 0x0000F01e, Action not finish, still need to wait */
|
||||||
|
RT_ERR_TIMEOUT, /* 0x0000F01f, Time out */
|
||||||
|
RT_ERR_REG_ARRAY_INDEX_1, /* 0x0000F020, invalid index 1 of register array */
|
||||||
|
RT_ERR_REG_ARRAY_INDEX_2, /* 0x0000F021, invalid index 2 of register array */
|
||||||
|
RT_ERR_ETHER_TYPE, /* 0x0000F022, invalid ether type */
|
||||||
|
RT_ERR_MBUF_PKT_NOT_AVAILABLE, /* 0x0000F023, mbuf->packet is not available */
|
||||||
|
RT_ERR_QOS_INVLD_RSN, /* 0x0000F024, invalid pkt to CPU reason */
|
||||||
|
RT_ERR_CB_FUNCTION_EXIST, /* 0x0000F025, Callback function exist */
|
||||||
|
RT_ERR_CB_FUNCTION_FULL, /* 0x0000F026, Callback function number is full */
|
||||||
|
RT_ERR_CB_FUNCTION_NOT_FOUND, /* 0x0000F027, Callback function can not found */
|
||||||
|
RT_ERR_TBL_FULL, /* 0x0000F028, The table is full */
|
||||||
|
RT_ERR_TRUNK_ID, /* 0x0000F029, invalid trunk id */
|
||||||
|
RT_ERR_TYPE, /* 0x0000F02a, invalid type */
|
||||||
|
RT_ERR_ENTRY_EXIST, /* 0x0000F02b, entry exists */
|
||||||
|
RT_ERR_CHIP_UNDEFINED_VALUE, /* 0x0000F02c, chip returned an undefined value */
|
||||||
|
RT_ERR_EXCEEDS_CAPACITY, /* 0x0000F02d, exceeds the capacity of hardware */
|
||||||
|
RT_ERR_ENTRY_REFERRED, /* 0x0000F02e, entry is still being referred */
|
||||||
|
RT_ERR_OPER_DENIED, /* 0x0000F02f, operation denied */
|
||||||
|
RT_ERR_PORT_NOT_SUPPORTED, /* 0x0000F030, functions not supported by this port */
|
||||||
|
RT_ERR_SOCKET, /* 0x0000F031, socket error */
|
||||||
|
RT_ERR_MEM_ALLOC, /* 0x0000F032, insufficient memory resource */
|
||||||
|
RT_ERR_ABORT, /* 0x0000F033, operation aborted */
|
||||||
|
RT_ERR_DEV_ID, /* 0x0000F034, invalid device id */
|
||||||
|
RT_ERR_DRIVER_NOT_SUPPORTED, /* 0x0000F035, functions not supported by this driver */
|
||||||
|
RT_ERR_NOT_SUPPORTED, /* 0x0000F036, functions not supported */
|
||||||
|
RT_ERR_SER, /* 0x0000F037, ECC or parity error */
|
||||||
|
RT_ERR_MEM_NOT_ALIGN, /* 0x0000F038, memory address is not aligned */
|
||||||
|
RT_ERR_SEM_FAKELOCK_OK, /* 0x0000F039, attach thread lock a semaphore which was already locked */
|
||||||
|
RT_ERR_CHECK_FAILED, /* 0x0000F03a, check result is failed */
|
||||||
|
|
||||||
|
RT_ERR_COMMON_END = 0xFFFF /* The symbol is the latest symbol of common error */
|
||||||
|
} rt_error_common_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro Definition
|
||||||
|
*/
|
||||||
|
#define RT_PARAM_CHK(expr, errCode)\
|
||||||
|
do {\
|
||||||
|
if ((int32)(expr)) {\
|
||||||
|
return errCode; \
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RT_PARAM_CHK_EHDL(expr, errCode, err_hdl)\
|
||||||
|
do {\
|
||||||
|
if ((int32)(expr)) {\
|
||||||
|
{err_hdl}\
|
||||||
|
return errCode; \
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RT_INIT_CHK(state)\
|
||||||
|
do {\
|
||||||
|
if (INIT_COMPLETED != (state)) {\
|
||||||
|
return RT_ERR_NOT_INIT;\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RT_INIT_REENTRY_CHK(state)\
|
||||||
|
do {\
|
||||||
|
if (INIT_COMPLETED == (state)) {\
|
||||||
|
osal_printf(" %s had already been initialized!\n", __FUNCTION__);\
|
||||||
|
return RT_ERR_OK;\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RT_INIT_REENTRY_CHK_NO_WARNING(state)\
|
||||||
|
do {\
|
||||||
|
if (INIT_COMPLETED == (state)) {\
|
||||||
|
return RT_ERR_OK;\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RT_ERR_CHK(op, ret)\
|
||||||
|
do {\
|
||||||
|
if ((ret = (op)) != RT_ERR_OK)\
|
||||||
|
return ret;\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define RT_ERR_HDL(op, errHandle, ret)\
|
||||||
|
do {\
|
||||||
|
if ((ret = (op)) != RT_ERR_OK)\
|
||||||
|
goto errHandle;\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define RT_ERR_CHK_EHDL(op, ret, err_hdl)\
|
||||||
|
do {\
|
||||||
|
if ((ret = (op)) != RT_ERR_OK)\
|
||||||
|
{\
|
||||||
|
{err_hdl}\
|
||||||
|
return ret;\
|
||||||
|
}\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define RT_NULL_HDL(pointer, err_label)\
|
||||||
|
do {\
|
||||||
|
if (NULL == (pointer)) {\
|
||||||
|
goto err_label;\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RT_ERR_VOID_CHK(op, ret)\
|
||||||
|
do {\
|
||||||
|
if ((ret = (op)) != RT_ERR_OK) {\
|
||||||
|
osal_printf("Fail in %s %d, ret %x!\n", __FUNCTION__, __LINE__, ret);\
|
||||||
|
return ;}\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#endif /* __COMMON_ERROR_H__ */
|
||||||
|
|
||||||
179
sources/rtk-gp3000/src/hal/phy/phy_patch.c
Normal file
179
sources/rtk-gp3000/src/hal/phy/phy_patch.c
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (chk_ret == RT_ERR_CHECK_FAILED) ? chk_ret : RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
173
sources/rtk-gp3000/src/hal/phy/phy_patch.h
Normal file
173
sources/rtk-gp3000/src/hal/phy/phy_patch.h
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HAL_PHY_PATCH_H__
|
||||||
|
#define __HAL_PHY_PATCH_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include "rtk_phylib_def.h"
|
||||||
|
#else
|
||||||
|
#include <common/rt_type.h>
|
||||||
|
#include <common/rt_autoconf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbol Definition
|
||||||
|
*/
|
||||||
|
#define PHYPATCH_PHYCTRL_IN_HALCTRL 0 /* 3.6.x: 1 ,4.0.x: 1, 4.1.x+: 0 */
|
||||||
|
#define PHYPATCH_FMAILY_IN_HWP 0 /* 3.6.x: 1 ,4.0.x: 0, 4.1.x+: 0 */
|
||||||
|
#define PHY_PATCH_MODE_BCAST_DEFAULT PHY_PATCH_MODE_BCAST /* 3.6.x: PHY_PATCH_MODE_BCAST_BUS ,4.0.x+: PHY_PATCH_MODE_BCAST */
|
||||||
|
|
||||||
|
#define PHY_PATCH_MODE_NORMAL 0
|
||||||
|
#define PHY_PATCH_MODE_CMP 1
|
||||||
|
#define PHY_PATCH_MODE_BCAST 2
|
||||||
|
#define PHY_PATCH_MODE_BCAST_BUS 3
|
||||||
|
|
||||||
|
#define RTK_PATCH_CMP_W 0 /* write */
|
||||||
|
#define RTK_PATCH_CMP_WC 1 /* compare */
|
||||||
|
#define RTK_PATCH_CMP_SWC 2 /* sram compare */
|
||||||
|
#define RTK_PATCH_CMP_WS 3 /* skip */
|
||||||
|
|
||||||
|
#define RTK_PATCH_OP_SECTION_SIZE 50
|
||||||
|
#define RTK_PATCH_OP_TO_CMP(_op, _cmp) (_op + (RTK_PATCH_OP_SECTION_SIZE * _cmp))
|
||||||
|
/* 0~49 normal op */
|
||||||
|
#define RTK_PATCH_OP_PHY 0
|
||||||
|
#define RTK_PATCH_OP_PHYOCP 1
|
||||||
|
#define RTK_PATCH_OP_TOP 2
|
||||||
|
#define RTK_PATCH_OP_TOPOCP 3
|
||||||
|
#define RTK_PATCH_OP_PSDS0 4
|
||||||
|
#define RTK_PATCH_OP_PSDS1 5
|
||||||
|
#define RTK_PATCH_OP_MSDS 6
|
||||||
|
#define RTK_PATCH_OP_MAC 7
|
||||||
|
|
||||||
|
/* 50~99 normal op for compare */
|
||||||
|
#define RTK_PATCH_OP_CMP_PHY RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHY , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_PHYOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHYOCP , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_TOP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOP , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_TOPOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOPOCP , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_PSDS0 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS0 , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_PSDS1 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS1 , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_MSDS RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MSDS , RTK_PATCH_CMP_WC)
|
||||||
|
#define RTK_PATCH_OP_CMP_MAC RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MAC , RTK_PATCH_CMP_WC)
|
||||||
|
|
||||||
|
/* 100~149 normal op for sram compare */
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_PHY RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHY , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_PHYOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHYOCP , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_TOP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOP , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_TOPOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOPOCP , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_PSDS0 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS0 , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_PSDS1 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS1 , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_MSDS RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MSDS , RTK_PATCH_CMP_SWC)
|
||||||
|
#define RTK_PATCH_OP_CMP_SRAM_MAC RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MAC , RTK_PATCH_CMP_SWC)
|
||||||
|
|
||||||
|
/* 200~255 control op */
|
||||||
|
#define RTK_PATCH_OP_DELAY_MS 200
|
||||||
|
#define RTK_PATCH_OP_SKIP 255
|
||||||
|
|
||||||
|
/*
|
||||||
|
patch type PHY_PATCH_TYPE_NONE => empty
|
||||||
|
patch type: PHY_PATCH_TYPE_TOP ~ (PHY_PATCH_TYPE_END-1) => data array
|
||||||
|
patch type: PHY_PATCH_TYPE_END ~ (PHY_PATCH_TYPE_END + RTK_PATCH_TYPE_FLOW_MAX) => flow
|
||||||
|
*/
|
||||||
|
#define RTK_PATCH_TYPE_IS_DATA(_patch_type) (_patch_type > PHY_PATCH_TYPE_NONE && _patch_type < PHY_PATCH_TYPE_END)
|
||||||
|
#define RTK_PATCH_TYPE_IS_FLOW(_patch_type) (_patch_type >= PHY_PATCH_TYPE_END && _patch_type <= (PHY_PATCH_TYPE_END + RTK_PATCH_TYPE_FLOWID_MAX))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro Definition
|
||||||
|
*/
|
||||||
|
#if PHYPATCH_PHYCTRL_IN_HALCTRL
|
||||||
|
#define PHYPATCH_DB_GET(_unit, _port, _pPatchDb) \
|
||||||
|
do {\
|
||||||
|
hal_control_t *pHalCtrl = NULL;\
|
||||||
|
if ((pHalCtrl = hal_ctrlInfo_get(_unit)) == NULL)\
|
||||||
|
return RT_ERR_FAILED;\
|
||||||
|
_pPatchDb = (pHalCtrl->pPhy_ctrl[_port]->pPhy_patchDb);\
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#else
|
||||||
|
#include <hal/phy/phydef.h>
|
||||||
|
#include <hal/phy/phy_probe.h>
|
||||||
|
#endif
|
||||||
|
#define PHYPATCH_DB_GET(_unit, _port, _pPatchDb) \
|
||||||
|
do {\
|
||||||
|
rt_phyctrl_t *pPhyCtrl = NULL;\
|
||||||
|
if ((pPhyCtrl = phy_phyctrl_get(_unit, _port)) == NULL)\
|
||||||
|
return RT_ERR_FAILED;\
|
||||||
|
_pPatchDb = (pPhyCtrl->pPhy_patchDb);\
|
||||||
|
} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PHYPATCH_FMAILY_IN_HWP
|
||||||
|
#define PHYPATCH_IS_RTKSDS(_unit) (HWP_9300_FAMILY_ID(_unit) || HWP_9310_FAMILY_ID(_unit))
|
||||||
|
#else
|
||||||
|
#define PHYPATCH_IS_RTKSDS(_unit) (RTK_9300_FAMILY_ID(_unit) || RTK_9310_FAMILY_ID(_unit) || RTK_9311B_FAMILY_ID(_unit) || RTK_9330_FAMILY_ID(_unit))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PHYPATCH_TABLE_ASSIGN(_pPatchDb, _table, _idx, _patch_type, _para) \
|
||||||
|
do {\
|
||||||
|
if (RTK_PATCH_TYPE_IS_DATA(_patch_type)) {\
|
||||||
|
_pPatchDb->_table[_idx].patch_type = _patch_type;\
|
||||||
|
_pPatchDb->_table[_idx].patch.data.conf = _para;\
|
||||||
|
_pPatchDb->_table[_idx].patch.data.size = sizeof(_para);\
|
||||||
|
}\
|
||||||
|
else if (RTK_PATCH_TYPE_IS_FLOW(_patch_type)) {\
|
||||||
|
_pPatchDb->_table[_idx].patch_type = _patch_type;\
|
||||||
|
_pPatchDb->_table[_idx].patch.flow_id = _patch_type;\
|
||||||
|
}\
|
||||||
|
else {\
|
||||||
|
_pPatchDb->_table[_idx].patch_type = PHY_PATCH_TYPE_NONE;\
|
||||||
|
}\
|
||||||
|
} while(0)
|
||||||
|
#define PHYPATCH_SEQ_TABLE_ASSIGN(_pPatchDb, _idx, _patch_type, _para) PHYPATCH_TABLE_ASSIGN(_pPatchDb, seq_table, _idx, _patch_type, _para)
|
||||||
|
#define PHYPATCH_CMP_TABLE_ASSIGN(_pPatchDb, _idx, _patch_type, _para) PHYPATCH_TABLE_ASSIGN(_pPatchDb, cmp_table, _idx, _patch_type, _para)
|
||||||
|
|
||||||
|
#define PHYPATCH_COMPARE(_mmdpage, _reg, _msb, _lsb, _exp, _real, _mask) \
|
||||||
|
do {\
|
||||||
|
uint32 _rData = REG32_FIELD_GET(_real, _lsb, _mask);\
|
||||||
|
if (_exp != _rData) {\
|
||||||
|
osal_printf("PATCH CHECK: %u(0x%X).%u(0x%X)[%u:%u] = 0x%X (!= 0x%X)\n", _mmdpage, _mmdpage, _reg, _reg, _msb, _lsb, _rData, _exp);\
|
||||||
|
return RT_ERR_CHECK_FAILED;\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function Declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern uint8 phy_patch_op_translate(uint8 patch_mode, uint8 patch_op, uint8 compare_op);
|
||||||
|
extern 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);
|
||||||
|
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
extern int32 phy_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __HAL_PHY_PATCH_H__ */
|
||||||
641
sources/rtk-gp3000/src/hal/phy/phy_rtl8224_patch.c
Normal file
641
sources/rtk-gp3000/src/hal/phy/phy_rtl8224_patch.c
Normal file
|
|
@ -0,0 +1,641 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2022 Realtek Semiconductor Corp.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is the proprietary software of Realtek Semiconductor
|
||||||
|
* Corporation and/or its licensors, and only be used, duplicated,
|
||||||
|
* modified or distributed under the authorized license from Realtek.
|
||||||
|
*
|
||||||
|
* ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
|
||||||
|
* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||||
|
*
|
||||||
|
* $Revision: $
|
||||||
|
* $Date: $
|
||||||
|
*
|
||||||
|
* Purpose : PHY 8224 HW patch APIs.
|
||||||
|
*
|
||||||
|
* Feature : PHY 8224 HW patch APIs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include "phy_rtl8224_patch.h"
|
||||||
|
#include "construct/conf_rtl8224.c"
|
||||||
|
#include "rtk_phylib_rtl8224.h"
|
||||||
|
#else
|
||||||
|
#include <common/rt_type.h>
|
||||||
|
#include <common/rt_error.h>
|
||||||
|
#include <common/debug/rt_log.h>
|
||||||
|
#include <soc/type.h>
|
||||||
|
#include <hal/common/halctrl.h>
|
||||||
|
#include <hal/mac/miim_common_drv.h>
|
||||||
|
#include <hal/phy/phy_construct.h>
|
||||||
|
#include <osal/time.h>
|
||||||
|
#include <hal/phy/construct/conftypes.h>
|
||||||
|
#if defined(CONFIG_SDK_RTL8224)
|
||||||
|
#include <hal/phy/phy_rtl8224.h>
|
||||||
|
#include <hal/phy/construct/conf_rtl8224.c>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbol Definition
|
||||||
|
*/
|
||||||
|
#define PHY_PATCH_OP_NORMAL 0
|
||||||
|
#define PHY_PATCH_OP_BCAST 1
|
||||||
|
#define PHY_PATCH_OP_BCAST_SAME_CHIP 2
|
||||||
|
#define PHY_PATCH_WAIT_TIMEOUT 10000000
|
||||||
|
|
||||||
|
#define PHY_PATCH_LOG LOG_INFO
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data Declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
rtk_phy_hwpatch_t *patch_fwpr_conf;
|
||||||
|
rtk_phy_hwpatch_t *patch_fwlm_conf;
|
||||||
|
rtk_phy_hwpatch_t *patch_afe_conf;
|
||||||
|
rtk_phy_hwpatch_t *patch_top_conf;
|
||||||
|
rtk_phy_hwpatch_t *patch_sds_conf;
|
||||||
|
int32 patch_fwpr_conf_size;
|
||||||
|
int32 patch_fwlm_conf_size;
|
||||||
|
int32 patch_afe_conf_size;
|
||||||
|
int32 patch_top_conf_size;
|
||||||
|
int32 patch_sds_conf_size;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro Declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function Declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32
|
||||||
|
_phy_rtl8224_patch_mask(uint8 msb, uint8 lsb)
|
||||||
|
{
|
||||||
|
uint32 val = 0;
|
||||||
|
uint8 i = 0;
|
||||||
|
|
||||||
|
for (i = lsb; i <= msb; i++)
|
||||||
|
{
|
||||||
|
val |= (1 << i);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_mask_get(uint8 msb, uint8 lsb, uint32 *mask)
|
||||||
|
{
|
||||||
|
if ((msb > 15) || (lsb > 15) || (msb < lsb))
|
||||||
|
{
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
*mask = _phy_rtl8224_patch_mask(msb, lsb);
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_wait(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data, uint32 mask, uint8 bcast_op)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 cnt = 0;
|
||||||
|
WAIT_COMPLETE_VAR()
|
||||||
|
|
||||||
|
|
||||||
|
WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
++cnt;
|
||||||
|
if ((rData & mask) == data)
|
||||||
|
break;
|
||||||
|
|
||||||
|
osal_time_mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WAIT_COMPLETE_IS_TIMEOUT())
|
||||||
|
{
|
||||||
|
PR_ERR("U%u 8224 patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, mmdAddr, mmdReg, data, mask, rData, cnt);
|
||||||
|
return RT_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_wait_not_equal(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data, uint32 mask, uint8 bcast_op)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 cnt = 0;
|
||||||
|
WAIT_COMPLETE_VAR()
|
||||||
|
|
||||||
|
WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
++cnt;
|
||||||
|
if ((rData & mask) != data)
|
||||||
|
break;
|
||||||
|
|
||||||
|
osal_time_mdelay(1);
|
||||||
|
}
|
||||||
|
if(WAIT_COMPLETE_IS_TIMEOUT())
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 8224 patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, port, mmdAddr, mmdReg, data, mask, rData, cnt);
|
||||||
|
return RT_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_top_get(uint32 unit, rtk_port_t port, uint32 topPage, uint32 topReg, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 rData = 0;
|
||||||
|
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, topReg, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
*pData = rData;
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_top_set(uint32 unit, rtk_port_t port, uint32 topPage, uint32 topReg, uint32 wData)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, topReg, wData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_sds_get(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 sdsAddr = (0x1 << 15) | (0x0 << 14) | (sdsReg << 7) | (sdsPage << 1);
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_top_set(unit, port, 0, 0x3F8, sdsAddr)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_top_get(unit, port, 0, 0x3FC, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
*pData = rData;
|
||||||
|
|
||||||
|
return _phy_rtl8224_patch_wait(unit, port, PHY_MMD_VEND1, 0x3F8, 0, BIT_15, PHY_PATCH_OP_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_sds_set(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 wData, uint8 bcast)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 sdsAddr = (0x1 << 15) | (0x1 << 14) | (sdsReg << 7) | (sdsPage << 1);
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_top_set(unit, port, 0, 0x400, wData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_rtl8224_patch_top_set(unit, port, 0, 0x3F8, sdsAddr)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return _phy_rtl8224_patch_wait(unit, port, PHY_MMD_VEND1, 0x3F8, 0, BIT_15, bcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_rtl8224_patch_process_op(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_phy_hwpatch_t *op, uint8 bcast)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 mask = 0;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 wData = 0;
|
||||||
|
|
||||||
|
if ((op->portmask & (1 << portOffset)) == 0)
|
||||||
|
{
|
||||||
|
return RT_ERR_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _phy_rtl8224_patch_mask_get(op->msb, op->lsb, &mask);
|
||||||
|
|
||||||
|
if (ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
switch (op->patch_op)
|
||||||
|
{
|
||||||
|
case RTK_HWPATCH_OP_PHY:
|
||||||
|
if ((op->msb != 15) || (op->lsb != 0))
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, op->addr, &rData)) != RT_ERR_OK)
|
||||||
|
{
|
||||||
|
PR_ERR("\n[port = %d] addr = 0x%08x ERROR!!!!!\n",port->mdio.addr, op->addr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask);
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, op->addr, wData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTK_HWPATCH_OP_MMD:
|
||||||
|
if ((op->msb != 15) || (op->lsb != 0))
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, op->addr, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask);
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, op->addr, wData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTK_HWPATCH_OP_TOP:
|
||||||
|
if ((op->msb != 15) || (op->lsb != 0))
|
||||||
|
{
|
||||||
|
if ((ret = _phy_rtl8224_patch_top_get(unit, port, PHY_MMD_VEND1, op->addr, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask);
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_top_set(unit, port, PHY_MMD_VEND1, op->addr, wData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTK_HWPATCH_OP_SDS:
|
||||||
|
if ((op->msb != 15) || (op->lsb != 0))
|
||||||
|
{
|
||||||
|
if ((ret = _phy_rtl8224_patch_sds_get(unit, port, op->pagemmd, op->addr, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask);
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_sds_set(unit, port, op->pagemmd, op->addr, wData, bcast)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTK_HWPATCH_OP_PHYW:
|
||||||
|
case RTK_HWPATCH_OP_ALGO:
|
||||||
|
case RTK_HWPATCH_OP_DATARAM:
|
||||||
|
case RTK_HWPATCH_OP_UNKNOWN:
|
||||||
|
default:
|
||||||
|
return RT_ERR_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_rtl8224_patch_op(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_op, uint8 portmask, uint16 pagemmd, uint16 addr, uint8 msb, uint8 lsb, uint16 data)
|
||||||
|
{
|
||||||
|
rtk_phy_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;
|
||||||
|
|
||||||
|
return phy_rtl8224_patch_process_op(unit, port, portOffset, &op, PHY_PATCH_OP_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_process(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_phy_hwpatch_t *pPatch, int32 size, uint32 *cnt, uint8 bcast)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
int32 i = 0;
|
||||||
|
int32 n = 0;
|
||||||
|
rtk_phy_hwpatch_t *patch = pPatch;
|
||||||
|
|
||||||
|
if (size <= 0)
|
||||||
|
{
|
||||||
|
*cnt = 0;
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
n = size/sizeof(rtk_phy_hwpatch_t);
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
ret = phy_rtl8224_patch_process_op(unit, port, portOffset, &patch[i], bcast);
|
||||||
|
if ((ret != RT_ERR_ABORT) && (ret != RT_ERR_OK))
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u %s failed! i=%u ret=0x%X\n", unit, port, __FUNCTION__, i, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*cnt = i;
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_assign(uint32 unit, rtk_port_t port, uint32 chipVer)
|
||||||
|
{
|
||||||
|
if(chipVer == PHY_RTL8224_VER_A)
|
||||||
|
{
|
||||||
|
patch_fwpr_conf = rtl8224_a_patch_fwpr_conf;
|
||||||
|
patch_fwlm_conf = rtl8224_a_patch_fwlm_conf;
|
||||||
|
patch_afe_conf = rtl8224_a_patch_afe_conf;
|
||||||
|
patch_top_conf = rtl8224_a_patch_top_conf;
|
||||||
|
patch_sds_conf = rtl8224_a_patch_sds_conf;
|
||||||
|
patch_fwpr_conf_size = sizeof(rtl8224_a_patch_fwpr_conf);
|
||||||
|
patch_fwlm_conf_size= sizeof(rtl8224_a_patch_fwlm_conf);
|
||||||
|
patch_afe_conf_size= sizeof(rtl8224_a_patch_afe_conf);
|
||||||
|
patch_top_conf_size= sizeof(rtl8224_a_patch_top_conf);
|
||||||
|
patch_sds_conf_size= sizeof(rtl8224_a_patch_sds_conf);
|
||||||
|
}
|
||||||
|
else if(chipVer == PHY_RTL8224_VER_B)
|
||||||
|
{
|
||||||
|
patch_fwpr_conf = rtl8224_b_patch_fwpr_conf;
|
||||||
|
patch_fwlm_conf = rtl8224_b_patch_fwlm_conf;
|
||||||
|
patch_afe_conf = rtl8224_b_patch_afe_conf;
|
||||||
|
patch_top_conf = rtl8224_b_patch_top_conf;
|
||||||
|
patch_sds_conf = rtl8224_b_patch_sds_conf;
|
||||||
|
patch_fwpr_conf_size = sizeof(rtl8224_b_patch_fwpr_conf);
|
||||||
|
patch_fwlm_conf_size= sizeof(rtl8224_b_patch_fwlm_conf);
|
||||||
|
patch_afe_conf_size= sizeof(rtl8224_b_patch_afe_conf);
|
||||||
|
patch_top_conf_size= sizeof(rtl8224_b_patch_top_conf);
|
||||||
|
patch_sds_conf_size= sizeof(rtl8224_b_patch_sds_conf);
|
||||||
|
}else{
|
||||||
|
patch_fwpr_conf = rtl8224_patch_fwpr_conf;
|
||||||
|
patch_fwlm_conf = rtl8224_patch_fwlm_conf;
|
||||||
|
patch_afe_conf = rtl8224_patch_afe_conf;
|
||||||
|
patch_top_conf = rtl8224_patch_top_conf;
|
||||||
|
patch_sds_conf = rtl8224_patch_sds_conf;
|
||||||
|
patch_fwpr_conf_size = sizeof(rtl8224_patch_fwpr_conf);
|
||||||
|
patch_fwlm_conf_size= sizeof(rtl8224_patch_fwlm_conf);
|
||||||
|
patch_afe_conf_size= sizeof(rtl8224_patch_afe_conf);
|
||||||
|
patch_top_conf_size= sizeof(rtl8224_patch_top_conf);
|
||||||
|
patch_sds_conf_size= sizeof(rtl8224_patch_sds_conf);
|
||||||
|
}
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch_version_assign(uint32 unit, rtk_port_t port, uint8 portOffset, uint32 chipVer)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
//writephy_ocp $phynum 0xA438 $currentVersion
|
||||||
|
if((chipVer == PHY_RTL8224_VER_A) || (chipVer == PHY_RTL8224_VER_B))
|
||||||
|
{
|
||||||
|
ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA438, 15, 0, RTL8224_AB_FW_VER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA438, 15, 0, RTL8224_FW_VER);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_rtl8224_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 bcast)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 cnt = 0;
|
||||||
|
uint32 chipVer = 5;
|
||||||
|
|
||||||
|
phy_8224_chipVer_get(unit, port, &chipVer);
|
||||||
|
|
||||||
|
_phy_rtl8224_patch_assign(unit, port, chipVer);
|
||||||
|
|
||||||
|
//Patch Request
|
||||||
|
//PP_PHYReg w $PHYID 0xB820 bit.4 0x1 patch request
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xb820, 4, 4, 0x1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
//PP_PHYReg_bit r $PHYID 0xB800 6 6 wait 1
|
||||||
|
if ((ret = _phy_rtl8224_patch_wait(unit, port, PHY_MMD_VEND2, 0xB800, BIT_6, BIT_6, bcast)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_process(unit, port, portOffset, patch_fwpr_conf, patch_fwpr_conf_size, &cnt, bcast))!= RT_ERR_OK)
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 8224 fwpr patch failed. ret:0x%X\n", unit, port, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
RT_LOG(PHY_PATCH_LOG, (MOD_HAL | MOD_PHY), "U%u P%u 8224 fwpr patch done. ret:0x%X cnt:%d\n", unit, port, ret, cnt);
|
||||||
|
|
||||||
|
//PP_PHYReg w $PHYID 0xB820 0x0000
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xb820, 4, 4, 0x0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//PP_PHYReg_bit r $PHYID 0xB800 6 6 wait 0 (Release patch request & wait patch_rdy = 0)
|
||||||
|
if ((ret = _phy_rtl8224_patch_wait(unit, port, PHY_MMD_VEND2, 0xB800, 0, BIT_6, bcast)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//Lock Main
|
||||||
|
//writephybits_ocp $phynum 0xa4a0 10 10 0x1
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA4A0, 10, 10, 0x1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
//[PP_PHYReg_bit r $PHYID 0xa600 7 0]
|
||||||
|
if ((ret = _phy_rtl8224_patch_wait(unit, port, PHY_MMD_VEND2, 0xa600, 0x1, 0xFF, bcast)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_process(unit, port, portOffset, patch_fwlm_conf, patch_fwlm_conf_size, &cnt, bcast))!= RT_ERR_OK)
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 8224 fwlm patch failed. ret:0x%X\n", unit, port, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
RT_LOG(PHY_PATCH_LOG, (MOD_HAL | MOD_PHY), "U%u P%u 8224 fwlm patch done. ret:0x%X cnt:%d\n", unit, port, ret, cnt);
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_process(unit, port, portOffset, patch_afe_conf, patch_afe_conf_size, &cnt, bcast)) != RT_ERR_OK)
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 8224 afe patch failed. ret:0x%X\n", unit, port, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
RT_LOG(PHY_PATCH_LOG, (MOD_HAL | MOD_PHY), "U%u P%u 8224 afe patch done. ret:0x%X cnt:%d\n", unit, port, ret, cnt);
|
||||||
|
|
||||||
|
//Patch PHY
|
||||||
|
if(chipVer == PHY_RTL8224_VER_A){
|
||||||
|
//writephy_ocp $phynum 0xa5d0 0x0
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xa5d0, 15, 0, 0x0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//writephybits_ocp $phynum 0xa430 2 0 0x0
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xa430, 2, 0, 0x0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//writephy_ocp $phynum 0xa47E 7 6 0x1
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xa47E, 7, 6, 0x1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//Release Lock Main
|
||||||
|
//writephybits_ocp $phynum 0xa4a0 10 10 0x0
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA4A0, 10, 10, 0x0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//[PP_PHYReg_bit r $PHYID 0xa600 7 0]
|
||||||
|
if ((ret = _phy_rtl8224_patch_wait_not_equal(unit, port, PHY_MMD_VEND2, 0xa600, 0x1, 0xFF, bcast)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_process(unit, port, portOffset, patch_top_conf, patch_top_conf_size, &cnt, bcast))!= RT_ERR_OK)
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 8224 top patch failed. ret:0x%X\n", unit, port, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
RT_LOG(PHY_PATCH_LOG, (MOD_HAL | MOD_PHY), "U%u P%u 8224 top patch done. ret:0x%X cnt:%d\n", unit, port, ret, cnt);
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch_process(unit, port, portOffset, patch_sds_conf, patch_sds_conf_size, &cnt, bcast))!= RT_ERR_OK)
|
||||||
|
{
|
||||||
|
RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 8224 sds patch failed. ret:0x%X\n", unit, port, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
RT_LOG(PHY_PATCH_LOG, (MOD_HAL | MOD_PHY), "U%u P%u 8224 sds patch done. ret:0x%X cnt:%d\n", unit, port, ret, cnt);
|
||||||
|
|
||||||
|
//writephy_ocp $phynum 0xA436 0x801E
|
||||||
|
if ((ret = phy_rtl8224_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA436, 15, 0, 0x801E)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = _phy_rtl8224_patch_version_assign(unit, port, portOffset, chipVer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_sdsReg_get
|
||||||
|
* Description:
|
||||||
|
* Get SerDes Register
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* sdsPage - the SerDes page
|
||||||
|
* sdsReg - the SerDes register
|
||||||
|
* Output:
|
||||||
|
* pData - return register value
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
int32
|
||||||
|
phy_rtl8224_sdsReg_get(uint32 unit, rtk_port_t baseport, uint32 sdsPage, uint32 sdsReg, uint32 *pData)
|
||||||
|
{
|
||||||
|
_phy_rtl8224_patch_sds_get(unit, baseport, sdsPage, sdsReg, pData);
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_sdsReg_set
|
||||||
|
* Description:
|
||||||
|
* Set SerDes Register
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* sdsPage - the SerDes page
|
||||||
|
* sdsReg - the SerDes register
|
||||||
|
* wData - the write data
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_rtl8224_sdsReg_set(uint32 unit, rtk_port_t baseport, uint32 sdsPage, uint32 sdsReg, uint32 wData)
|
||||||
|
{
|
||||||
|
return _phy_rtl8224_patch_sds_set(unit, baseport, sdsPage, sdsReg, wData, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_patch
|
||||||
|
* Description:
|
||||||
|
* Apply initial patch data to PHY
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* portOffset - the index offset base on baseport for the port to patch
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
int32
|
||||||
|
phy_rtl8224_patch(uint32 unit, rtk_port_t port, uint8 portOffset)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData = 0;
|
||||||
|
|
||||||
|
if ((ret = _phy_rtl8224_patch(unit, port, portOffset, PHY_PATCH_OP_NORMAL)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*Disable 100M/1G EEE advertise ability */
|
||||||
|
phyData = 0;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xa5d0, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*Disable 1G lite ability */
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xa428, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
phyData &= ~(BIT_9);
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xa428, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (PHYPATCH_IS_RTKSDS(unit))
|
||||||
|
{
|
||||||
|
PR_INFO("\nDisable SerDes AN with Realtek switch");
|
||||||
|
/* Disable USXGMII AN */
|
||||||
|
if ((ret = phy_8224_sdsReg_get(unit, port, 7, 17, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
phyData &= ~(uint32)(0xf);
|
||||||
|
if ((ret = phy_8224_sdsReg_set(unit, port, 7, 17, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PHYPATCH_IS_RTKSDS(unit))
|
||||||
|
{
|
||||||
|
if ((ret = phy_8224_sdsOpCode_set(unit, port, 0x3)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_8224_sdsAmPeriod_set(unit, port, 0xa4)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PR_INFO("\nConnect to Realtek switch");
|
||||||
|
if ((ret = phy_8224_sdsOpCode_set(unit, port, 0xaa)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_8224_sdsAmPeriod_set(unit, port, 0x5078)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_8224_sdsAllAm_set(unit, port, 0x0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_8224_sdsExtra_set(unit, port)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
128
sources/rtk-gp3000/src/hal/phy/phy_rtl8224_patch.h
Normal file
128
sources/rtk-gp3000/src/hal/phy/phy_rtl8224_patch.h
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2022 Realtek Semiconductor Corp.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is the proprietary software of Realtek Semiconductor
|
||||||
|
* Corporation and/or its licensors, and only be used, duplicated,
|
||||||
|
* modified or distributed under the authorized license from Realtek.
|
||||||
|
*
|
||||||
|
* ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
|
||||||
|
* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||||
|
*
|
||||||
|
* $Revision: $
|
||||||
|
* $Date: $
|
||||||
|
*
|
||||||
|
* Purpose : PHY 8224 HW patch APIs.
|
||||||
|
*
|
||||||
|
* Feature : PHY 8224 HW patch APIs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __HAL_PHY_PHY_RTL8224_PATCH_H__
|
||||||
|
#define __HAL_PHY_PHY_RTL8224_PATCH_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include "rtk_osal.h"
|
||||||
|
#include "rtk_phylib_def.h"
|
||||||
|
#else
|
||||||
|
#include <common/rt_type.h>
|
||||||
|
#include <rtk/port.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_sdsReg_get
|
||||||
|
* Description:
|
||||||
|
* Get SerDes Register
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* sdsPage - the SerDes page
|
||||||
|
* sdsReg - the SerDes register
|
||||||
|
* Output:
|
||||||
|
* pData - return register value
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
extern int32
|
||||||
|
phy_rtl8224_sdsReg_get(uint32 unit, rtk_port_t baseport, uint32 sdsPage, uint32 sdsReg, uint32 *pData);
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_sdsReg_set
|
||||||
|
* Description:
|
||||||
|
* Set SerDes Register
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* sdsPage - the SerDes page
|
||||||
|
* sdsReg - the SerDes register
|
||||||
|
* wData - the write data
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int32
|
||||||
|
phy_rtl8224_sdsReg_set(uint32 unit, rtk_port_t baseport, uint32 sdsPage, uint32 sdsReg, uint32 wData);
|
||||||
|
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_patch
|
||||||
|
* Description:
|
||||||
|
* Apply patch data to PHY
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* portOffset - the index offset base on baseport for the port to patch
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
extern int32
|
||||||
|
phy_rtl8224_patch(uint32 unit, rtk_port_t baseport, uint8 portOffset);
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl8224_broadcast_patch
|
||||||
|
* Description:
|
||||||
|
* Apply patch data to PHY
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* portOffset - the index offset base on baseport for the port to patch
|
||||||
|
* perChip - 1 for per-chip mode, 0 for per-bus mode
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
extern int32
|
||||||
|
phy_rtl8224_broadcast_patch(uint32 unit, uint8 port, uint8 portOffset, uint8 perChip);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __HAL_PHY_PHY_RTL8224_PATCH_H__ */
|
||||||
|
|
||||||
1122
sources/rtk-gp3000/src/hal/phy/phy_rtl826xb_patch.c
Normal file
1122
sources/rtk-gp3000/src/hal/phy/phy_rtl826xb_patch.c
Normal file
File diff suppressed because it is too large
Load diff
63
sources/rtk-gp3000/src/hal/phy/phy_rtl826xb_patch.h
Normal file
63
sources/rtk-gp3000/src/hal/phy/phy_rtl826xb_patch.h
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HAL_PHY_PHY_RTL826XB_PATCH_H__
|
||||||
|
#define __HAL_PHY_PHY_RTL826XB_PATCH_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include "rtk_osal.h"
|
||||||
|
#include "rtk_phylib_def.h"
|
||||||
|
#else
|
||||||
|
#include <common/rt_type.h>
|
||||||
|
#include <rtk/port.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl826xb_patch
|
||||||
|
* Description:
|
||||||
|
* apply patch data to PHY
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* portOffset - the index offset base on baseport for the port to patch
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
extern int32 phy_rtl826xb_patch(uint32 unit, rtk_port_t baseport, uint8 portOffset);
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_rtl826xb_broadcast_patch
|
||||||
|
* Description:
|
||||||
|
* apply patch data to PHY
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* baseport - base port id on the PHY chip
|
||||||
|
* portOffset - the index offset base on baseport for the port to patch
|
||||||
|
* perChip - 1 for per-chip mode, 0 for per-bus mode
|
||||||
|
* Output:
|
||||||
|
* None
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK
|
||||||
|
* RT_ERR_FAILED
|
||||||
|
* RT_ERR_NOT_SUPPORTED
|
||||||
|
* RT_ERR_ABORT
|
||||||
|
* Note:
|
||||||
|
* None
|
||||||
|
*/
|
||||||
|
extern int32 phy_rtl826xb_broadcast_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 perChip);
|
||||||
|
|
||||||
|
extern int32 phy_rtl826xb_patch_db_init(uint32 unit, rtk_port_t port, rt_phy_patch_db_t **pPhy_patchDb);
|
||||||
|
#endif /* __HAL_PHY_PHY_RTL826XB_PATCH_H__ */
|
||||||
885
sources/rtk-gp3000/src/hal/phy/rtk_macsec.c
Normal file
885
sources/rtk-gp3000/src/hal/phy/rtk_macsec.c
Normal file
|
|
@ -0,0 +1,885 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <crypto/aes.h>
|
||||||
|
#include <net/macsec.h>
|
||||||
|
#include "rtk_phylib_macsec.h"
|
||||||
|
#include "rtk_phylib_rtl826xb.h"
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
#include "rtk_phy.h"
|
||||||
|
|
||||||
|
static int rtk_macsec_del_txsa(struct macsec_context *ctx);
|
||||||
|
static int rtk_macsec_del_rxsa(struct macsec_context *ctx);
|
||||||
|
|
||||||
|
static int __rtk_macsec_clear_txsc(struct macsec_context *ctx, uint32 sc_id)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_del(ctx->phydev, RTK_MACSEC_DIR_EGRESS, sc_id));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __rtk_macsec_clear_rxsc(struct macsec_context *ctx, uint32 sc_id)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_del(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_dev_open(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rtk_phylib_macsec_enable_set(ctx->phydev, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_dev_stop(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rtk_phylib_macsec_enable_set(ctx->phydev, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_add_secy(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(MACSEC_SC_IS_USED(macsec_db, RTK_MACSEC_DIR_EGRESS, 0))
|
||||||
|
{
|
||||||
|
PR_ERR("[%s]MACSEC_SC_IS_USED\n",__FUNCTION__);
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create TX SC */
|
||||||
|
{
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sc_t sc;
|
||||||
|
memset(&sc, 0x0, sizeof(rtk_macsec_sc_t));
|
||||||
|
|
||||||
|
switch (ctx->secy->key_len)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
sc.tx.cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_128 : RTK_MACSEC_CIPHER_GCM_ASE_128;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
sc.tx.cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_256 : RTK_MACSEC_CIPHER_GCM_ASE_256;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("Not support key_len %d\n", ctx->secy->key_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTK_PHYLIB_VAL_TO_BYTE_ARRAY(ctx->secy->sci, 8, sc.tx.sci, 0, 8);
|
||||||
|
PR_DBG("[%s]secy->sci: 0x%llX\n", __FUNCTION__, ctx->secy->sci);
|
||||||
|
sc.tx.flow_match = RTK_MACSEC_MATCH_NON_CTRL;
|
||||||
|
sc.tx.protect_frame = ctx->secy->protect_frames;
|
||||||
|
sc.tx.include_sci = ctx->secy->tx_sc.send_sci;
|
||||||
|
sc.tx.use_es = ctx->secy->tx_sc.end_station;
|
||||||
|
sc.tx.use_scb = ctx->secy->tx_sc.scb;
|
||||||
|
sc.tx.conf_protect = ctx->secy->tx_sc.encrypt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_create(ctx->phydev, RTK_MACSEC_DIR_EGRESS, &sc, &sc_id, (ctx->secy->tx_sc.active) ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_del_secy(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
uint32 i = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < MACSEC_SC_MAX(macsec_db); i++)
|
||||||
|
{
|
||||||
|
if(MACSEC_SC_IS_USED(macsec_db, RTK_MACSEC_DIR_EGRESS, i))
|
||||||
|
{
|
||||||
|
PR_DBG("[%s] clear TX SC %u\n", __FUNCTION__, i);
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_clear_txsc(ctx, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MACSEC_SC_IS_USED(macsec_db, RTK_MACSEC_DIR_INGRESS, i))
|
||||||
|
{
|
||||||
|
PR_DBG("[%s] clear RX SC %u\n", __FUNCTION__, i);
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_clear_rxsc(ctx, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(&(macsec_db->port_stats), 0x0, sizeof(rtk_macsec_sc_t));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_upd_secy(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
|
||||||
|
rtk_macsec_cipher_t cipher_suite;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(MACSEC_SC_IS_CLEAR(macsec_db, RTK_MACSEC_DIR_EGRESS, 0))
|
||||||
|
{
|
||||||
|
PR_ERR("[%s]MACSEC_SC_IS_CLEAR\n",__FUNCTION__);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create TX SC */
|
||||||
|
{
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sc_t sc;
|
||||||
|
rtk_macsec_sc_t cur_sc;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_get(ctx->phydev, RTK_MACSEC_DIR_EGRESS, 0, &sc));
|
||||||
|
memcpy(&cur_sc, &sc, sizeof(rtk_macsec_sc_t));
|
||||||
|
|
||||||
|
switch (ctx->secy->key_len)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_128 : RTK_MACSEC_CIPHER_GCM_ASE_128;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_256 : RTK_MACSEC_CIPHER_GCM_ASE_256;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("Not support key_len %d\n", ctx->secy->key_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTK_PHYLIB_VAL_TO_BYTE_ARRAY(ctx->secy->sci, 8, sc.tx.sci, 0, 8);
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
PR_DBG("[%s]secy->sci: 0x%llX\n", __FUNCTION__, ctx->secy->sci);
|
||||||
|
PR_DBG("cipher_suite %u => %u\n", sc.tx.cipher_suite, cipher_suite);
|
||||||
|
PR_DBG("flow_match %u => %u\n", sc.tx.flow_match, RTK_MACSEC_MATCH_NON_CTRL);
|
||||||
|
PR_DBG("protect_frame %u => %u\n", sc.tx.protect_frame, ctx->secy->protect_frames);
|
||||||
|
PR_DBG("include_sci %u => %u\n", sc.tx.include_sci, ctx->secy->tx_sc.send_sci);
|
||||||
|
PR_DBG("use_es %u => %u\n", sc.tx.use_es, ctx->secy->tx_sc.end_station);
|
||||||
|
PR_DBG("use_scb %u => %u\n", sc.tx.use_scb, ctx->secy->tx_sc.scb);
|
||||||
|
PR_DBG("conf_protect %u => %u\n", sc.tx.conf_protect, ctx->secy->tx_sc.encrypt);
|
||||||
|
#endif
|
||||||
|
sc.tx.cipher_suite = cipher_suite;
|
||||||
|
sc.tx.flow_match = RTK_MACSEC_MATCH_NON_CTRL;
|
||||||
|
sc.tx.protect_frame = ctx->secy->protect_frames;
|
||||||
|
sc.tx.include_sci = ctx->secy->tx_sc.send_sci;
|
||||||
|
sc.tx.use_es = ctx->secy->tx_sc.end_station;
|
||||||
|
sc.tx.use_scb = ctx->secy->tx_sc.scb;
|
||||||
|
sc.tx.conf_protect = ctx->secy->tx_sc.encrypt;
|
||||||
|
|
||||||
|
if(memcmp(&cur_sc, &sc, sizeof(rtk_macsec_sc_t)) != 0)
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_update(ctx->phydev, RTK_MACSEC_DIR_EGRESS, &sc, &sc_id, (ctx->secy->tx_sc.active) ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_add_rxsc(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sc_t sc;
|
||||||
|
memset(&sc, 0x0, sizeof(rtk_macsec_sc_t));
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->rx_sc->sci, &sc_id);
|
||||||
|
if(ret != RTK_PHYLIB_ERR_ENTRY_NOTFOUND) //sc is existed
|
||||||
|
{
|
||||||
|
PR_DBG("[%s] ret:%d sc_id:%d is existed \n", __FUNCTION__, ret, sc_id);
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
PR_DBG("[%s]rx_sc->sci: 0x%llX\n", __FUNCTION__, ctx->rx_sc->sci);
|
||||||
|
|
||||||
|
switch (ctx->secy->key_len)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
sc.rx.cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_128 : RTK_MACSEC_CIPHER_GCM_ASE_128;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
sc.rx.cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_256 : RTK_MACSEC_CIPHER_GCM_ASE_256;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("Not support key_len %d\n", ctx->secy->key_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PR_DBG("[%s]rx_sc->sci: 0x%llX\n", __FUNCTION__, ctx->rx_sc->sci);
|
||||||
|
RTK_PHYLIB_VAL_TO_BYTE_ARRAY(ctx->rx_sc->sci, 8, sc.rx.sci, 0, 8);
|
||||||
|
sc.rx.flow_match = RTK_MACSEC_MATCH_SCI;
|
||||||
|
|
||||||
|
switch (ctx->secy->validate_frames)
|
||||||
|
{
|
||||||
|
case MACSEC_VALIDATE_DISABLED:
|
||||||
|
sc.rx.validate_frames = RTK_MACSEC_VALIDATE_DISABLE;
|
||||||
|
break;
|
||||||
|
case MACSEC_VALIDATE_CHECK:
|
||||||
|
sc.rx.validate_frames = RTK_MACSEC_VALIDATE_CHECK;
|
||||||
|
break;
|
||||||
|
case MACSEC_VALIDATE_STRICT:
|
||||||
|
sc.rx.validate_frames = RTK_MACSEC_VALIDATE_STRICT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("Not support validate_frames %d\n", ctx->secy->validate_frames);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.rx.replay_protect = ctx->secy->replay_protect;
|
||||||
|
sc.rx.replay_window = ctx->secy->replay_window;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_create(ctx->phydev, RTK_MACSEC_DIR_INGRESS, &sc, &sc_id, (ctx->rx_sc->active) ? 1 : 0));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_del_rxsc(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->rx_sc->sci, &sc_id));
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_clear_rxsc(ctx, sc_id));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_upd_rxsc(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sc_t sc;
|
||||||
|
rtk_macsec_sc_t cur_sc;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->rx_sc->sci, &sc_id);
|
||||||
|
if(ret == RTK_PHYLIB_ERR_ENTRY_NOTFOUND) //sc is not existed
|
||||||
|
{
|
||||||
|
PR_DBG("[%s] ret:%d sc_id:%d is not existed \n", __FUNCTION__, ret, sc_id);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
PR_DBG("[%s]rx_sc->sci: 0x%llX\n", __FUNCTION__, ctx->rx_sc->sci);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_get(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id, &sc));
|
||||||
|
memcpy(&cur_sc, &sc, sizeof(rtk_macsec_sc_t));
|
||||||
|
|
||||||
|
switch (ctx->secy->key_len)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
sc.rx.cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_128 : RTK_MACSEC_CIPHER_GCM_ASE_128;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
sc.rx.cipher_suite = (ctx->secy->xpn) ? RTK_MACSEC_CIPHER_GCM_ASE_XPN_256 : RTK_MACSEC_CIPHER_GCM_ASE_256;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("Not support key_len %d\n", ctx->secy->key_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PR_DBG("[%s]rx_sc->sci: 0x%llX\n", __FUNCTION__, ctx->rx_sc->sci);
|
||||||
|
RTK_PHYLIB_VAL_TO_BYTE_ARRAY(ctx->rx_sc->sci, 8, sc.rx.sci, 0, 8);
|
||||||
|
sc.rx.flow_match = RTK_MACSEC_MATCH_SCI;
|
||||||
|
|
||||||
|
switch (ctx->secy->validate_frames)
|
||||||
|
{
|
||||||
|
case MACSEC_VALIDATE_DISABLED:
|
||||||
|
sc.rx.validate_frames = RTK_MACSEC_VALIDATE_DISABLE;
|
||||||
|
break;
|
||||||
|
case MACSEC_VALIDATE_CHECK:
|
||||||
|
sc.rx.validate_frames = RTK_MACSEC_VALIDATE_CHECK;
|
||||||
|
break;
|
||||||
|
case MACSEC_VALIDATE_STRICT:
|
||||||
|
sc.rx.validate_frames = RTK_MACSEC_VALIDATE_STRICT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("Not support validate_frames %d\n", ctx->secy->validate_frames);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.rx.replay_protect = ctx->secy->replay_protect;
|
||||||
|
sc.rx.replay_window = ctx->secy->replay_window;
|
||||||
|
|
||||||
|
if(memcmp(&cur_sc, &sc, sizeof(rtk_macsec_sc_t)) != 0)
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sc_update(ctx->phydev, RTK_MACSEC_DIR_INGRESS, &sc, &sc_id, (ctx->rx_sc->active) ? 1 : 0));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __rtk_macsec_set_rxsa(struct macsec_context *ctx, bool update)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sa_t sa;
|
||||||
|
memset(&sa, 0x0, sizeof(rtk_macsec_sa_t));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->sa.rx_sa->sc->sci, &sc_id));
|
||||||
|
|
||||||
|
if (update)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_get(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id, ctx->sa.assoc_num, &sa));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sa.key_bytes = ctx->secy->key_len;
|
||||||
|
memcpy(sa.key, ctx->sa.key, sa.key_bytes);
|
||||||
|
if(ctx->secy->xpn)
|
||||||
|
{
|
||||||
|
memcpy(sa.salt, ctx->sa.rx_sa->key.salt.bytes, MACSEC_SALT_LEN);
|
||||||
|
RTK_PHYLIB_VAL_TO_BYTE_ARRAY(ctx->sa.rx_sa->ssci, 4, sa.ssci, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sa.pn = ctx->sa.tx_sa->next_pn_halves.lower;
|
||||||
|
sa.pn_h = ctx->sa.tx_sa->next_pn_halves.upper;
|
||||||
|
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
{
|
||||||
|
PR_DBG("[%s,%d] update:%u \n", __FUNCTION__, __LINE__, update);
|
||||||
|
PR_DBG(" KEY 0-15 = 0x%02X%02X%02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||||
|
sa.key[0], sa.key[1], sa.key[2], sa.key[3],
|
||||||
|
sa.key[4], sa.key[5], sa.key[6], sa.key[7],
|
||||||
|
sa.key[8], sa.key[9], sa.key[10],sa.key[11],
|
||||||
|
sa.key[12],sa.key[13],sa.key[14],sa.key[15]);
|
||||||
|
if (ctx->secy->key_len == 32)
|
||||||
|
{
|
||||||
|
PR_DBG(" KEY16-31 = 0x%02X%02X%02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||||
|
sa.key[16],sa.key[17],sa.key[18],sa.key[19],
|
||||||
|
sa.key[20],sa.key[21],sa.key[22],sa.key[23],
|
||||||
|
sa.key[24],sa.key[25],sa.key[26],sa.key[27],
|
||||||
|
sa.key[28],sa.key[29],sa.key[30],sa.key[31]);
|
||||||
|
}
|
||||||
|
PR_DBG(" ctx->sa.rx_sa->active: %u\n", ctx->sa.rx_sa->active);
|
||||||
|
PR_DBG(" ctx->secy->xpn: %u\n", ctx->secy->xpn);
|
||||||
|
PR_DBG(" sa.pn: 0x%X, sa.pn_h: 0x%X\n", sa.pn, sa.pn_h);
|
||||||
|
if(ctx->secy->xpn)
|
||||||
|
{
|
||||||
|
PR_DBG(" ctx->sa.tx_sa->key.salt = 0x%02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X\n",
|
||||||
|
sa.salt[0], sa.salt[1], sa.salt[2], sa.salt[3],
|
||||||
|
sa.salt[4], sa.salt[5], sa.salt[6], sa.salt[7],
|
||||||
|
sa.salt[8], sa.salt[9], sa.salt[10], sa.salt[11]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_create(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id, ctx->sa.assoc_num, &sa));
|
||||||
|
|
||||||
|
if (ctx->sa.rx_sa->active)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_activate(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id, ctx->sa.assoc_num));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_rxsa_disable(ctx->phydev, sc_id, ctx->sa.assoc_num));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_add_rxsa(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0, sa_id = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_set_rxsa(ctx, false));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->sa.rx_sa->sc->sci, &sc_id));
|
||||||
|
sa_id = PHY_MACSEC_HW_SA_ID(sc_id, ctx->sa.assoc_num);
|
||||||
|
macsec_db->rxsa_stats[sa_id] = kzalloc(sizeof(rtk_macsec_rxsa_stats_t), GFP_KERNEL);
|
||||||
|
if (macsec_db->rxsa_stats[sa_id] == NULL)
|
||||||
|
{
|
||||||
|
rtk_macsec_del_rxsa(ctx);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_del_rxsa(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0, sa_id = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->sa.rx_sa->sc->sci, &sc_id));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_del(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id, ctx->sa.assoc_num));
|
||||||
|
|
||||||
|
sa_id = PHY_MACSEC_HW_SA_ID(sc_id, ctx->sa.assoc_num);
|
||||||
|
if (macsec_db->rxsa_stats[sa_id] != NULL)
|
||||||
|
{
|
||||||
|
kfree(macsec_db->rxsa_stats[sa_id]);
|
||||||
|
macsec_db->rxsa_stats[sa_id] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_upd_rxsa(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_set_rxsa(ctx, true));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __rtk_macsec_set_txsa(struct macsec_context *ctx, bool update)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sa_t sa;
|
||||||
|
memset(&sa, 0x0, sizeof(rtk_macsec_sa_t));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_EGRESS, ctx->secy->sci, &sc_id));
|
||||||
|
|
||||||
|
if (update)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_get(ctx->phydev, RTK_MACSEC_DIR_EGRESS, sc_id, ctx->sa.assoc_num, &sa));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sa.key_bytes = ctx->secy->key_len;
|
||||||
|
memcpy(sa.key, ctx->sa.key, sa.key_bytes);
|
||||||
|
if(ctx->secy->xpn)
|
||||||
|
{
|
||||||
|
memcpy(sa.salt, ctx->sa.tx_sa->key.salt.bytes, MACSEC_SALT_LEN);
|
||||||
|
RTK_PHYLIB_VAL_TO_BYTE_ARRAY(ctx->sa.tx_sa->ssci, 4, sa.ssci, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sa.pn = ctx->sa.tx_sa->next_pn_halves.lower;
|
||||||
|
sa.pn_h = ctx->sa.tx_sa->next_pn_halves.upper;
|
||||||
|
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
{
|
||||||
|
PR_DBG("[%s,%d] update:%u \n", __FUNCTION__, __LINE__, update);
|
||||||
|
PR_DBG(" KEY 0-15 = 0x%02X%02X%02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||||
|
sa.key[0], sa.key[1], sa.key[2], sa.key[3],
|
||||||
|
sa.key[4], sa.key[5], sa.key[6], sa.key[7],
|
||||||
|
sa.key[8], sa.key[9], sa.key[10],sa.key[11],
|
||||||
|
sa.key[12],sa.key[13],sa.key[14],sa.key[15]);
|
||||||
|
if (ctx->secy->key_len == 32)
|
||||||
|
{
|
||||||
|
PR_DBG(" KEY16-31 = 0x%02X%02X%02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||||
|
sa.key[16],sa.key[17],sa.key[18],sa.key[19],
|
||||||
|
sa.key[20],sa.key[21],sa.key[22],sa.key[23],
|
||||||
|
sa.key[24],sa.key[25],sa.key[26],sa.key[27],
|
||||||
|
sa.key[28],sa.key[29],sa.key[30],sa.key[31]);
|
||||||
|
}
|
||||||
|
PR_DBG(" ctx->sa.tx_sa->active: %u\n", ctx->sa.tx_sa->active);
|
||||||
|
PR_DBG(" ctx->secy->xpn: %u\n", ctx->secy->xpn);
|
||||||
|
PR_DBG(" sa.pn: 0x%X, sa.pn_h: 0x%X\n", sa.pn, sa.pn_h);
|
||||||
|
if(ctx->secy->xpn)
|
||||||
|
{
|
||||||
|
PR_DBG(" ctx->sa.tx_sa->key.salt = 0x%02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X\n",
|
||||||
|
sa.salt[0], sa.salt[1], sa.salt[2], sa.salt[3],
|
||||||
|
sa.salt[4], sa.salt[5], sa.salt[6], sa.salt[7],
|
||||||
|
sa.salt[8], sa.salt[9], sa.salt[10], sa.salt[11]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_create(ctx->phydev, RTK_MACSEC_DIR_EGRESS, sc_id, ctx->sa.assoc_num, &sa));
|
||||||
|
|
||||||
|
if (ctx->sa.tx_sa->active)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_activate(ctx->phydev, RTK_MACSEC_DIR_EGRESS, sc_id, ctx->sa.assoc_num));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_txsa_disable(ctx->phydev, sc_id));
|
||||||
|
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_add_txsa(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0, sa_id = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_set_txsa(ctx, false));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_EGRESS, ctx->secy->sci, &sc_id));
|
||||||
|
sa_id = PHY_MACSEC_HW_SA_ID(sc_id, ctx->sa.assoc_num);
|
||||||
|
macsec_db->txsa_stats[sa_id] = kzalloc(sizeof(rtk_macsec_txsa_stats_t), GFP_KERNEL);
|
||||||
|
if (macsec_db->txsa_stats[sa_id] == NULL)
|
||||||
|
{
|
||||||
|
rtk_macsec_del_txsa(ctx);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_del_txsa(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 sc_id = 0, sa_id = 0;
|
||||||
|
struct rtk_phy_priv *priv = ctx->phydev->priv;
|
||||||
|
rtk_macsec_port_info_t *macsec_db = priv->macsec;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_EGRESS, ctx->secy->sci, &sc_id));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_del(ctx->phydev, RTK_MACSEC_DIR_EGRESS, sc_id, ctx->sa.assoc_num));
|
||||||
|
|
||||||
|
sa_id = PHY_MACSEC_HW_SA_ID(sc_id, ctx->sa.assoc_num);
|
||||||
|
if (macsec_db->txsa_stats[sa_id] != NULL)
|
||||||
|
{
|
||||||
|
kfree(macsec_db->txsa_stats[sa_id]);
|
||||||
|
macsec_db->txsa_stats[sa_id] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_upd_txsa(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(__rtk_macsec_set_txsa(ctx, true));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rtk_macsec_get_dev_stats(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint64 cnt = 0;
|
||||||
|
uint32 sc_id = 0, an = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_port_get(ctx->phydev, RTK_MACSEC_STAT_OutPktsUntagged, &cnt));
|
||||||
|
ctx->stats.dev_stats->OutPktsUntagged = cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_port_get(ctx->phydev, RTK_MACSEC_STAT_InPktsUntagged, &cnt));
|
||||||
|
ctx->stats.dev_stats->InPktsUntagged = cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_port_get(ctx->phydev, RTK_MACSEC_STAT_InPktsNoTag, &cnt));
|
||||||
|
ctx->stats.dev_stats->InPktsNoTag = cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_port_get(ctx->phydev, RTK_MACSEC_STAT_InPktsBadTag, &cnt));
|
||||||
|
ctx->stats.dev_stats->InPktsBadTag = cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_port_get(ctx->phydev, RTK_MACSEC_STAT_InPktsUnknownSCI, &cnt));
|
||||||
|
ctx->stats.dev_stats->InPktsUnknownSCI = cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_port_get(ctx->phydev, RTK_MACSEC_STAT_InPktsNoSCI, &cnt));
|
||||||
|
ctx->stats.dev_stats->InPktsNoSCI = cnt;
|
||||||
|
|
||||||
|
ctx->stats.dev_stats->InPktsOverrun = 0; /* not support */
|
||||||
|
|
||||||
|
/* accumulate over each egress SA */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_EGRESS, ctx->secy->sci, &sc_id));
|
||||||
|
for (an = 0; an < MACSEC_NUM_AN; an++)
|
||||||
|
{
|
||||||
|
if (0 == rtk_phylib_macsec_stat_txsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_TXSA_STAT_OutPktsTooLong, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.dev_stats->OutPktsTooLong += cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_get_txsc_stats(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint64 cnt = 0;
|
||||||
|
uint32 sc_id = 0, an = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_EGRESS, ctx->secy->sci, &sc_id));
|
||||||
|
|
||||||
|
/* accumulate over each egress SA */
|
||||||
|
for (an = 0; an < MACSEC_NUM_AN; an++)
|
||||||
|
{
|
||||||
|
if (0 == rtk_phylib_macsec_stat_txsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_TXSA_STAT_OutPktsProtectedEncrypted, &cnt))
|
||||||
|
{
|
||||||
|
if (ctx->secy->tx_sc.encrypt)
|
||||||
|
{
|
||||||
|
ctx->stats.tx_sc_stats->OutPktsEncrypted += cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->stats.tx_sc_stats->OutPktsProtected += cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == rtk_phylib_macsec_stat_txsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_TXSA_STAT_OutOctetsProtectedEncrypted, &cnt))
|
||||||
|
{
|
||||||
|
if (ctx->secy->tx_sc.encrypt)
|
||||||
|
{
|
||||||
|
ctx->stats.tx_sc_stats->OutOctetsEncrypted += cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->stats.tx_sc_stats->OutOctetsProtected += cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_get_rxsc_stats(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint64 cnt = 0;
|
||||||
|
uint32 sc_id = 0, an = 0;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->rx_sc->sci, &sc_id));
|
||||||
|
|
||||||
|
/* accumulate over each ingress SA */
|
||||||
|
for (an = 0; an < MACSEC_NUM_AN; an++)
|
||||||
|
{
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InOctetsDecryptedValidated, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InOctetsValidated += cnt;
|
||||||
|
ctx->stats.rx_sc_stats->InOctetsDecrypted = ctx->stats.rx_sc_stats->InOctetsValidated;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsUnchecked, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsUnchecked += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsDelayed, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsDelayed += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsOK, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsOK += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsInvalid, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsInvalid += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsLate, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsLate += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsNotValid, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsNotValid += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsNotUsingSA, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsNotUsingSA += cnt;
|
||||||
|
}
|
||||||
|
if (0 == rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, an, RTK_MACSEC_RXSA_STAT_InPktsUnusedSA, &cnt))
|
||||||
|
{
|
||||||
|
ctx->stats.rx_sc_stats->InPktsUnusedSA += cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_get_txsa_stats(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint64 cnt = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sa_t sa;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_EGRESS, ctx->secy->sci, &sc_id));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_txsa_get(ctx->phydev, sc_id, ctx->sa.assoc_num, RTK_MACSEC_TXSA_STAT_OutPktsProtectedEncrypted, &cnt));
|
||||||
|
if (ctx->secy->tx_sc.encrypt)
|
||||||
|
{
|
||||||
|
ctx->stats.tx_sa_stats->OutPktsEncrypted = (uint32)cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->stats.tx_sa_stats->OutPktsProtected = (uint32)cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_get(ctx->phydev, RTK_MACSEC_DIR_EGRESS, sc_id, ctx->sa.assoc_num, &sa));
|
||||||
|
ctx->sa.tx_sa->next_pn_halves.lower = sa.pn;
|
||||||
|
ctx->sa.tx_sa->next_pn_halves.upper = sa.pn_h;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtk_macsec_get_rxsa_stats(struct macsec_context *ctx)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint64 cnt = 0;
|
||||||
|
uint32 sc_id = 0;
|
||||||
|
rtk_macsec_sa_t sa;
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||||
|
if (ctx->prepare)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sci_to_scid(ctx->phydev, RTK_MACSEC_DIR_INGRESS, ctx->rx_sc->sci, &sc_id));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, ctx->sa.assoc_num, RTK_MACSEC_RXSA_STAT_InPktsOK, &cnt));
|
||||||
|
ctx->stats.rx_sa_stats->InPktsOK = (uint32)cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, ctx->sa.assoc_num, RTK_MACSEC_RXSA_STAT_InPktsInvalid, &cnt));
|
||||||
|
ctx->stats.rx_sa_stats->InPktsInvalid = (uint32)cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, ctx->sa.assoc_num, RTK_MACSEC_RXSA_STAT_InPktsNotValid, &cnt));
|
||||||
|
ctx->stats.rx_sa_stats->InPktsNotValid = (uint32)cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, ctx->sa.assoc_num, RTK_MACSEC_RXSA_STAT_InPktsNotUsingSA, &cnt));
|
||||||
|
ctx->stats.rx_sa_stats->InPktsNotUsingSA = (uint32)cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_stat_rxsa_get(ctx->phydev, sc_id, ctx->sa.assoc_num, RTK_MACSEC_RXSA_STAT_InPktsUnusedSA, &cnt));
|
||||||
|
ctx->stats.rx_sa_stats->InPktsUnusedSA = (uint32)cnt;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_sa_get(ctx->phydev, RTK_MACSEC_DIR_INGRESS, sc_id, ctx->sa.assoc_num, &sa));
|
||||||
|
ctx->sa.rx_sa->next_pn_halves.lower = sa.pn;
|
||||||
|
ctx->sa.rx_sa->next_pn_halves.upper = sa.pn_h;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct macsec_ops rtk_macsec_ops = {
|
||||||
|
/* Device wide */
|
||||||
|
.mdo_dev_open = rtk_macsec_dev_open,
|
||||||
|
.mdo_dev_stop = rtk_macsec_dev_stop,
|
||||||
|
/* SecY */
|
||||||
|
.mdo_add_secy = rtk_macsec_add_secy,
|
||||||
|
.mdo_upd_secy = rtk_macsec_upd_secy,
|
||||||
|
.mdo_del_secy = rtk_macsec_del_secy,
|
||||||
|
/* Security channels */
|
||||||
|
.mdo_add_rxsc = rtk_macsec_add_rxsc,
|
||||||
|
.mdo_upd_rxsc = rtk_macsec_upd_rxsc,
|
||||||
|
.mdo_del_rxsc = rtk_macsec_del_rxsc,
|
||||||
|
/* Security associations */
|
||||||
|
.mdo_add_rxsa = rtk_macsec_add_rxsa,
|
||||||
|
.mdo_upd_rxsa = rtk_macsec_upd_rxsa,
|
||||||
|
.mdo_del_rxsa = rtk_macsec_del_rxsa,
|
||||||
|
.mdo_add_txsa = rtk_macsec_add_txsa,
|
||||||
|
.mdo_upd_txsa = rtk_macsec_upd_txsa,
|
||||||
|
.mdo_del_txsa = rtk_macsec_del_txsa,
|
||||||
|
/* Statistics */
|
||||||
|
.mdo_get_dev_stats = rtk_macsec_get_dev_stats,
|
||||||
|
.mdo_get_tx_sc_stats = rtk_macsec_get_txsc_stats,
|
||||||
|
.mdo_get_rx_sc_stats = rtk_macsec_get_rxsc_stats,
|
||||||
|
.mdo_get_tx_sa_stats = rtk_macsec_get_txsa_stats,
|
||||||
|
.mdo_get_rx_sa_stats = rtk_macsec_get_rxsa_stats,
|
||||||
|
};
|
||||||
|
|
||||||
|
int rtk_macsec_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
struct rtk_phy_priv *priv = phydev->priv;
|
||||||
|
|
||||||
|
priv->macsec = kzalloc(sizeof(*(priv->macsec)), GFP_KERNEL);
|
||||||
|
if (!priv->macsec)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(priv->macsec, 0, sizeof(*(priv->macsec)));
|
||||||
|
|
||||||
|
switch (phydev->drv->phy_id)
|
||||||
|
{
|
||||||
|
case REALTEK_PHY_ID_RTL8261N:
|
||||||
|
case REALTEK_PHY_ID_RTL8264B:
|
||||||
|
phydev->macsec_ops = &rtk_macsec_ops;
|
||||||
|
priv->macsec->max_sa_num = 64;
|
||||||
|
priv->macsec->max_sc_num = 64/4;
|
||||||
|
ret = rtk_phylib_826xb_macsec_init(phydev);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
phydev_err(phydev, "[%s]rtk_phylib_826xb_macsec_init failed!! 0x%X\n", __FUNCTION__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PR_ERR("[%s]phy_id: 0x%X not support!\n", __FUNCTION__, phydev->drv->phy_id);
|
||||||
|
kfree(priv->macsec);
|
||||||
|
priv->macsec = NULL;
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_macsec_init(phydev));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
58
sources/rtk-gp3000/src/hal/phy/rtk_osal.c
Normal file
58
sources/rtk-gp3000/src/hal/phy/rtk_osal.c
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "type.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "rtk_phylib_def.h"
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/sched/signal.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
|
||||||
|
#ifndef CONFIG_OPENWRT_SDK
|
||||||
|
int32
|
||||||
|
osal_time_usecs_get(osal_usecs_t *pUsec)
|
||||||
|
{
|
||||||
|
struct timespec64 ts;
|
||||||
|
|
||||||
|
RT_PARAM_CHK((NULL == pUsec), RT_ERR_NULL_POINTER);
|
||||||
|
|
||||||
|
ktime_get_ts64(&ts);
|
||||||
|
*pUsec = (osal_usecs_t)((ts.tv_sec * USEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_USEC));
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
osal_alloc(uint32 size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
p = kmalloc((size_t)size, GFP_ATOMIC);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_common_general_reg_mmd_get(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 rData = 0;
|
||||||
|
rData = phy_read_mmd(port, mmdAddr, mmdReg);
|
||||||
|
if (rData < 0)
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
*pData = (uint32)rData;
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_common_general_reg_mmd_set(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data)
|
||||||
|
{
|
||||||
|
int ret = phy_write_mmd(port, mmdAddr, mmdReg, data);
|
||||||
|
return (ret < 0) ? RT_ERR_FAILED : RT_ERR_OK;
|
||||||
|
}
|
||||||
100
sources/rtk-gp3000/src/hal/phy/rtk_osal.h
Normal file
100
sources/rtk-gp3000/src/hal/phy/rtk_osal.h
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RTK_PHY_OSAL_H
|
||||||
|
#define __RTK_PHY_OSAL_H
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include "type.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "phy_patch.h"
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
|
||||||
|
#ifdef PHYPATCH_DB_GET
|
||||||
|
#undef PHYPATCH_DB_GET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PHYPATCH_DB_GET(_unit, _pPhy_device, _pPatchDb) \
|
||||||
|
do { \
|
||||||
|
struct rtk_phy_priv *_pPriv = (_pPhy_device)->priv; \
|
||||||
|
rt_phy_patch_db_t *_pDb = _pPriv->patch; _pPatchDb = _pDb; \
|
||||||
|
/*printk("[PHYPATCH_DB_GET] ? [%s]\n", (_pDb != NULL) ? "E":"N");*/ \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define HWP_9300_FAMILY_ID(_unit) 1
|
||||||
|
#define HWP_9310_FAMILY_ID(_unit) 0
|
||||||
|
#define RTK_9300_FAMILY_ID(_unit) 1
|
||||||
|
#define RTK_9310_FAMILY_ID(_unit) 0
|
||||||
|
#define RTK_9311B_FAMILY_ID(_unit) 0
|
||||||
|
#define RTK_9330_FAMILY_ID(_unit) 0
|
||||||
|
|
||||||
|
#ifndef WAIT_COMPLETE_VAR
|
||||||
|
#define WAIT_COMPLETE_VAR() \
|
||||||
|
osal_usecs_t _t, _now, _t_wait=0, _timeout; \
|
||||||
|
int32 _chkCnt=0;
|
||||||
|
|
||||||
|
#define WAIT_COMPLETE(_timeout_us) \
|
||||||
|
_timeout = _timeout_us; \
|
||||||
|
for(osal_time_usecs_get(&_t),osal_time_usecs_get(&_now),_t_wait=0,_chkCnt=0 ; \
|
||||||
|
(_t_wait <= _timeout); \
|
||||||
|
osal_time_usecs_get(&_now), _chkCnt++, _t_wait += ((_now >= _t) ? (_now - _t) : (0xFFFFFFFF - _t + _now)),_t = _now \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define WAIT_COMPLETE_IS_TIMEOUT() (_t_wait > _timeout)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* OSAL */
|
||||||
|
#include <linux/slab.h>
|
||||||
|
int32 osal_time_usecs_get(osal_usecs_t *pUsec);
|
||||||
|
void *osal_alloc(uint32 size);
|
||||||
|
#define osal_time_mdelay mdelay
|
||||||
|
|
||||||
|
#include <linux/ctype.h> /* for Kernel Space */
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#define osal_strlen strlen
|
||||||
|
#define osal_strcmp strcmp
|
||||||
|
#define osal_strcpy strcpy
|
||||||
|
#define osal_strncpy strncpy
|
||||||
|
#define osal_strcat strcat
|
||||||
|
#define osal_strchr strchr
|
||||||
|
#define osal_memset memset
|
||||||
|
#define osal_memcpy memcpy
|
||||||
|
#define osal_memcmp memcmp
|
||||||
|
#define osal_strdup strdup
|
||||||
|
#define osal_strncmp strncmp
|
||||||
|
#define osal_strstr strstr
|
||||||
|
#define osal_strtok strtok
|
||||||
|
#define osal_strtok_r strtok_r
|
||||||
|
#define osal_toupper toupper
|
||||||
|
|
||||||
|
#define osal_printf printk
|
||||||
|
|
||||||
|
/* HWP */
|
||||||
|
#define HWP_PORT_SMI(unit, port) 0
|
||||||
|
#define HWP_PHY_MODEL_BY_PORT(unit, port) 0
|
||||||
|
#define HWP_PHY_ADDR(unit, port) 0
|
||||||
|
#define HWP_PHY_BASE_MACID(unit, p) 0
|
||||||
|
#define HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) if (bcast_phyad < 0x1F && p != NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/* RT_LOG */
|
||||||
|
//#define RT_LOG(level, module, fmt, args...) do { printk("RT_LOG:"fmt, ## args); } while(0)
|
||||||
|
#define RT_LOG(level, module, fmt, args...) do {} while(0)
|
||||||
|
#define RT_ERR(error_code, module, fmt, args...) do {} while(0)
|
||||||
|
#define RT_INIT_ERR(error_code, module, fmt, args...) do {} while(0)
|
||||||
|
#define RT_INIT_MSG(fmt, args...) do {} while(0)
|
||||||
|
|
||||||
|
#define phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, bcast_phyad) 0
|
||||||
|
#define phy_8224_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, bcast_phyad) 0
|
||||||
|
|
||||||
|
/* reg access */
|
||||||
|
int32 phy_common_general_reg_mmd_get(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 *pData);
|
||||||
|
int32 phy_common_general_reg_mmd_set(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __RTK_PHY_OSAL_H */
|
||||||
613
sources/rtk-gp3000/src/hal/phy/rtk_phy.c
Normal file
613
sources/rtk-gp3000/src/hal/phy/rtk_phy.c
Normal file
|
|
@ -0,0 +1,613 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/ethtool_netlink.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
|
#include "phy_rtl826xb_patch.h"
|
||||||
|
|
||||||
|
#include "rtk_phylib_rtl826xb.h"
|
||||||
|
#include "rtk_phylib_rtl8224.h"
|
||||||
|
#include "rtk_phylib_macsec.h"
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
|
||||||
|
#include "rtk_phy.h"
|
||||||
|
#include "rtk_phy_rtl8224.h"
|
||||||
|
|
||||||
|
static int rtk_phy_cable_test_report_trans(rtk_rtct_channel_result_t *result)
|
||||||
|
{
|
||||||
|
if(result->cable_status == 0)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OK;
|
||||||
|
|
||||||
|
if(result->cable_status & RTK_PHYLIB_CABLE_STATUS_INTER_PAIR_SHORT)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
|
||||||
|
if(result->cable_status & RTK_PHYLIB_CABLE_STATUS_SHORT)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->cable_status & RTK_PHYLIB_CABLE_STATUS_OPEN)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
|
||||||
|
if(result->cable_status & RTK_PHYLIB_CABLE_STATUS_CROSS)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_get_features(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct rtk_phy_priv *priv = phydev->priv;
|
||||||
|
|
||||||
|
ret = genphy_c45_pma_read_abilities(phydev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
linkmode_or(phydev->supported, phydev->supported, PHY_BASIC_FEATURES);
|
||||||
|
|
||||||
|
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
|
||||||
|
/* not support 10M modes */
|
||||||
|
linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
|
||||||
|
switch (priv->phytype)
|
||||||
|
{
|
||||||
|
case RTK_PHYLIB_RTL8251L:
|
||||||
|
case RTK_PHYLIB_RTL8254B:
|
||||||
|
linkmode_clear_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_probe(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct rtk_phy_priv *priv = NULL;
|
||||||
|
int data = 0;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct rtk_phy_priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(priv, 0, sizeof(struct rtk_phy_priv));
|
||||||
|
|
||||||
|
if (phy_rtl826xb_patch_db_init(0, phydev, &(priv->patch)) != RT_ERR_OK)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8261N)
|
||||||
|
{
|
||||||
|
data = phy_read_mmd(phydev, 30, 0x103);
|
||||||
|
if (data < 0)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
if (data == 0x8251)
|
||||||
|
{
|
||||||
|
priv->phytype = RTK_PHYLIB_RTL8251L;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->phytype = RTK_PHYLIB_RTL8261N;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8264B)
|
||||||
|
{
|
||||||
|
data = phy_read_mmd(phydev, 30, 0x103);
|
||||||
|
if (data < 0)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
if (data == 0x8254)
|
||||||
|
{
|
||||||
|
priv->phytype = RTK_PHYLIB_RTL8254B;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->phytype = RTK_PHYLIB_RTL8264B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
priv->isBasePort = (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8261N) ? (1) : (((phydev->mdio.addr % 4) == 0) ? (1) : (0));
|
||||||
|
phydev->priv = priv;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
switch (phydev->drv->phy_id)
|
||||||
|
{
|
||||||
|
case REALTEK_PHY_ID_RTL8261N:
|
||||||
|
case REALTEK_PHY_ID_RTL8264B:
|
||||||
|
phydev_info(phydev, "%s:%u [RTL8261N/RTL826XB] phy_id: 0x%X PHYAD:%d\n", __FUNCTION__, __LINE__, phydev->drv->phy_id, phydev->mdio.addr);
|
||||||
|
|
||||||
|
#if 1 /* toggle reset */
|
||||||
|
phy_write_mmd(phydev, 30, 0x145, 0x0001);
|
||||||
|
phy_write_mmd(phydev, 30, 0x145, 0x0000);
|
||||||
|
mdelay(30);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = phy_patch(0, phydev, 0, PHY_PATCH_MODE_NORMAL);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] patch failed!! 0x%X\n", __FUNCTION__, __LINE__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rtk_phylib_826xb_intr_init(phydev);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] rtk_phylib_826xb_intr_init failed!! 0x%X\n", __FUNCTION__, __LINE__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rtk_macsec_init(phydev);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] rtk_macsec_init failed!! 0x%X\n", __FUNCTION__, __LINE__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = rtk_phylib_826xb_sds_write(phydev, 6, 3, 15, 0, 0x88C6);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] SerDes init failed!! 0x%X\n", __FUNCTION__, __LINE__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* Debug: patch check */
|
||||||
|
ret = phy_patch(0, phydev, 0, PHY_PATCH_MODE_CMP);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] phy_patch failed!! 0x%X\n", __FUNCTION__, __LINE__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
printk("[%s,%u] patch chk %s\n", __FUNCTION__, __LINE__, (ret == 0) ? "PASS" : "FAIL");
|
||||||
|
#endif
|
||||||
|
#if 0 /* Debug: USXGMII*/
|
||||||
|
{
|
||||||
|
uint32 data = 0;
|
||||||
|
rtk_phylib_826xb_sds_read(phydev, 0x07, 0x10, 15, 0, &data);
|
||||||
|
printk("[%s,%u] SDS 0x07, 0x10 : 0x%X\n", __FUNCTION__, __LINE__, data);
|
||||||
|
rtk_phylib_826xb_sds_read(phydev, 0x06, 0x12, 15, 0, &data);
|
||||||
|
printk("[%s,%u] SDS 0x06, 0x12 : 0x%X\n", __FUNCTION__, __LINE__, data);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
u16 sdspage = 0x5, sdsreg = 0x0;
|
||||||
|
u16 regData = (sdspage & 0x3f) | ((sdsreg & 0x1f) << 6) | BIT(15);
|
||||||
|
u16 readData = 0;
|
||||||
|
phy_write_mmd(phydev, 30, 323, regData);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
udelay(10);
|
||||||
|
readData = phy_read_mmd(phydev, 30, 323);
|
||||||
|
} while ((readData & BIT(15)) != 0);
|
||||||
|
readData = phy_read_mmd(phydev, 30, 322);
|
||||||
|
printk("[%s,%d] sds link [%s] (0x%X)\n", __FUNCTION__, __LINE__, (readData & BIT(12)) ? "UP" : "DOWN", readData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
phydev_err(phydev, "%s:%u Unknow phy_id: 0x%X\n", __FUNCTION__, __LINE__, phydev->drv->phy_id);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_c45_suspend(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = rtk_phylib_c45_power_low(phydev);
|
||||||
|
|
||||||
|
phydev->speed = SPEED_UNKNOWN;
|
||||||
|
phydev->duplex = DUPLEX_UNKNOWN;
|
||||||
|
phydev->pause = 0;
|
||||||
|
phydev->asym_pause = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_c45_resume(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
return rtk_phylib_c45_power_normal(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_c45_config_aneg(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
u16 reg = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
|
||||||
|
if (phydev->autoneg == AUTONEG_DISABLE)
|
||||||
|
{
|
||||||
|
if (phydev->speed != SPEED_100)
|
||||||
|
{
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
return genphy_c45_pma_setup_forced(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = genphy_c45_an_config_aneg(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret > 0)
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
reg = 0;
|
||||||
|
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||||
|
phydev->advertising))
|
||||||
|
reg |= BIT(9);
|
||||||
|
|
||||||
|
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||||
|
phydev->advertising))
|
||||||
|
reg |= BIT(8);
|
||||||
|
|
||||||
|
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, 0xA412,
|
||||||
|
BIT(9) | BIT(8) , reg);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret > 0)
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
return genphy_c45_check_and_restart_aneg(phydev, changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_c45_aneg_done(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
return genphy_c45_aneg_done(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_c45_read_status(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret = 0, status = 0;
|
||||||
|
phydev->speed = SPEED_UNKNOWN;
|
||||||
|
phydev->duplex = DUPLEX_UNKNOWN;
|
||||||
|
phydev->pause = 0;
|
||||||
|
phydev->asym_pause = 0;
|
||||||
|
|
||||||
|
ret = genphy_c45_read_link(phydev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (phydev->autoneg == AUTONEG_ENABLE)
|
||||||
|
{
|
||||||
|
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||||
|
phydev->lp_advertising);
|
||||||
|
|
||||||
|
ret = genphy_c45_read_lpa(phydev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
status = phy_read_mmd(phydev, 31, 0xA414);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||||
|
phydev->lp_advertising, status & BIT(11));
|
||||||
|
|
||||||
|
phy_resolve_aneg_linkmode(phydev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = genphy_c45_read_pma(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mdix*/
|
||||||
|
status = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_SWAPPOL);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
switch (status & 0x3)
|
||||||
|
{
|
||||||
|
case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
|
||||||
|
phydev->mdix = ETH_TP_MDI;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
phydev->mdix = ETH_TP_MDI_X;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
phydev->mdix = ETH_TP_MDI_INVALID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtkphy_c45_pcs_loopback(struct phy_device *phydev, bool enable)
|
||||||
|
{
|
||||||
|
return rtk_phylib_c45_pcs_loopback(phydev, (enable == true) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_cable_test_start(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
return rtk_phylib_826xb_cable_test_start(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_cable_test_get_status(struct phy_device *phydev, bool *finished)
|
||||||
|
{
|
||||||
|
uint32 finish_read = 0;
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 pair = 0;
|
||||||
|
rtk_rtct_channel_result_t reslut;
|
||||||
|
|
||||||
|
*finished = false;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_cable_test_finished_get(phydev, &finish_read));
|
||||||
|
*finished = (finish_read == 1) ? true : false;
|
||||||
|
|
||||||
|
if (finish_read == 1)
|
||||||
|
{
|
||||||
|
for (pair = 0; pair < 4; pair++)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_cable_test_result_get(phydev, pair, &reslut));
|
||||||
|
ethnl_cable_test_result(phydev, pair, rtk_phy_cable_test_report_trans(&reslut));
|
||||||
|
|
||||||
|
if(reslut.cable_status != RTK_PHYLIB_CABLE_STATUS_NORMAL)
|
||||||
|
ethnl_cable_test_fault_length(phydev, pair, reslut.length_cm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_config_intr(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_intr_enable(phydev, (phydev->interrupts == PHY_INTERRUPT_ENABLED)? 1 : 0));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_ack_intr(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 status = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_intr_read_clear(phydev, &status));
|
||||||
|
if (status & RTK_PHY_INTR_WOL)
|
||||||
|
{
|
||||||
|
rtk_phylib_826xb_wol_reset(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t rtl826xb_handle_intr(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
irqreturn_t ret;
|
||||||
|
uint32 status = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_intr_read_clear(phydev, &status));
|
||||||
|
if (status & RTK_PHY_INTR_LINK_CHANGE)
|
||||||
|
{
|
||||||
|
pr_debug("[%s,%d] RTK_PHY_INTR_LINK_CHANGE\n", __FUNCTION__, __LINE__);
|
||||||
|
phy_mac_interrupt(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & RTK_PHY_INTR_WOL)
|
||||||
|
{
|
||||||
|
pr_debug("[%s,%d] RTK_PHY_INTR_WOL\n", __FUNCTION__, __LINE__);
|
||||||
|
rtk_phylib_826xb_wol_reset(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_get_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, void *data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 val = 0;
|
||||||
|
|
||||||
|
switch (tuna->id)
|
||||||
|
{
|
||||||
|
case ETHTOOL_PHY_EDPD:
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_link_down_power_saving_get(phydev, &val));
|
||||||
|
*(u16 *)data = (val == 0) ? ETHTOOL_PHY_EDPD_DISABLE : ETHTOOL_PHY_EDPD_DFLT_TX_MSECS;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_set_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, const void *data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 val = 0;
|
||||||
|
|
||||||
|
switch (tuna->id)
|
||||||
|
{
|
||||||
|
case ETHTOOL_PHY_EDPD:
|
||||||
|
switch (*(const u16 *)data)
|
||||||
|
{
|
||||||
|
case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
|
||||||
|
val = 1;
|
||||||
|
break;
|
||||||
|
case ETHTOOL_PHY_EDPD_DISABLE:
|
||||||
|
val = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_link_down_power_saving_set(phydev, val));
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl826xb_set_wol(struct phy_device *phydev,
|
||||||
|
struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint8 *mac_addr = NULL;
|
||||||
|
uint32 rtk_wol_opts = 0;
|
||||||
|
|
||||||
|
struct net_device *ndev = phydev->attached_dev;
|
||||||
|
if (!ndev)
|
||||||
|
return RTK_PHYLIB_ERR_FAILED;
|
||||||
|
|
||||||
|
if (wol->wolopts & ~( WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (wol->wolopts & (WAKE_MAGIC | WAKE_UCAST))
|
||||||
|
{
|
||||||
|
mac_addr = (uint8 *) ndev->dev_addr;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_wol_unicast_addr_set(phydev, mac_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_MCAST)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_wol_multicast_mask_reset(phydev));
|
||||||
|
|
||||||
|
if (!netdev_mc_empty(ndev))
|
||||||
|
{
|
||||||
|
struct netdev_hw_addr *ha;
|
||||||
|
netdev_for_each_mc_addr(ha, ndev)
|
||||||
|
{
|
||||||
|
pr_info("[%s,%d] mac: %pM \n", __FUNCTION__, __LINE__, ha->addr);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_wol_multicast_mask_add(phydev, rtk_phylib_826xb_wol_multicast_mac2offset(ha->addr)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_PHY)
|
||||||
|
rtk_wol_opts |= RTK_WOL_OPT_LINK;
|
||||||
|
if (wol->wolopts & WAKE_MAGIC)
|
||||||
|
rtk_wol_opts |= RTK_WOL_OPT_MAGIC;
|
||||||
|
if (wol->wolopts & WAKE_UCAST)
|
||||||
|
rtk_wol_opts |= RTK_WOL_OPT_UCAST;
|
||||||
|
if (wol->wolopts & WAKE_BCAST)
|
||||||
|
rtk_wol_opts |= RTK_WOL_OPT_BCAST;
|
||||||
|
if (wol->wolopts & WAKE_MCAST)
|
||||||
|
rtk_wol_opts |= RTK_WOL_OPT_MCAST;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_wol_set(phydev, rtk_wol_opts));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void rtl826xb_get_wol(struct phy_device *phydev,
|
||||||
|
struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 rtk_wol_opts = 0;
|
||||||
|
|
||||||
|
wol->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST;
|
||||||
|
wol->wolopts = 0;
|
||||||
|
|
||||||
|
ret = rtk_phylib_826xb_wol_get(phydev, &rtk_wol_opts);
|
||||||
|
if (ret != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rtk_wol_opts & RTK_WOL_OPT_LINK)
|
||||||
|
wol->wolopts |= WAKE_PHY;
|
||||||
|
if (rtk_wol_opts & RTK_WOL_OPT_MAGIC)
|
||||||
|
wol->wolopts |= WAKE_MAGIC;
|
||||||
|
if (rtk_wol_opts & RTK_WOL_OPT_UCAST)
|
||||||
|
wol->wolopts |= WAKE_UCAST;
|
||||||
|
if (rtk_wol_opts & RTK_WOL_OPT_MCAST)
|
||||||
|
wol->wolopts |= WAKE_MCAST;
|
||||||
|
if (rtk_wol_opts & RTK_WOL_OPT_BCAST)
|
||||||
|
wol->wolopts |= WAKE_BCAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct phy_driver rtk_phy_drivers[] = {
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8261N),
|
||||||
|
.name = "Realtek RTL8261N/8261BE/8251L",
|
||||||
|
.get_features = rtl826xb_get_features,
|
||||||
|
.config_init = rtkphy_config_init,
|
||||||
|
.probe = rtl826xb_probe,
|
||||||
|
.suspend = rtkphy_c45_suspend,
|
||||||
|
.resume = rtkphy_c45_resume,
|
||||||
|
.config_aneg = rtkphy_c45_config_aneg,
|
||||||
|
.aneg_done = rtkphy_c45_aneg_done,
|
||||||
|
.read_status = rtkphy_c45_read_status,
|
||||||
|
.set_loopback = rtkphy_c45_pcs_loopback,
|
||||||
|
.cable_test_start = rtl826xb_cable_test_start,
|
||||||
|
.cable_test_get_status = rtl826xb_cable_test_get_status,
|
||||||
|
.config_intr = rtl826xb_config_intr,
|
||||||
|
.ack_interrupt = rtl826xb_ack_intr,
|
||||||
|
.handle_interrupt = rtl826xb_handle_intr,
|
||||||
|
.get_tunable = rtl826xb_get_tunable,
|
||||||
|
.set_tunable = rtl826xb_set_tunable,
|
||||||
|
.set_wol = rtl826xb_set_wol,
|
||||||
|
.get_wol = rtl826xb_get_wol,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8264B),
|
||||||
|
.name = "Realtek RTL8264B/8254B",
|
||||||
|
.get_features = rtl826xb_get_features,
|
||||||
|
.config_init = rtkphy_config_init,
|
||||||
|
.probe = rtl826xb_probe,
|
||||||
|
.suspend = rtkphy_c45_suspend,
|
||||||
|
.resume = rtkphy_c45_resume,
|
||||||
|
.config_aneg = rtkphy_c45_config_aneg,
|
||||||
|
.aneg_done = rtkphy_c45_aneg_done,
|
||||||
|
.read_status = rtkphy_c45_read_status,
|
||||||
|
.set_loopback = rtkphy_c45_pcs_loopback,
|
||||||
|
.cable_test_start = rtl826xb_cable_test_start,
|
||||||
|
.cable_test_get_status = rtl826xb_cable_test_get_status,
|
||||||
|
.config_intr = rtl826xb_config_intr,
|
||||||
|
.ack_interrupt = rtl826xb_ack_intr,
|
||||||
|
.handle_interrupt = rtl826xb_handle_intr,
|
||||||
|
.get_tunable = rtl826xb_get_tunable,
|
||||||
|
.set_tunable = rtl826xb_set_tunable,
|
||||||
|
.set_wol = rtl826xb_set_wol,
|
||||||
|
.get_wol = rtl826xb_get_wol,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8224),
|
||||||
|
.name = "Realtek RTL8224/8224N",
|
||||||
|
.get_features = rtl8224_get_features,
|
||||||
|
.config_init = rtl8224_config_init,
|
||||||
|
.probe = rtl8224_probe,
|
||||||
|
.suspend = rtkphy_c45_suspend,
|
||||||
|
.resume = rtkphy_c45_resume,
|
||||||
|
.config_aneg = rtkphy_c45_config_aneg,
|
||||||
|
.aneg_done = rtkphy_c45_aneg_done,
|
||||||
|
.read_status = rtkphy_c45_read_status,
|
||||||
|
.set_loopback = rtkphy_c45_pcs_loopback,
|
||||||
|
.cable_test_start = rtl8224_cable_test_start,
|
||||||
|
.cable_test_get_status = rtl8224_cable_test_get_status,
|
||||||
|
.get_tunable = rtl8224_get_tunable,
|
||||||
|
.set_tunable = rtl8224_set_tunable,
|
||||||
|
.config_intr = rtl8224_config_intr,
|
||||||
|
.ack_interrupt = rtl8224_ack_intr,
|
||||||
|
.handle_interrupt = rtl8224_handle_intr,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_phy_driver(rtk_phy_drivers);
|
||||||
|
|
||||||
|
|
||||||
|
static struct mdio_device_id __maybe_unused rtk_phy_tbl[] = {
|
||||||
|
{ PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8261N) },
|
||||||
|
{ PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8264B) },
|
||||||
|
{ PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8224) },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(mdio, rtk_phy_tbl);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Realtek");
|
||||||
|
MODULE_DESCRIPTION("Realtek PHY drivers");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
22
sources/rtk-gp3000/src/hal/phy/rtk_phy.h
Normal file
22
sources/rtk-gp3000/src/hal/phy/rtk_phy.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define REALTEK_PHY_ID_RTL8261N 0x001CCAF3
|
||||||
|
#define REALTEK_PHY_ID_RTL8264B 0x001CC813
|
||||||
|
#define REALTEK_PHY_ID_RTL8224 0x001CCAD0
|
||||||
|
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_MACSEC)
|
||||||
|
int rtk_macsec_init(struct phy_device *phydev);
|
||||||
|
#else
|
||||||
|
static inline int rtk_macsec_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
573
sources/rtk-gp3000/src/hal/phy/rtk_phy_rtl8224.c
Normal file
573
sources/rtk-gp3000/src/hal/phy/rtk_phy_rtl8224.c
Normal file
|
|
@ -0,0 +1,573 @@
|
||||||
|
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/ethtool_netlink.h>
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
#include "rtk_phy.h"
|
||||||
|
#include "rtk_phylib_rtl8224.h"
|
||||||
|
#include "rtk_phy_rtl8224.h"
|
||||||
|
#include "phy_rtl8224_patch.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "rtk_osal.h"
|
||||||
|
|
||||||
|
//#define RTL8224_INTERNAL_INFO 1
|
||||||
|
|
||||||
|
#ifdef RTL8224_INTERNAL_INFO
|
||||||
|
#define RTL8224_INTERNAL_PORT_CHECK(port)\
|
||||||
|
do{\
|
||||||
|
printk("\n[%s] addr(%d)\n",__FUNCTION__,port->mdio.addr);\
|
||||||
|
}while(0)
|
||||||
|
#else
|
||||||
|
#define RTL8224_INTERNAL_PORT_CHECK(port)\
|
||||||
|
do{\
|
||||||
|
}while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int _phy_8224_cable_test_report_trans(uint32 pair, rtk_rtctResult_t *result)
|
||||||
|
{
|
||||||
|
switch(pair)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if(result->un.ge_result.channelAShort)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelAOpen)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
|
||||||
|
if(result->un.ge_result.channelAMismatch)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelAPairBusy)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if(result->un.ge_result.channelBShort)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelBOpen)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
|
||||||
|
if(result->un.ge_result.channelBMismatch)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelBPairBusy)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(result->un.ge_result.channelCShort)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelCOpen)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
|
||||||
|
if(result->un.ge_result.channelCMismatch)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelCPairBusy)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if(result->un.ge_result.channelDShort)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelDOpen)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
|
||||||
|
if(result->un.ge_result.channelDMismatch)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
|
||||||
|
if(result->un.ge_result.channelDPairBusy)
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
|
||||||
|
|
||||||
|
}
|
||||||
|
return ETHTOOL_A_CABLE_RESULT_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _phy_8224_cable_test_length_get(uint32 pair, rtk_rtctResult_t *result, uint32 *length_cm)
|
||||||
|
{
|
||||||
|
switch(pair)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if(result->un.ge_result.channelAShort)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelAOpen)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelAMismatch)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelAPairBusy)
|
||||||
|
return -1;
|
||||||
|
*length_cm = result->un.ge_result.channelALen;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if(result->un.ge_result.channelBShort)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelBOpen)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelBMismatch)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelBPairBusy)
|
||||||
|
return -1;
|
||||||
|
*length_cm = result->un.ge_result.channelBLen;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(result->un.ge_result.channelCShort)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelCOpen)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelCMismatch)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelCPairBusy)
|
||||||
|
return -1;
|
||||||
|
*length_cm = result->un.ge_result.channelCLen;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if(result->un.ge_result.channelDShort)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelDOpen)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelDMismatch)
|
||||||
|
return -1;
|
||||||
|
if(result->un.ge_result.channelDPairBusy)
|
||||||
|
return -1;
|
||||||
|
*length_cm = result->un.ge_result.channelDLen;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _phy_8224_dbCompleted_check(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)phydev->priv;
|
||||||
|
struct phy_device *base_phydev = NULL;
|
||||||
|
struct rtl8224_priv_info *base_priv = NULL;
|
||||||
|
struct phy_device *tmp_phydev = NULL;
|
||||||
|
struct rtl8224_priv_info *tmp_priv = NULL;
|
||||||
|
int phy_addr, loop, ret = 0;
|
||||||
|
|
||||||
|
|
||||||
|
base_phydev = priv->basePort;
|
||||||
|
base_priv = (struct rtl8224_priv_info *)base_phydev->priv;
|
||||||
|
phy_addr = base_phydev->mdio.addr;
|
||||||
|
|
||||||
|
for(loop = 0; loop < RTL8224_PORT_NUM; loop++)
|
||||||
|
{
|
||||||
|
tmp_phydev = mdiobus_get_phy(base_phydev->mdio.bus, (phy_addr + loop));
|
||||||
|
tmp_priv = (struct rtl8224_priv_info *)tmp_phydev->priv;
|
||||||
|
|
||||||
|
if((loop == 0) && (tmp_phydev != base_phydev))
|
||||||
|
{
|
||||||
|
PR_ERR("[%d][loop %d] base port is WRONG!!!",__LINE__,loop);
|
||||||
|
ret = -1;
|
||||||
|
goto db_not_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmp_phydev != base_priv->memberPort[loop])
|
||||||
|
{
|
||||||
|
PR_ERR("[%d][loop %d] member port is WRONG!!!",__LINE__,loop);
|
||||||
|
ret = -2;
|
||||||
|
goto db_not_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmp_priv->port_offset != loop)
|
||||||
|
{
|
||||||
|
PR_ERR("[%d][loop %d] port offset is WRONG!!!",__LINE__,loop);
|
||||||
|
ret = -3;
|
||||||
|
goto db_not_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((tmp_priv->is_basePort != 0) && (loop != 0))
|
||||||
|
{
|
||||||
|
PR_ERR("[%d][loop %d] is_basePort is WRONG!!!",__LINE__,loop);
|
||||||
|
ret = -4;
|
||||||
|
goto db_not_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
db_not_ready:
|
||||||
|
PR_ERR("[%d][loop %d] dbCompleted is NOT Ready!!!",__LINE__,loop);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* updated base port db*/
|
||||||
|
static struct phy_device *phy_8224_basePort_db_updated(struct phy_device *phydev, int *reg_data1, int *reg_data2)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *phy_priv = (struct rtl8224_priv_info *)phydev->priv;
|
||||||
|
|
||||||
|
*reg_data1 = phy_read_mmd(phydev, 30, 0x4);
|
||||||
|
if (*reg_data1 < 0)
|
||||||
|
goto bus_read_error;
|
||||||
|
*reg_data2 = phy_read_mmd(phydev, 30, 0x5);
|
||||||
|
if (*reg_data2 < 0)
|
||||||
|
goto bus_read_error;
|
||||||
|
|
||||||
|
if(*reg_data2 == 0x8224) /* base port match */
|
||||||
|
{
|
||||||
|
phy_priv->basePort = phydev;
|
||||||
|
phy_priv->is_basePort = 1;
|
||||||
|
phy_priv->port_offset = 0;
|
||||||
|
phy_priv->memberPort[RTL8224_BASE_PORT_OFFSET]= phydev;
|
||||||
|
if(*reg_data1 == 0x0)
|
||||||
|
phy_priv->phytype = RTK_PHYLIB_RTL8224;
|
||||||
|
else if(*reg_data1 == 0x7000)
|
||||||
|
phy_priv->phytype = RTK_PHYLIB_RTL8224N;
|
||||||
|
else
|
||||||
|
goto basePort_match_error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phy_priv->is_basePort = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return phydev;
|
||||||
|
bus_read_error:
|
||||||
|
PR_ERR("\n[%s] read error!\n",__FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
basePort_match_error:
|
||||||
|
PR_ERR("\n[%s] base port match error!\n",__FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* updated member port db*/
|
||||||
|
int phy_8224_member_db_updated(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *phy_priv = (struct rtl8224_priv_info *)phydev->priv;
|
||||||
|
struct phy_device *tmp_phydev = NULL;
|
||||||
|
struct rtl8224_priv_info *temp_priv;
|
||||||
|
int index = RTL8224_PORT_NUM;
|
||||||
|
int port_offset = 0;
|
||||||
|
int phy_addr = phydev->mdio.addr;
|
||||||
|
|
||||||
|
/* base port's phy address is the first always, */
|
||||||
|
/* and 4 phy addresses are continuous */
|
||||||
|
while(index > 0)
|
||||||
|
{
|
||||||
|
phy_addr--;
|
||||||
|
index --;
|
||||||
|
tmp_phydev = mdiobus_get_phy(phydev->mdio.bus, phy_addr); /* get other port's phy device by phy address*/
|
||||||
|
temp_priv = (struct rtl8224_priv_info *)tmp_phydev->priv;
|
||||||
|
if(tmp_phydev == NULL)
|
||||||
|
{
|
||||||
|
/* to find next one */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(temp_priv->is_basePort == 1)
|
||||||
|
{
|
||||||
|
/* Record base port*/
|
||||||
|
phy_priv->basePort = tmp_phydev;
|
||||||
|
/* Record member port*/
|
||||||
|
phy_priv->memberPort[RTL8224_BASE_PORT_OFFSET] = tmp_phydev;
|
||||||
|
/* port offset */
|
||||||
|
port_offset = (phydev->mdio.addr - tmp_phydev->mdio.addr);
|
||||||
|
phy_priv->memberPort[port_offset] = phydev;
|
||||||
|
phy_priv->port_offset = port_offset;
|
||||||
|
/* updated base port's member port db */
|
||||||
|
temp_priv->memberPort[port_offset] = phydev;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PR_ERR("\n[%s](PHY addr %d) FAILED!!!\n",__FUNCTION__,phydev->mdio.addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl8224_probe(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = NULL;
|
||||||
|
int reg_data1 = 0, reg_data2 = 0, db_ret = 0, tmp_base = 1;
|
||||||
|
struct phy_device *tmp_phydev = NULL;
|
||||||
|
struct rtl8224_priv_info *tmp_priv;
|
||||||
|
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
priv = kmalloc(sizeof(struct rtl8224_priv_info), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(priv, 0, sizeof(struct rtl8224_priv_info));
|
||||||
|
phydev->priv = priv;
|
||||||
|
|
||||||
|
if (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8224)
|
||||||
|
{
|
||||||
|
tmp_phydev = phy_8224_basePort_db_updated(phydev, ®_data1, ®_data2);
|
||||||
|
/* updated member port db */
|
||||||
|
if(tmp_phydev == NULL)
|
||||||
|
{
|
||||||
|
tmp_base = 0;
|
||||||
|
db_ret = phy_8224_member_db_updated(phydev);
|
||||||
|
if(db_ret)
|
||||||
|
goto match_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto match_error;
|
||||||
|
}
|
||||||
|
tmp_priv = (struct rtl8224_priv_info *)phydev->priv;
|
||||||
|
|
||||||
|
phydev->priv = priv;
|
||||||
|
return 0;
|
||||||
|
match_error:
|
||||||
|
PR_ERR("[%s] probe miss MATCH!!!\n",__FUNCTION__);
|
||||||
|
devm_kfree(&phydev->mdio.dev, priv);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rtl8224_get_features(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
ret = genphy_c45_pma_read_abilities(phydev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
linkmode_or(phydev->supported, phydev->supported, PHY_BASIC_FEATURES);
|
||||||
|
|
||||||
|
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
|
||||||
|
/* not support 10M modes */
|
||||||
|
linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
|
||||||
|
phydev->supported);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rtl8224_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)phydev->priv;
|
||||||
|
struct rtl8224_priv_info *tmp_priv = NULL;
|
||||||
|
int ret = 0, loop = 0;
|
||||||
|
int32 unit = 0;
|
||||||
|
rtk_port_t port;
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
ret = _phy_8224_dbCompleted_check(phydev);
|
||||||
|
if(ret)
|
||||||
|
PR_ERR("\n PHY data base is NOT completed\n");
|
||||||
|
|
||||||
|
if(priv->is_basePort == 1)
|
||||||
|
{
|
||||||
|
PR_INFO("\n Base port (phy_addr %d), execute patch...\n",phydev->mdio.addr);
|
||||||
|
|
||||||
|
for (loop = 0; loop < RTL8224_PORT_NUM; loop++)
|
||||||
|
{
|
||||||
|
if ((port = _phy_8224_get_phydevice_by_offset(unit, phydev, loop)) == NULL)
|
||||||
|
{
|
||||||
|
PR_ERR("\n Offset(%d) PHY device cannot get\n",loop);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmp_priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
|
||||||
|
phy_rtl8224_patch(unit, port, loop);
|
||||||
|
_phy_8224_mdi_reverse_set(port, RTL8224_MDI_PIN_SWAP);
|
||||||
|
|
||||||
|
if ((RTL8224_MDI_PAIR_SWAP) != 0)
|
||||||
|
{
|
||||||
|
_phy_8224_tx_polarity_swap_set(port, RTL8224_MDI_PAIR_SWAP);
|
||||||
|
}
|
||||||
|
_phy_8224_interrupt_init(unit, port);
|
||||||
|
}
|
||||||
|
PR_INFO("\n Base port (phy_addr %d), path completed!\n",phydev->mdio.addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PR_INFO("\n(phy_addr %d) is member port\n", phydev->mdio.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rtl8224_cable_test_start(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 unit = 0;
|
||||||
|
uint32 phyData = 0, speed = 0, duplex = 0;
|
||||||
|
uint32 tryTime = 1000;
|
||||||
|
rtk_enable_t ena;
|
||||||
|
rtk_port_t port = phydev;
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_common_c45_enable_get(unit, port, &ena)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ena == DISABLED)
|
||||||
|
{
|
||||||
|
return RT_ERR_OPER_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the port is link up or not?
|
||||||
|
* Due to bit 2 is LL(latching low), need to read twice to get current status
|
||||||
|
*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0x1, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0x1, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
_phy_8224_common_c45_speedDuplexStatusResReg_get(unit, port, &speed, &duplex);
|
||||||
|
if (phyData & BIT_2)
|
||||||
|
{
|
||||||
|
if (speed == PORT_SPEED_10M)
|
||||||
|
{
|
||||||
|
return RT_ERR_PORT_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA400, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
phyData |= (BIT_9); //[9]=1
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA400, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
osal_time_mdelay(500);
|
||||||
|
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA422, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
phyData &= (~BIT_15); //[15]=0
|
||||||
|
phyData |= (BIT_1); //[1]=1
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA422, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
phyData |= (BIT_4 | BIT_5 | BIT_6 | BIT_7); //[7:4]=0xf
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA422, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
phyData |= (BIT_0); //[0]=0x1
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA422, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA422, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
while((phyData & BIT_15) == 0)
|
||||||
|
{
|
||||||
|
osal_time_mdelay(10);
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA422, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
tryTime--;
|
||||||
|
if(tryTime == 0)
|
||||||
|
return RT_ERR_NOT_FINISH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl8224_cable_test_get_status(struct phy_device *phydev, bool *finished)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 pair = 0, unit = 0, length_cm;
|
||||||
|
rtk_rtctResult_t result;
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
*finished = false;
|
||||||
|
ret = _phy_8224_rtctResult_get(unit, phydev, &result);
|
||||||
|
if(ret == 0)
|
||||||
|
*finished = true;
|
||||||
|
|
||||||
|
for (pair = 0; pair < 4; pair++)
|
||||||
|
{
|
||||||
|
ethnl_cable_test_result(phydev, pair, _phy_8224_cable_test_report_trans(pair, &result));
|
||||||
|
|
||||||
|
if(_phy_8224_cable_test_length_get(pair, &result, &length_cm))
|
||||||
|
ethnl_cable_test_fault_length(phydev, pair, length_cm);
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl8224_get_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, void *data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
rtk_enable_t val = 0;
|
||||||
|
uint32 unit = 0;
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
switch (tuna->id)
|
||||||
|
{
|
||||||
|
case ETHTOOL_PHY_EDPD:
|
||||||
|
RTK_PHYLIB_ERR_CHK(phy_8224_linkDownPowerSavingEnable_get(unit, phydev, &val));
|
||||||
|
*(u16 *)data = (val == DISABLED) ? ETHTOOL_PHY_EDPD_DISABLE : ETHTOOL_PHY_EDPD_DFLT_TX_MSECS;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl8224_set_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, const void *data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
rtk_enable_t val = DISABLED;
|
||||||
|
uint32 unit = 0;
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
switch (tuna->id)
|
||||||
|
{
|
||||||
|
case ETHTOOL_PHY_EDPD:
|
||||||
|
switch (*(const u16 *)data)
|
||||||
|
{
|
||||||
|
case ETHTOOL_PHY_EDPD_DISABLE:
|
||||||
|
val = DISABLED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
val = ENABLED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
RTK_PHYLIB_ERR_CHK(phy_8224_linkDownPowerSavingEnable_set(unit, phydev, val));
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl8224_config_intr(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(_phy_8224_intr_enable(phydev, (phydev->interrupts == PHY_INTERRUPT_ENABLED)? 1 : 0));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl8224_ack_intr(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 status = 0;
|
||||||
|
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(_phy_8224_intr_read_clear(phydev, &status));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
irqreturn_t rtl8224_handle_intr(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
irqreturn_t ret;
|
||||||
|
uint32 status = 0;
|
||||||
|
|
||||||
|
RTL8224_INTERNAL_PORT_CHECK(phydev);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(_phy_8224_intr_read_clear(phydev, &status));
|
||||||
|
if (status & BIT_4)
|
||||||
|
{
|
||||||
|
PR_INFO("[%s,%d] RTK_PHY_INTR_LINK_CHANGE\n", __FUNCTION__, __LINE__);
|
||||||
|
phy_mac_interrupt(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
13
sources/rtk-gp3000/src/hal/phy/rtk_phy_rtl8224.h
Normal file
13
sources/rtk-gp3000/src/hal/phy/rtk_phy_rtl8224.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
|
||||||
|
extern int rtl8224_probe(struct phy_device *phydev);
|
||||||
|
extern int rtl8224_get_features(struct phy_device *phydev);
|
||||||
|
extern int rtl8224_config_init(struct phy_device *phydev);
|
||||||
|
extern int rtl8224_cable_test_start(struct phy_device *phydev);
|
||||||
|
extern int rtl8224_cable_test_get_status(struct phy_device *phydev, bool *finished);
|
||||||
|
extern int rtl8224_get_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, void *data);
|
||||||
|
extern int rtl8224_set_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, const void *data);
|
||||||
|
extern int rtl8224_config_intr(struct phy_device *phydev);
|
||||||
|
extern int rtl8224_ack_intr(struct phy_device *phydev);
|
||||||
|
extern irqreturn_t rtl8224_handle_intr(struct phy_device *phydev);
|
||||||
|
|
||||||
117
sources/rtk-gp3000/src/hal/phy/rtk_phylib.c
Normal file
117
sources/rtk-gp3000/src/hal/phy/rtk_phylib.c
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
#include <linux/phy.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* OSAL */
|
||||||
|
|
||||||
|
void rtk_phylib_mdelay(uint32 msec)
|
||||||
|
{
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
mdelay(msec);
|
||||||
|
#else
|
||||||
|
osal_time_mdelay(msec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rtk_phylib_udelay(uint32 usec)
|
||||||
|
{
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
if (1000 <= usec)
|
||||||
|
{
|
||||||
|
mdelay(usec/1000);
|
||||||
|
usec = usec % 1000;
|
||||||
|
}
|
||||||
|
udelay(usec);
|
||||||
|
#else
|
||||||
|
osal_time_udelay(usec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 rtk_phylib_time_usecs_get(uint32 *pUsec)
|
||||||
|
{
|
||||||
|
struct timespec64 ts;
|
||||||
|
|
||||||
|
if(NULL == pUsec)
|
||||||
|
return RTK_PHYLIB_ERR_INPUT;
|
||||||
|
|
||||||
|
ktime_get_ts64(&ts);
|
||||||
|
*pUsec = ((ts.tv_sec * USEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_USEC));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register Access APIs */
|
||||||
|
int32 rtk_phylib_mmd_write(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
mask = UINT32_BITS_MASK(msb,lsb);
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
ret = phy_modify_mmd(phydev, mmd, reg, mask, (data << lsb));
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
uint32 rData = 0, wData = 0;
|
||||||
|
if ((msb != 15) || (lsb != 0))
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(phydev->unit, phydev->port, page, reg, &rData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
wData = REG32_FIELD_SET(rData, data, lsb, mask);
|
||||||
|
ret = phy_common_general_reg_mmd_set(phydev->unit, phydev->port, page, reg, wData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 rtk_phylib_mmd_read(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
mask = UINT32_BITS_MASK(msb,lsb);
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
rData = phy_read_mmd(phydev, mmd, reg);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
ret = phy_common_general_reg_mmd_get(phydev->unit, phydev->port, page, reg, &rData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*pData = REG32_FIELD_GET(rData, lsb, mask);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function Driver */
|
||||||
|
|
||||||
|
int32 rtk_phylib_c45_power_normal(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 1, 0, 11, 11, 0));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 rtk_phylib_c45_power_low(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 1, 0, 11, 11, 1));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 rtk_phylib_c45_pcs_loopback(rtk_phydev *phydev, uint32 enable)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 3, 0, 14, 14, (enable == 0) ? 0 : 1));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
389
sources/rtk-gp3000/src/hal/phy/rtk_phylib.h
Normal file
389
sources/rtk-gp3000/src/hal/phy/rtk_phylib.h
Normal file
|
|
@ -0,0 +1,389 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RTK_PHYLIB_H
|
||||||
|
#define __RTK_PHYLIB_H
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include "type.h"
|
||||||
|
#include "rtk_phylib_def.h"
|
||||||
|
#else
|
||||||
|
//#include SDK headers
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEBUG)
|
||||||
|
#define MACSEC_DBG_PRINT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#define PR_INFO(_fmt, _args...) pr_info(_fmt, ##_args)
|
||||||
|
#define PR_DBG(_fmt, _args...) pr_debug(_fmt, ##_args)
|
||||||
|
#define PR_ERR(_fmt, _args...) pr_err("ERROR: "_fmt, ##_args)
|
||||||
|
|
||||||
|
#define RTK_PHYLIB_ERR_FAILED (-EPERM)
|
||||||
|
#define RTK_PHYLIB_ERR_INPUT (-EINVAL)
|
||||||
|
#define RTK_PHYLIB_ERR_EXCEEDS_CAPACITY (-ENOSPC)
|
||||||
|
#define RTK_PHYLIB_ERR_TIMEOUT (-ETIME)
|
||||||
|
#define RTK_PHYLIB_ERR_ENTRY_NOTFOUND (-ENODATA)
|
||||||
|
#define RTK_PHYLIB_ERR_OPER_DENIED (-EACCES)
|
||||||
|
#else
|
||||||
|
#define PR_INFO(_fmt, _args...) RT_LOG(LOG_INFO, (MOD_HAL|MOD_PHY), _fmt, ##_args)
|
||||||
|
#define PR_DBG(_fmt, _args...) RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PHY), _fmt, ##_args)
|
||||||
|
#define PR_ERR(_fmt, _args...) RT_LOG(LOG_MAJOR_ERR, (MOD_HAL|MOD_PHY), _fmt, ##_args)
|
||||||
|
|
||||||
|
#define RTK_PHYLIB_ERR_FAILED (RT_ERR_FAILED)
|
||||||
|
#define RTK_PHYLIB_ERR_INPUT (RT_ERR_INPUT)
|
||||||
|
#define RTK_PHYLIB_ERR_EXCEEDS_CAPACITY (RT_ERR_EXCEEDS_CAPACITY)
|
||||||
|
#define RTK_PHYLIB_ERR_TIMEOUT (RT_ERR_BUSYWAIT_TIMEOUT)
|
||||||
|
#define RTK_PHYLIB_ERR_ENTRY_NOTFOUND (RT_ERR_ENTRY_NOTFOUND)
|
||||||
|
#define RTK_PHYLIB_ERR_OPER_DENIED (RT_ERR_OPER_DENIED)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum rtk_phylib_phy_e
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_NONE,
|
||||||
|
RTK_PHYLIB_RTL8261N,
|
||||||
|
RTK_PHYLIB_RTL8264B,
|
||||||
|
RTK_PHYLIB_RTL8251L,
|
||||||
|
RTK_PHYLIB_RTL8254B,
|
||||||
|
RTK_PHYLIB_RTL8224,
|
||||||
|
RTK_PHYLIB_RTL8224N,
|
||||||
|
RTK_PHYLIB_END
|
||||||
|
} rtk_phylib_phy_t;
|
||||||
|
|
||||||
|
typedef enum rtk_port_duplex_e
|
||||||
|
{
|
||||||
|
PORT_HALF_DUPLEX = 0,
|
||||||
|
PORT_FULL_DUPLEX,
|
||||||
|
PORT_DUPLEX_END
|
||||||
|
} rtk_port_duplex_t;
|
||||||
|
|
||||||
|
typedef enum rtk_port_speed_e
|
||||||
|
{
|
||||||
|
PORT_SPEED_10M = 0,
|
||||||
|
PORT_SPEED_100M,
|
||||||
|
PORT_SPEED_500M,
|
||||||
|
PORT_SPEED_1000M,
|
||||||
|
PORT_SPEED_2_5G_LITE,
|
||||||
|
PORT_SPEED_2G,
|
||||||
|
PORT_SPEED_2_5G,
|
||||||
|
PORT_SPEED_5G_LITE,
|
||||||
|
PORT_SPEED_5G,
|
||||||
|
PORT_SPEED_10G_LITE,
|
||||||
|
PORT_SPEED_10G,
|
||||||
|
PORT_SPEED_25G,
|
||||||
|
PORT_SPEED_40G,
|
||||||
|
PORT_SPEED_50G,
|
||||||
|
PORT_SPEED_100G,
|
||||||
|
PORT_SPEED_END
|
||||||
|
} rtk_port_speed_t;
|
||||||
|
|
||||||
|
typedef enum rtk_port_lite_mode_e
|
||||||
|
{
|
||||||
|
PORT_LITE_1G,
|
||||||
|
PORT_LITE_2P5G,
|
||||||
|
PORT_LITE_5G,
|
||||||
|
PORT_LITE_10G,
|
||||||
|
PORT_LITE_END
|
||||||
|
} rtk_port_lite_mode_t;
|
||||||
|
|
||||||
|
/* RTCT result Status of one channel */
|
||||||
|
typedef struct rtk_rtctChannelStatus_s
|
||||||
|
{
|
||||||
|
uint32 channelShort;
|
||||||
|
uint32 channelOpen;
|
||||||
|
uint32 channelLowMismatch;
|
||||||
|
uint32 channelHighMismatch;
|
||||||
|
uint32 channelCrossoverA;
|
||||||
|
uint32 channelCrossoverB;
|
||||||
|
uint32 channelCrossoverC;
|
||||||
|
uint32 channelCrossoverD;
|
||||||
|
uint32 channelLen;
|
||||||
|
} rtk_rtctChannelStatus_t;
|
||||||
|
|
||||||
|
/* result of RTCT test */
|
||||||
|
typedef struct rtk_rtctResult_s
|
||||||
|
{
|
||||||
|
rtk_port_speed_t linkType;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct fe_result_s
|
||||||
|
{
|
||||||
|
uint32 isRxShort;
|
||||||
|
uint32 isTxShort;
|
||||||
|
uint32 isRxOpen;
|
||||||
|
uint32 isTxOpen;
|
||||||
|
uint32 isRxMismatch;
|
||||||
|
uint32 isTxMismatch;
|
||||||
|
uint32 isRxLinedriver;
|
||||||
|
uint32 isTxLinedriver;
|
||||||
|
uint32 rxLen;
|
||||||
|
uint32 txLen;
|
||||||
|
} fe_result;
|
||||||
|
|
||||||
|
struct ge_result_s
|
||||||
|
{
|
||||||
|
uint32 channelAShort;
|
||||||
|
uint32 channelBShort;
|
||||||
|
uint32 channelCShort;
|
||||||
|
uint32 channelDShort;
|
||||||
|
|
||||||
|
uint32 channelAOpen;
|
||||||
|
uint32 channelBOpen;
|
||||||
|
uint32 channelCOpen;
|
||||||
|
uint32 channelDOpen;
|
||||||
|
|
||||||
|
uint32 channelAMismatch;
|
||||||
|
uint32 channelBMismatch;
|
||||||
|
uint32 channelCMismatch;
|
||||||
|
uint32 channelDMismatch;
|
||||||
|
|
||||||
|
uint32 channelALinedriver;
|
||||||
|
uint32 channelBLinedriver;
|
||||||
|
uint32 channelCLinedriver;
|
||||||
|
uint32 channelDLinedriver;
|
||||||
|
|
||||||
|
uint32 channelAHiImpedance;
|
||||||
|
uint32 channelBHiImpedance;
|
||||||
|
uint32 channelCHiImpedance;
|
||||||
|
uint32 channelDHiImpedance;
|
||||||
|
|
||||||
|
uint32 channelACross;
|
||||||
|
uint32 channelBCross;
|
||||||
|
uint32 channelCCross;
|
||||||
|
uint32 channelDCross;
|
||||||
|
|
||||||
|
uint32 channelAPartialCross;
|
||||||
|
uint32 channelBPartialCross;
|
||||||
|
uint32 channelCPartialCross;
|
||||||
|
uint32 channelDPartialCross;
|
||||||
|
|
||||||
|
/* when paire is busy, RTCT shall re-do by calling start API again. */
|
||||||
|
uint32 channelAPairBusy;
|
||||||
|
uint32 channelBPairBusy;
|
||||||
|
uint32 channelCPairBusy;
|
||||||
|
uint32 channelDPairBusy;
|
||||||
|
|
||||||
|
uint32 channelALen;
|
||||||
|
uint32 channelBLen;
|
||||||
|
uint32 channelCLen;
|
||||||
|
uint32 channelDLen;
|
||||||
|
} ge_result;
|
||||||
|
|
||||||
|
struct channels_result_s
|
||||||
|
{
|
||||||
|
rtk_rtctChannelStatus_t a;
|
||||||
|
rtk_rtctChannelStatus_t b;
|
||||||
|
rtk_rtctChannelStatus_t c;
|
||||||
|
rtk_rtctChannelStatus_t d;
|
||||||
|
} channels_result;
|
||||||
|
} un;
|
||||||
|
} rtk_rtctResult_t;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
typedef struct phy_device rtk_phydev;
|
||||||
|
#else
|
||||||
|
struct rtk_phy_dev_s
|
||||||
|
{
|
||||||
|
uint32 unit;
|
||||||
|
rtk_port_t port;
|
||||||
|
|
||||||
|
struct rtk_phy_priv *priv;
|
||||||
|
};
|
||||||
|
typedef struct rtk_phy_dev_s rtk_phydev;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTK_PHYLIB_ERR_CHK(op)\
|
||||||
|
do {\
|
||||||
|
if ((ret = (op)) != 0)\
|
||||||
|
return ret;\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define RTK_PHYLIB_VAL_TO_BYTE_ARRAY(_val, _valbytes, _array, _start, _bytes)\
|
||||||
|
do{\
|
||||||
|
uint32 _i = 0;\
|
||||||
|
for (_i = 0; _i < _bytes; _i++)\
|
||||||
|
_array[(_bytes-1)-_i] = (_val >> (8* (_valbytes - _i - 1)));\
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
#define RTK_PHYLIB_BYTE_ARRAY_TO_VAL(_val, _array, _start, _bytes)\
|
||||||
|
do{\
|
||||||
|
uint32 _i = 0;\
|
||||||
|
_val = 0;\
|
||||||
|
for (_i = 0; _i < _bytes; _i++)\
|
||||||
|
_val = (_val << 8) | _array[(_bytes-1)-_i];\
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
/* RTCT */
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_NORMAL (0)
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_UNKNOWN (1u << 0)
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_SHORT (1u << 1)
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_OPEN (1u << 2)
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_MISMATCH (1u << 3)
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_CROSS (1u << 4)
|
||||||
|
#define RTK_PHYLIB_CABLE_STATUS_INTER_PAIR_SHORT (1u << 5)
|
||||||
|
|
||||||
|
typedef struct rtk_rtct_channel_result_s
|
||||||
|
{
|
||||||
|
uint32 cable_status;
|
||||||
|
uint32 length_cm;
|
||||||
|
} rtk_rtct_channel_result_t;
|
||||||
|
|
||||||
|
/* MACsec */
|
||||||
|
typedef struct rtk_macsec_sa_info_s
|
||||||
|
{
|
||||||
|
uint8 ssci[4];
|
||||||
|
} rtk_macsec_sa_info_t;
|
||||||
|
|
||||||
|
#define MACSEC_SA_IS_USED(macsec_port_info_ptr, dir, sa_id) (macsec_port_info_ptr->sa_used[dir][sa_id])
|
||||||
|
#define MACSEC_SC_IS_USED(macsec_port_info_ptr, dir, sc_id) (macsec_port_info_ptr->sc_used[dir][sc_id])
|
||||||
|
|
||||||
|
#define MACSEC_SA_IS_CLEAR(macsec_port_info_ptr, dir, sa_id) (!MACSEC_SA_IS_USED(macsec_port_info_ptr, dir, sa_id))
|
||||||
|
#define MACSEC_SC_IS_CLEAR(macsec_port_info_ptr, dir, sc_id) (!MACSEC_SC_IS_USED(macsec_port_info_ptr, dir, sc_id))
|
||||||
|
|
||||||
|
#define MACSEC_SA_SET_USED(macsec_port_info_ptr, dir, sa_id) do { macsec_port_info_ptr->sa_used[dir][sa_id] = 1; }while(0)
|
||||||
|
#define MACSEC_SC_SET_USED(macsec_port_info_ptr, dir, sc_id) do { macsec_port_info_ptr->sc_used[dir][sc_id] = 1; }while(0)
|
||||||
|
|
||||||
|
#define MACSEC_SA_UNSET_USED(macsec_port_info_ptr, dir, sa_id) do { macsec_port_info_ptr->sa_used[dir][sa_id] = 0; }while(0)
|
||||||
|
#define MACSEC_SC_UNSET_USED(macsec_port_info_ptr, dir, sc_id) do { macsec_port_info_ptr->sc_used[dir][sc_id] = 0; }while(0)
|
||||||
|
|
||||||
|
#define MACSEC_SA_MAX(macsec_port_info_ptr) macsec_port_info_ptr->max_sa_num
|
||||||
|
#define MACSEC_SC_MAX(macsec_port_info_ptr) macsec_port_info_ptr->max_sc_num
|
||||||
|
#define MACSEC_SC_CS(macsec_port_info_ptr, dir, sc_id) macsec_port_info_ptr->cipher_suite[dir][sc_id]
|
||||||
|
#define MACSEC_SC_MATCH(macsec_port_info_ptr, dir, sc_id) macsec_port_info_ptr->flow_match[dir][sc_id]
|
||||||
|
#define MACSEC_SA_SSCI(macsec_port_info_ptr, sa_id) macsec_port_info_ptr->sa_info[sa_id].ssci
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_port_stats_s
|
||||||
|
{
|
||||||
|
uint64 InPktsUntagged;
|
||||||
|
uint64 InPktsNoTag;
|
||||||
|
uint64 InPktsBadTag;
|
||||||
|
uint64 InPktsUnknownSCI;
|
||||||
|
uint64 InPktsNoSCI;
|
||||||
|
uint64 OutPktsUntagged;
|
||||||
|
}rtk_macsec_port_stats_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_txsa_stats_s
|
||||||
|
{
|
||||||
|
uint64 OutPktsTooLong;
|
||||||
|
uint64 OutOctetsProtectedEncrypted;
|
||||||
|
uint64 OutPktsProtectedEncrypted;
|
||||||
|
}rtk_macsec_txsa_stats_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_rxsa_stats_s
|
||||||
|
{
|
||||||
|
uint64 InPktsUnusedSA;
|
||||||
|
uint64 InPktsNotUsingSA;
|
||||||
|
uint64 InPktsUnchecked;
|
||||||
|
uint64 InPktsDelayed;
|
||||||
|
uint64 InPktsLate;
|
||||||
|
uint64 InPktsOK;
|
||||||
|
uint64 InPktsInvalid;
|
||||||
|
uint64 InPktsNotValid;
|
||||||
|
uint64 InOctetsDecryptedValidated;
|
||||||
|
}rtk_macsec_rxsa_stats_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_port_info_s
|
||||||
|
{
|
||||||
|
int32 (*macsec_reg_get)(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData);
|
||||||
|
int32 (*macsec_reg_set)(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 reg, uint8 msb, uint8 lsb, uint32 data);
|
||||||
|
|
||||||
|
uint16 sa_gen_seq;
|
||||||
|
uint32 max_sa_num;
|
||||||
|
uint32 max_sc_num;
|
||||||
|
rtk_macsec_cipher_t cipher_suite[RTK_MACSEC_DIR_END][RTK_MAX_MACSEC_SC_PER_PORT];
|
||||||
|
uint32 flow_match[RTK_MACSEC_DIR_END][RTK_MAX_MACSEC_SC_PER_PORT];
|
||||||
|
uint8 sc_used[RTK_MACSEC_DIR_END][RTK_MAX_MACSEC_SC_PER_PORT];
|
||||||
|
uint8 sa_used[RTK_MACSEC_DIR_END][RTK_MAX_MACSEC_SA_PER_PORT];
|
||||||
|
rtk_macsec_sa_info_t sa_info[RTK_MAX_MACSEC_SA_PER_PORT];
|
||||||
|
uint64 sci[RTK_MACSEC_DIR_END][RTK_MAX_MACSEC_SC_PER_PORT];
|
||||||
|
|
||||||
|
rtk_macsec_port_stats_t port_stats;
|
||||||
|
rtk_macsec_txsa_stats_t *txsa_stats[RTK_MAX_MACSEC_SA_PER_PORT];
|
||||||
|
rtk_macsec_rxsa_stats_t *rxsa_stats[RTK_MAX_MACSEC_SA_PER_PORT];
|
||||||
|
} rtk_macsec_port_info_t;
|
||||||
|
|
||||||
|
struct rtk_phy_priv {
|
||||||
|
rtk_phylib_phy_t phytype;
|
||||||
|
uint8 isBasePort;
|
||||||
|
rt_phy_patch_db_t *patch;
|
||||||
|
rtk_macsec_port_info_t *macsec;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* OSAL */
|
||||||
|
void rtk_phylib_mdelay(uint32 msec);
|
||||||
|
void rtk_phylib_udelay(uint32 usec);
|
||||||
|
#define rtk_phylib_strlen strlen
|
||||||
|
#define rtk_phylib_strcmp strcmp
|
||||||
|
#define rtk_phylib_strcpy strcpy
|
||||||
|
#define rtk_phylib_strncpy strncpy
|
||||||
|
#define rtk_phylib_strcat strcat
|
||||||
|
#define rtk_phylib_strchr strchr
|
||||||
|
#define rtk_phylib_memset memset
|
||||||
|
#define rtk_phylib_memcpy memcpy
|
||||||
|
#define rtk_phylib_memcmp memcmp
|
||||||
|
#define rtk_phylib_strdup strdup
|
||||||
|
#define rtk_phylib_strncmp strncmp
|
||||||
|
#define rtk_phylib_strstr strstr
|
||||||
|
#define rtk_phylib_strtok strtok
|
||||||
|
#define rtk_phylib_strtok_r strtok_r
|
||||||
|
#define rtk_phylib_toupper toupper
|
||||||
|
|
||||||
|
int rtk_phylib_time_usecs_get(uint32 *pUsec);
|
||||||
|
#ifndef WAIT_COMPLETE_VAR
|
||||||
|
#define WAIT_COMPLETE_VAR() \
|
||||||
|
uint32 _t, _now, _t_wait=0, _timeout; \
|
||||||
|
int32 _chkCnt=0;
|
||||||
|
|
||||||
|
#define WAIT_COMPLETE(_timeout_us) \
|
||||||
|
_timeout = _timeout_us; \
|
||||||
|
for(rtk_phylib_time_usecs_get(&_t),rtk_phylib_time_usecs_get(&_now),_t_wait=0,_chkCnt=0 ; \
|
||||||
|
(_t_wait <= _timeout); \
|
||||||
|
rtk_phylib_time_usecs_get(&_now), _chkCnt++, _t_wait += ((_now >= _t) ? (_now - _t) : (0xFFFFFFFF - _t + _now)),_t = _now \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define WAIT_COMPLETE_IS_TIMEOUT() (_t_wait > _timeout)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Register Access APIs */
|
||||||
|
int32 rtk_phylib_mmd_write(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 data);
|
||||||
|
int32 rtk_phylib_mmd_read(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData);
|
||||||
|
|
||||||
|
/* Function Driver */
|
||||||
|
int32 rtk_phylib_c45_power_normal(rtk_phydev *phydev);
|
||||||
|
int32 rtk_phylib_c45_power_low(rtk_phydev *phydev);
|
||||||
|
int32 rtk_phylib_c45_pcs_loopback(rtk_phydev *phydev, uint32 enable);
|
||||||
|
|
||||||
|
/* MACsec*/
|
||||||
|
int32 rtk_phylib_macsec_init(rtk_phydev *phydev);
|
||||||
|
int32 rtk_phylib_macsec_enable_get(rtk_phydev *phydev, uint32 *pEna);
|
||||||
|
int32 rtk_phylib_macsec_enable_set(rtk_phydev *phydev, uint32 ena);
|
||||||
|
|
||||||
|
int32 rtk_phylib_macsec_sc_create(rtk_phydev *phydev, rtk_macsec_dir_t dir, rtk_macsec_sc_t *pSc, uint32 *pSc_id, uint8 active);
|
||||||
|
int32 rtk_phylib_macsec_sc_update(rtk_phydev *phydev, rtk_macsec_dir_t dir, rtk_macsec_sc_t *pSc, uint32 *pSc_id, uint8 active);
|
||||||
|
int32 rtk_phylib_macsec_sc_del(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 sc_id);
|
||||||
|
int32 rtk_phylib_macsec_sci_to_scid(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint64 sci, uint32 *sc_id);
|
||||||
|
int32 rtk_phylib_macsec_sc_status_get(rtk_phydev *phydev, rtk_macsec_dir_t dir,uint32 sc_id, rtk_macsec_sc_status_t *pSc_status);
|
||||||
|
int32 rtk_phylib_macsec_sc_get(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 sc_id, rtk_macsec_sc_t *pSc);
|
||||||
|
|
||||||
|
int32 rtk_phylib_macsec_sa_activate(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 sc_id, rtk_macsec_an_t an);
|
||||||
|
int32 rtk_phylib_macsec_rxsa_disable(rtk_phydev *phydev, uint32 rxsc_id, rtk_macsec_an_t an);
|
||||||
|
int32 rtk_phylib_macsec_txsa_disable(rtk_phydev *phydev, uint32 txsc_id);
|
||||||
|
int32 rtk_phylib_macsec_sa_create(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 sc_id, rtk_macsec_an_t an, rtk_macsec_sa_t *pSa);
|
||||||
|
int32 rtk_phylib_macsec_sa_get(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 sc_id, rtk_macsec_an_t an, rtk_macsec_sa_t *pSa);
|
||||||
|
int32 rtk_phylib_macsec_sa_del(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 sc_id, rtk_macsec_an_t an);
|
||||||
|
|
||||||
|
int32 rtk_phylib_macsec_stat_port_get(rtk_phydev *phydev, rtk_macsec_stat_t stat, uint64 *pCnt);
|
||||||
|
int32 rtk_phylib_macsec_stat_txsa_get(rtk_phydev *phydev, uint32 sc_id, rtk_macsec_an_t an, rtk_macsec_txsa_stat_t stat, uint64 *pCnt);
|
||||||
|
int32 rtk_phylib_macsec_stat_rxsa_get(rtk_phydev *phydev, uint32 sc_id, rtk_macsec_an_t an, rtk_macsec_rxsa_stat_t stat, uint64 *pCnt);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __RTK_PHYLIB_H */
|
||||||
421
sources/rtk-gp3000/src/hal/phy/rtk_phylib_def.h
Normal file
421
sources/rtk-gp3000/src/hal/phy/rtk_phylib_def.h
Normal file
|
|
@ -0,0 +1,421 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RTK_PHYLIB_DEF_H
|
||||||
|
#define __RTK_PHYLIB_DEF_H
|
||||||
|
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
#define PHY_C22_MMD_PAGE 0x0A41
|
||||||
|
#define PHY_C22_MMD_DEV_REG 13
|
||||||
|
#define PHY_C22_MMD_ADD_REG 14
|
||||||
|
|
||||||
|
/* MDIO Manageable Device(MDD) address*/
|
||||||
|
#define PHY_MMD_PMAPMD 1
|
||||||
|
#define PHY_MMD_PCS 3
|
||||||
|
#define PHY_MMD_AN 7
|
||||||
|
#define PHY_MMD_VEND1 30 /* Vendor specific 1 */
|
||||||
|
#define PHY_MMD_VEND2 31 /* Vendor specific 2 */
|
||||||
|
|
||||||
|
#define BIT_0 0x00000001U
|
||||||
|
#define BIT_1 0x00000002U
|
||||||
|
#define BIT_2 0x00000004U
|
||||||
|
#define BIT_3 0x00000008U
|
||||||
|
#define BIT_4 0x00000010U
|
||||||
|
#define BIT_5 0x00000020U
|
||||||
|
#define BIT_6 0x00000040U
|
||||||
|
#define BIT_7 0x00000080U
|
||||||
|
#define BIT_8 0x00000100U
|
||||||
|
#define BIT_9 0x00000200U
|
||||||
|
#define BIT_10 0x00000400U
|
||||||
|
#define BIT_11 0x00000800U
|
||||||
|
#define BIT_12 0x00001000U
|
||||||
|
#define BIT_13 0x00002000U
|
||||||
|
#define BIT_14 0x00004000U
|
||||||
|
#define BIT_15 0x00008000U
|
||||||
|
#define BIT_16 0x00010000U
|
||||||
|
#define BIT_17 0x00020000U
|
||||||
|
#define BIT_18 0x00040000U
|
||||||
|
#define BIT_19 0x00080000U
|
||||||
|
#define BIT_20 0x00100000U
|
||||||
|
#define BIT_21 0x00200000U
|
||||||
|
#define BIT_22 0x00400000U
|
||||||
|
#define BIT_23 0x00800000U
|
||||||
|
#define BIT_24 0x01000000U
|
||||||
|
#define BIT_25 0x02000000U
|
||||||
|
#define BIT_26 0x04000000U
|
||||||
|
#define BIT_27 0x08000000U
|
||||||
|
#define BIT_28 0x10000000U
|
||||||
|
#define BIT_29 0x20000000U
|
||||||
|
#define BIT_30 0x40000000U
|
||||||
|
#define BIT_31 0x80000000U
|
||||||
|
|
||||||
|
#define MASK_1_BITS (BIT_1 - 1)
|
||||||
|
#define MASK_2_BITS (BIT_2 - 1)
|
||||||
|
#define MASK_3_BITS (BIT_3 - 1)
|
||||||
|
#define MASK_4_BITS (BIT_4 - 1)
|
||||||
|
#define MASK_5_BITS (BIT_5 - 1)
|
||||||
|
#define MASK_6_BITS (BIT_6 - 1)
|
||||||
|
#define MASK_7_BITS (BIT_7 - 1)
|
||||||
|
#define MASK_8_BITS (BIT_8 - 1)
|
||||||
|
#define MASK_9_BITS (BIT_9 - 1)
|
||||||
|
#define MASK_10_BITS (BIT_10 - 1)
|
||||||
|
#define MASK_11_BITS (BIT_11 - 1)
|
||||||
|
#define MASK_12_BITS (BIT_12 - 1)
|
||||||
|
#define MASK_13_BITS (BIT_13 - 1)
|
||||||
|
#define MASK_14_BITS (BIT_14 - 1)
|
||||||
|
#define MASK_15_BITS (BIT_15 - 1)
|
||||||
|
#define MASK_16_BITS (BIT_16 - 1)
|
||||||
|
#define MASK_17_BITS (BIT_17 - 1)
|
||||||
|
#define MASK_18_BITS (BIT_18 - 1)
|
||||||
|
#define MASK_19_BITS (BIT_19 - 1)
|
||||||
|
#define MASK_20_BITS (BIT_20 - 1)
|
||||||
|
#define MASK_21_BITS (BIT_21 - 1)
|
||||||
|
#define MASK_22_BITS (BIT_22 - 1)
|
||||||
|
#define MASK_23_BITS (BIT_23 - 1)
|
||||||
|
#define MASK_24_BITS (BIT_24 - 1)
|
||||||
|
#define MASK_25_BITS (BIT_25 - 1)
|
||||||
|
#define MASK_26_BITS (BIT_26 - 1)
|
||||||
|
#define MASK_27_BITS (BIT_27 - 1)
|
||||||
|
#define MASK_28_BITS (BIT_28 - 1)
|
||||||
|
#define MASK_29_BITS (BIT_29 - 1)
|
||||||
|
#define MASK_30_BITS (BIT_30 - 1)
|
||||||
|
#define MASK_31_BITS (BIT_31 - 1)
|
||||||
|
|
||||||
|
#define REG32_FIELD_SET(_data, _val, _fOffset, _fMask) ((_data & ~(_fMask)) | ((_val << (_fOffset)) & (_fMask)))
|
||||||
|
#define REG32_FIELD_GET(_data, _fOffset, _fMask) ((_data & (_fMask)) >> (_fOffset))
|
||||||
|
#define UINT32_BITS_MASK(_mBit, _lBit) ((0xFFFFFFFF >> (31 - _mBit)) ^ ((1 << _lBit) - 1))
|
||||||
|
|
||||||
|
typedef struct phy_device * rtk_port_t;
|
||||||
|
|
||||||
|
#if 1 /* ss\sdk\include\hal\phy\phydef.h */
|
||||||
|
/* unified patch format */
|
||||||
|
typedef enum rtk_phypatch_type_e
|
||||||
|
{
|
||||||
|
PHY_PATCH_TYPE_NONE = 0,
|
||||||
|
PHY_PATCH_TYPE_TOP = 1,
|
||||||
|
PHY_PATCH_TYPE_SDS,
|
||||||
|
PHY_PATCH_TYPE_AFE,
|
||||||
|
PHY_PATCH_TYPE_UC,
|
||||||
|
PHY_PATCH_TYPE_UC2,
|
||||||
|
PHY_PATCH_TYPE_NCTL0,
|
||||||
|
PHY_PATCH_TYPE_NCTL1,
|
||||||
|
PHY_PATCH_TYPE_NCTL2,
|
||||||
|
PHY_PATCH_TYPE_ALGXG,
|
||||||
|
PHY_PATCH_TYPE_ALG1G,
|
||||||
|
PHY_PATCH_TYPE_NORMAL,
|
||||||
|
PHY_PATCH_TYPE_DATARAM,
|
||||||
|
PHY_PATCH_TYPE_RTCT,
|
||||||
|
PHY_PATCH_TYPE_END
|
||||||
|
} rtk_phypatch_type_t;
|
||||||
|
|
||||||
|
#define RTK_PATCH_TYPE_FLOW(_id) (PHY_PATCH_TYPE_END + _id)
|
||||||
|
#define RTK_PATCH_TYPE_FLOWID_MAX PHY_PATCH_TYPE_END
|
||||||
|
#define RTK_PATCH_SEQ_MAX ( PHY_PATCH_TYPE_END + RTK_PATCH_TYPE_FLOWID_MAX -1)
|
||||||
|
|
||||||
|
/* Interrupt */
|
||||||
|
/* PHY Interrupt Status */
|
||||||
|
#define RTK_PHY_INTR_NEXT_PAGE_RECV (BIT_0)
|
||||||
|
#define RTK_PHY_INTR_AN_COMPLETE (BIT_1)
|
||||||
|
#define RTK_PHY_INTR_LINK_CHANGE (BIT_2)
|
||||||
|
#define RTK_PHY_INTR_ALDPS_STATE_CHANGE (BIT_3)
|
||||||
|
#define RTK_PHY_INTR_RLFD (BIT_4)
|
||||||
|
#define RTK_PHY_INTR_TM_LOW (BIT_5)
|
||||||
|
#define RTK_PHY_INTR_TM_HIGH (BIT_6)
|
||||||
|
#define RTK_PHY_INTR_FATAL_ERROR (BIT_7)
|
||||||
|
#define RTK_PHY_INTR_MACSEC (BIT_8)
|
||||||
|
#define RTK_PHY_INTR_PTP1588 (BIT_9)
|
||||||
|
#define RTK_PHY_INTR_WOL (BIT_10)
|
||||||
|
|
||||||
|
typedef struct rtk_hwpatch_s
|
||||||
|
{
|
||||||
|
uint8 patch_op;
|
||||||
|
uint8 portmask;
|
||||||
|
uint16 pagemmd;
|
||||||
|
uint16 addr;
|
||||||
|
uint8 msb;
|
||||||
|
uint8 lsb;
|
||||||
|
uint16 data;
|
||||||
|
uint8 compare_op;
|
||||||
|
uint16 sram_p;
|
||||||
|
uint16 sram_rr;
|
||||||
|
uint16 sram_rw;
|
||||||
|
uint16 sram_a;
|
||||||
|
} rtk_hwpatch_t;
|
||||||
|
|
||||||
|
typedef struct rtk_hwpatch_data_s
|
||||||
|
{
|
||||||
|
rtk_hwpatch_t *conf;
|
||||||
|
uint32 size;
|
||||||
|
} rtk_hwpatch_data_t;
|
||||||
|
|
||||||
|
typedef struct rtk_hwpatch_seq_s
|
||||||
|
{
|
||||||
|
uint8 patch_type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
rtk_hwpatch_data_t data;
|
||||||
|
uint8 flow_id;
|
||||||
|
} patch;
|
||||||
|
} rtk_hwpatch_seq_t;
|
||||||
|
|
||||||
|
typedef struct rt_phy_patch_db_s
|
||||||
|
{
|
||||||
|
/* patch operation */
|
||||||
|
int32 (*fPatch_op)(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_hwpatch_t *pPatch_data, uint8 patch_mode);
|
||||||
|
int32 (*fPatch_flow)(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_flow, uint8 patch_mode);
|
||||||
|
|
||||||
|
/* patch data */
|
||||||
|
rtk_hwpatch_seq_t seq_table[RTK_PATCH_SEQ_MAX];
|
||||||
|
rtk_hwpatch_seq_t cmp_table[RTK_PATCH_SEQ_MAX];
|
||||||
|
|
||||||
|
} rt_phy_patch_db_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTK_HWPATCH_OP_UNKNOWN 0
|
||||||
|
#define RTK_HWPATCH_OP_SDS 1
|
||||||
|
#define RTK_HWPATCH_OP_PHY 2
|
||||||
|
#define RTK_HWPATCH_OP_PHYW 3
|
||||||
|
#define RTK_HWPATCH_OP_ALGO 4
|
||||||
|
#define RTK_HWPATCH_OP_TOP 5
|
||||||
|
#define RTK_HWPATCH_OP_MMD 6
|
||||||
|
#define RTK_HWPATCH_OP_DATARAM 7
|
||||||
|
|
||||||
|
typedef struct rtk_phy_hwpatch_s
|
||||||
|
{
|
||||||
|
uint8 patch_op;
|
||||||
|
uint8 portmask;
|
||||||
|
uint16 pagemmd;
|
||||||
|
uint16 addr;
|
||||||
|
uint8 msb;
|
||||||
|
uint8 lsb;
|
||||||
|
uint16 data;
|
||||||
|
} rtk_phy_hwpatch_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* cable type for cable test */
|
||||||
|
typedef enum {
|
||||||
|
RTK_RTCT_CABLE_COMMON,
|
||||||
|
RTK_RTCT_CABLE_CAT5E,
|
||||||
|
RTK_RTCT_CABLE_CAT6A,
|
||||||
|
} rtk_rtct_cable_type_t;
|
||||||
|
|
||||||
|
/* MACSec */
|
||||||
|
#ifndef RTK_MAX_MACSEC_SA_PER_PORT
|
||||||
|
#define RTK_MAX_MACSEC_SA_PER_PORT 64 /* max number of Secure Association by a port*/
|
||||||
|
#define RTK_MAX_MACSEC_SC_PER_PORT RTK_MAX_MACSEC_SA_PER_PORT/4 /* max number of Secure Channel by a port (4 AN per SC) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTK_MACSEC_MAX_KEY_LEN 32
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_reg_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_DIR_EGRESS = 0,
|
||||||
|
RTK_MACSEC_DIR_INGRESS,
|
||||||
|
RTK_MACSEC_DIR_END,
|
||||||
|
} rtk_macsec_dir_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_an_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_AN0 = 0,
|
||||||
|
RTK_MACSEC_AN1,
|
||||||
|
RTK_MACSEC_AN2,
|
||||||
|
RTK_MACSEC_AN3,
|
||||||
|
RTK_MACSEC_AN_MAX,
|
||||||
|
} rtk_macsec_an_t ;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_flow_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_FLOW_BYPASS = 0,
|
||||||
|
RTK_MACSEC_FLOW_DROP,
|
||||||
|
RTK_MACSEC_FLOW_INGRESS,
|
||||||
|
RTK_MACSEC_FLOW_EGRESS,
|
||||||
|
} rtk_macsec_flow_type_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_validate_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_VALIDATE_STRICT = 0,
|
||||||
|
RTK_MACSEC_VALIDATE_CHECK,
|
||||||
|
RTK_MACSEC_VALIDATE_DISABLE,
|
||||||
|
} rtk_macsec_validate_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_cipher_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_CIPHER_GCM_ASE_128 = 0,
|
||||||
|
RTK_MACSEC_CIPHER_GCM_ASE_256,
|
||||||
|
RTK_MACSEC_CIPHER_GCM_ASE_XPN_128,
|
||||||
|
RTK_MACSEC_CIPHER_GCM_ASE_XPN_256,
|
||||||
|
RTK_MACSEC_CIPHER_MAX,
|
||||||
|
} rtk_macsec_cipher_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_stat_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_STAT_InPktsUntagged = 0,
|
||||||
|
RTK_MACSEC_STAT_InPktsNoTag,
|
||||||
|
RTK_MACSEC_STAT_InPktsBadTag,
|
||||||
|
RTK_MACSEC_STAT_InPktsUnknownSCI,
|
||||||
|
RTK_MACSEC_STAT_InPktsNoSCI,
|
||||||
|
RTK_MACSEC_STAT_OutPktsUntagged,
|
||||||
|
RTK_MACSEC_STAT_MAX,
|
||||||
|
} rtk_macsec_stat_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_txsa_stat_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_TXSA_STAT_OutPktsTooLong = 0,
|
||||||
|
RTK_MACSEC_TXSA_STAT_OutOctetsProtectedEncrypted,
|
||||||
|
RTK_MACSEC_TXSA_STAT_OutPktsProtectedEncrypted,
|
||||||
|
RTK_MACSEC_TXSA_STAT_MAX,
|
||||||
|
} rtk_macsec_txsa_stat_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_rxsa_stat_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsUnusedSA = 0,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsNotUsingSA,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsUnchecked,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsDelayed,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsLate,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsOK,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsInvalid,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InPktsNotValid,
|
||||||
|
RTK_MACSEC_RXSA_STAT_InOctetsDecryptedValidated,
|
||||||
|
RTK_MACSEC_RXSA_STAT_MAX,
|
||||||
|
} rtk_macsec_rxsa_stat_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_match_tx_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_MATCH_NON_CTRL = 0, /* match all non-control and untagged packets */
|
||||||
|
RTK_MACSEC_MATCH_MAC_DA, /* match all non-control and untagged packets with specific MAC DA */
|
||||||
|
} rtk_macsec_match_tx_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_txsc_s
|
||||||
|
{
|
||||||
|
/* 8-byte SCI([0:5] = MAC address, [6:7] = port index) for this secure channel */
|
||||||
|
uint8 sci[8];
|
||||||
|
|
||||||
|
/* cipher suite for this SC */
|
||||||
|
rtk_macsec_cipher_t cipher_suite;
|
||||||
|
|
||||||
|
/* packet flow type to match this SC */
|
||||||
|
rtk_macsec_match_tx_t flow_match;
|
||||||
|
rtk_mac_t mac_da; /* the target address for RTK_MACSEC_MATCH_MAC_DA */
|
||||||
|
|
||||||
|
uint8 protect_frame; /* 1 = enable frame protection */
|
||||||
|
uint8 include_sci; /* 1 = include explicit SCI in packet */
|
||||||
|
uint8 use_es; /* 1 = set ES (End Station) bit in TCI field */
|
||||||
|
uint8 use_scb; /* 1 = set SCB (Single Copy Broadcast) bit in TCI field */
|
||||||
|
uint8 conf_protect; /* 1 = enable confidentiality protection, */
|
||||||
|
}rtk_macsec_txsc_t;
|
||||||
|
|
||||||
|
typedef enum rtk_macsec_match_rx_e
|
||||||
|
{
|
||||||
|
RTK_MACSEC_MATCH_SCI = 0,
|
||||||
|
RTK_MACSEC_MATCH_MAC_SA, //for pkt without SCI field/TCI.SC=0,
|
||||||
|
} rtk_macsec_match_rx_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_rxsc_s
|
||||||
|
{
|
||||||
|
/* 8-byte SCI([0:5] = MAC address, [6:7] = port index) for this secure channel */
|
||||||
|
uint8 sci[8];
|
||||||
|
|
||||||
|
/* cipher suite for this SC */
|
||||||
|
rtk_macsec_cipher_t cipher_suite;
|
||||||
|
|
||||||
|
/* packet flow type to match this SC */
|
||||||
|
rtk_macsec_match_rx_t flow_match;
|
||||||
|
rtk_mac_t mac_sa; /* the target address for RTK_MACSEC_MATCH_MAC_SA */
|
||||||
|
|
||||||
|
/* frame validation level */
|
||||||
|
rtk_macsec_validate_t validate_frames;
|
||||||
|
|
||||||
|
/* replay protection */
|
||||||
|
uint8 replay_protect; /* 1 = enable replay protection */
|
||||||
|
uint32 replay_window; /* the window size for replay protection, range for PN: 0 ~ 2^32 - 1, for XPN: 0 ~ 2^30 */
|
||||||
|
|
||||||
|
}rtk_macsec_rxsc_t;
|
||||||
|
|
||||||
|
typedef union rtk_macsec_sc_u
|
||||||
|
{
|
||||||
|
rtk_macsec_txsc_t tx;
|
||||||
|
rtk_macsec_rxsc_t rx;
|
||||||
|
}
|
||||||
|
rtk_macsec_sc_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_txsc_status_s
|
||||||
|
{
|
||||||
|
uint32 hw_flow_index;
|
||||||
|
uint32 hw_sa_index;
|
||||||
|
uint8 sa_inUse;
|
||||||
|
uint32 hw_flow_data;
|
||||||
|
uint8 hw_sc_flow_status;
|
||||||
|
rtk_macsec_an_t running_an;
|
||||||
|
}
|
||||||
|
rtk_macsec_txsc_status_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_rxsc_status_s
|
||||||
|
{
|
||||||
|
uint32 hw_flow_base;
|
||||||
|
uint32 hw_sa_index[RTK_MACSEC_AN_MAX];
|
||||||
|
uint8 sa_inUse[RTK_MACSEC_AN_MAX];
|
||||||
|
uint32 hw_flow_data[RTK_MACSEC_AN_MAX];
|
||||||
|
uint8 hw_sc_flow_status[RTK_MACSEC_AN_MAX];
|
||||||
|
}
|
||||||
|
rtk_macsec_rxsc_status_t;
|
||||||
|
|
||||||
|
typedef union rtk_macsec_sc_status_u
|
||||||
|
{
|
||||||
|
rtk_macsec_txsc_status_t tx;
|
||||||
|
rtk_macsec_rxsc_status_t rx;
|
||||||
|
}
|
||||||
|
rtk_macsec_sc_status_t;
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_sa_s
|
||||||
|
{
|
||||||
|
uint8 key[RTK_MACSEC_MAX_KEY_LEN]; // MACsec Key.
|
||||||
|
uint32 key_bytes; // Size of the MACsec key in bytes (16 for AES128, 32 for AES256).
|
||||||
|
|
||||||
|
uint32 pn; // PN (32-bit) or lower 32-bit of XPN (64-bit)
|
||||||
|
uint32 pn_h; // higher 32-bit of XPN (64-bit)
|
||||||
|
uint8 salt[12]; // 12-byte salt (for XPN).
|
||||||
|
uint8 ssci[4]; // 4-byte SSCI value (for XPN).
|
||||||
|
} rtk_macsec_sa_t;
|
||||||
|
|
||||||
|
#define RTK_MACSEC_INTR_EGRESS_PN_THRESHOLD 0x00000001
|
||||||
|
#define RTK_MACSEC_INTR_EGRESS_PN_ROLLOVER 0x00000002
|
||||||
|
|
||||||
|
typedef struct rtk_macsec_intr_status_s
|
||||||
|
{
|
||||||
|
/* a bitmap of RTK_MACSEC_INTR_* to present occured event */
|
||||||
|
uint32 status;
|
||||||
|
|
||||||
|
/* When read 1b, the corresponding MACsec egress SA is about to expire due to
|
||||||
|
the packet number crossing the rtk_macsec_port_cfg_t.pn_intr_threshold or xpn_intr_threshold*/
|
||||||
|
uint8 egress_pn_thr_an_bmap[RTK_MAX_MACSEC_SC_PER_PORT]; //bitmap of AN3~0.
|
||||||
|
|
||||||
|
/* When read 1b, the corresponding MACsec egress SA has expired due to
|
||||||
|
the packet number reaching the maximum allowed value. */
|
||||||
|
uint8 egress_pn_exp_an_bmap[RTK_MAX_MACSEC_SC_PER_PORT]; //bitmap of AN3~0.
|
||||||
|
}
|
||||||
|
rtk_macsec_intr_status_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum rtk_wol_opt_e
|
||||||
|
{
|
||||||
|
RTK_WOL_OPT_LINK = (0x1U << 0),
|
||||||
|
RTK_WOL_OPT_MAGIC = (0x1U << 1),
|
||||||
|
RTK_WOL_OPT_UCAST = (0x1U << 2),
|
||||||
|
RTK_WOL_OPT_MCAST = (0x1U << 3),
|
||||||
|
RTK_WOL_OPT_BCAST = (0x1U << 4),
|
||||||
|
} rtk_wol_opt_t;
|
||||||
|
|
||||||
|
/* value for RTK_PHY_CTRL_MDI_POLARITY_SWAP */
|
||||||
|
#define RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_A 0b0001
|
||||||
|
#define RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_B 0b0010
|
||||||
|
#define RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_C 0b0100
|
||||||
|
#define RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_D 0b1000
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __RTK_PHYLIB_DEF_H */
|
||||||
2448
sources/rtk-gp3000/src/hal/phy/rtk_phylib_macsec.c
Normal file
2448
sources/rtk-gp3000/src/hal/phy/rtk_phylib_macsec.c
Normal file
File diff suppressed because it is too large
Load diff
329
sources/rtk-gp3000/src/hal/phy/rtk_phylib_macsec.h
Normal file
329
sources/rtk-gp3000/src/hal/phy/rtk_phylib_macsec.h
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RTK_PHYLIB_MACSEC_H
|
||||||
|
#define __RTK_PHYLIB_MACSEC_H
|
||||||
|
|
||||||
|
#if defined(RTK_PHYDRV_IN_LINUX)
|
||||||
|
#include "type.h"
|
||||||
|
#include "rtk_phylib_def.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PHY_MACSEC_DEV_EGRESS 0
|
||||||
|
#define PHY_MACSEC_DEV_INGRESS 1
|
||||||
|
|
||||||
|
#define MACSEC_REG_OFFS 4
|
||||||
|
|
||||||
|
#define PHY_MACSEC_HW_SA_ID(sc_id, an) (sc_id * 4 + an)
|
||||||
|
#define PHY_MACSEC_HW_FLOW_ID(sc_id) (sc_id * 4)
|
||||||
|
#define PHY_MACSEC_HW_SA_TO_AN(sa_id) (sa_id % 4)
|
||||||
|
|
||||||
|
#define PHY_MACSEC_MAX_SA_EN_SIZE 24 //32-bit words
|
||||||
|
#define PHY_MACSEC_MAX_SA_IN_SIZE 20
|
||||||
|
#define PHY_MACSEC_MAX_SA_SIZE PHY_MACSEC_MAX_SA_EN_SIZE
|
||||||
|
|
||||||
|
#define MACSEC_XFORM_REC_BASE (0x0000)
|
||||||
|
#define MACSEC_XFORM_REC_SIZE(dir) ((RTK_MACSEC_DIR_EGRESS == dir) ? PHY_MACSEC_MAX_SA_EN_SIZE : PHY_MACSEC_MAX_SA_IN_SIZE )
|
||||||
|
|
||||||
|
#define MACSEC_REG_XFORM_REC(n, dir) (MACSEC_XFORM_REC_BASE + MACSEC_XFORM_REC_SIZE(dir) * \
|
||||||
|
MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_XFORM_REC_OFFS(n, dir, off) (MACSEC_REG_XFORM_REC(n, dir) + off * MACSEC_REG_OFFS)
|
||||||
|
|
||||||
|
|
||||||
|
#define MACSEC_REG_SAM_MAC_SA_MATCH_LO(n) (0x4000 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_MAC_SA_MATCH_HI(n) (0x4004 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_MAC_DA_MATCH_LO(n) (0x4008 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_MAC_DA_MATCH_HI(n) (0x400C + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
|
||||||
|
#define MACSEC_REG_SAM_MISC_MATCH(n) (0x4010 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_SCI_MATCH_LO(n) (0x4014 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_SCI_MATCH_HI(n) (0x4018 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_MASK(n) (0x401C + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
#define MACSEC_REG_SAM_EXT_MATCH(n) (0x4020 + 16 * MACSEC_REG_OFFS * (n % 128))
|
||||||
|
|
||||||
|
#define MACSEC_REG_SAM_ENTRY_ENABLE(n) (0x6000 + (n * MACSEC_REG_OFFS))
|
||||||
|
#define MACSEC_REG_SAM_ENTRY_TOGGLE(n) (0x6040 + (n * MACSEC_REG_OFFS))
|
||||||
|
#define MACSEC_REG_SAM_ENTRY_SET(n) (0x6080 + (n * MACSEC_REG_OFFS))
|
||||||
|
#define MACSEC_REG_SAM_ENTRY_CLEAR(n) (0x60C0 + (n * MACSEC_REG_OFFS))
|
||||||
|
#define MACSEC_REG_SAM_ENTRY_ENABLE_CTRL (0x6100)
|
||||||
|
#define MACSEC_REG_SAM_IN_FLIGHT (0x6104)
|
||||||
|
|
||||||
|
#define MACSEC_REG_SAM_FLOW_CTRL(n) (0x7000 + MACSEC_REG_OFFS * (n % 128))
|
||||||
|
|
||||||
|
|
||||||
|
#define MACSEC_REG_SAM_IN_FLIGHT (0x6104)
|
||||||
|
#define MACSEC_REG_COUNT_CTRL (0xC810)
|
||||||
|
#define MACSEC_REG_IG_CC_CONTROL (0xE840)
|
||||||
|
#define MACSEC_REG_COUNT_SECFAIL1 (0xF124)
|
||||||
|
#define MACSEC_REG_CTX_CTRL (0xF408)
|
||||||
|
#define MACSEC_REG_CTX_UPD_CTRL (0xF430)
|
||||||
|
#define MACSEC_REG_SAM_CP_TAG (0x7900)
|
||||||
|
#define MACSEC_REG_SAM_NM_PARAMS (0x7940)
|
||||||
|
#define MACSEC_REG_SAM_NM_FLOW_NCP (0x7944)
|
||||||
|
#define MACSEC_REG_SAM_NM_FLOW_CP (0x7948)
|
||||||
|
|
||||||
|
#define MACSEC_REG_MISC_CONTROL (0x797C)
|
||||||
|
|
||||||
|
// Mask last byte received of MAC source address
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_0 BIT_0
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_1 BIT_1
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_2 BIT_2
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_3 BIT_3
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_4 BIT_4
|
||||||
|
// Mask first byte received of MAC source address
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_5 BIT_5
|
||||||
|
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_SA_FULL (BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_4 | BIT_5)
|
||||||
|
|
||||||
|
// Mask last byte received of MAC destination address
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_0 BIT_6
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_1 BIT_7
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_2 BIT_8
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_3 BIT_9
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_4 BIT_10
|
||||||
|
// Mask first byte received of MAC destination address
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_5 BIT_11
|
||||||
|
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_DA_FULL (BIT_6 | BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11)
|
||||||
|
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MAC_ETYPE BIT_12
|
||||||
|
#define MACSEC_SA_MATCH_MASK_VLAN_VALID BIT_13
|
||||||
|
#define MACSEC_SA_MATCH_MASK_QINQ_FOUND BIT_14
|
||||||
|
#define MACSEC_SA_MATCH_MASK_STAG_VALID BIT_15
|
||||||
|
#define MACSEC_SA_MATCH_MASK_QTAG_VALID BIT_16
|
||||||
|
#define MACSEC_SA_MATCH_MASK_VLAN_UP BIT_17
|
||||||
|
#define MACSEC_SA_MATCH_MASK_VLAN_ID BIT_18
|
||||||
|
#define MACSEC_SA_MATCH_MASK_SRC_PORT BIT_19
|
||||||
|
#define MACSEC_SA_MATCH_MASK_CTRL_PKT BIT_20
|
||||||
|
|
||||||
|
// For ingress only
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MACSEC_SCI BIT_23
|
||||||
|
#define MACSEC_SA_MATCH_MASK_MACSEC_TCI_AN_SC (BIT_24 | BIT_25 | BIT_29)
|
||||||
|
|
||||||
|
#define MACSEC_SAB_CW0_MACSEC_EG32 0x9241e066
|
||||||
|
#define MACSEC_SAB_CW0_MACSEC_IG32 0xd241e06f
|
||||||
|
#define MACSEC_SAB_CW0_MACSEC_EG64 0xa241e066
|
||||||
|
#define MACSEC_SAB_CW0_MACSEC_IG64 0xe241a0ef
|
||||||
|
#define MACSEC_SAB_CW0_AES128 0x000a0000
|
||||||
|
#define MACSEC_SAB_CW0_AES256 0x000e0000
|
||||||
|
|
||||||
|
|
||||||
|
#define RTK_MACSEC_PORT_COMMON 0
|
||||||
|
#define RTK_MACSEC_PORT_RESERVED 1
|
||||||
|
#define RTK_MACSEC_PORT_CONTROLLED 2
|
||||||
|
#define RTK_MACSEC_PORT_UNCONTROLLED 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct phy_macsec_flow_action_e_s
|
||||||
|
{
|
||||||
|
// 1 - enable frame protection,
|
||||||
|
// 0 - bypass frame through device
|
||||||
|
uint8 protect_frame;
|
||||||
|
|
||||||
|
// 1 - SA is in use, packets classified for it can be transformed
|
||||||
|
// 0 - SA not in use, packets classified for it can not be transformed
|
||||||
|
uint8 sa_in_use;
|
||||||
|
|
||||||
|
// 1 - inserts explicit SCI in the packet,
|
||||||
|
// 0 - use implicit SCI (not transferred)
|
||||||
|
uint8 include_sci;
|
||||||
|
|
||||||
|
// 1 - enable ES bit in the generated SecTAG
|
||||||
|
// 0 - disable ES bit in the generated SecTAG
|
||||||
|
uint8 use_es;
|
||||||
|
|
||||||
|
// 1 - enable SCB bit in the generated SecTAG
|
||||||
|
// 0 - disable SCB bit in the generated SecTAG
|
||||||
|
uint8 use_scb;
|
||||||
|
|
||||||
|
// Number of VLAN tags to bypass for egress processing.
|
||||||
|
// Valid values: 0, 1 and 2.
|
||||||
|
// This feature is only available on HW4.1 and possibly later versions.
|
||||||
|
uint8 tag_bypass_size;
|
||||||
|
|
||||||
|
// 1 - Does not update sa_in_use flag
|
||||||
|
// 0 - Update sa_in_use flag
|
||||||
|
uint8 sa_index_update_by_hw;
|
||||||
|
|
||||||
|
// The number of bytes (in the range of 0-127) that are authenticated but
|
||||||
|
// not encrypted following the SecTAG in the encrypted packet. Values
|
||||||
|
// 65-127 are reserved in HW < 4.0 and should not be used there.
|
||||||
|
uint8 confidentiality_offset;
|
||||||
|
|
||||||
|
// 1 - enable confidentiality protection
|
||||||
|
// 0 - disable confidentiality protection
|
||||||
|
uint8 conf_protect;
|
||||||
|
|
||||||
|
} phy_macsec_flow_action_e_t;
|
||||||
|
|
||||||
|
typedef struct phy_macsec_flow_action_i_s
|
||||||
|
{
|
||||||
|
// 1 - enable replay protection
|
||||||
|
// 0 - disable replay protection
|
||||||
|
uint8 replay_protect;
|
||||||
|
|
||||||
|
// true - SA is in use, packets classified for it can be transformed
|
||||||
|
// false - SA not in use, packets classified for it can not be transformed
|
||||||
|
uint8 sa_in_use;
|
||||||
|
|
||||||
|
// MACsec frame validation level
|
||||||
|
rtk_macsec_validate_t validate_frames;
|
||||||
|
|
||||||
|
// The number of bytes (in the range of 0-127) that are authenticated but
|
||||||
|
// not encrypted following the SecTAG in the encrypted packet.
|
||||||
|
uint8 confidentiality_offset;
|
||||||
|
|
||||||
|
} phy_macsec_flow_action_i_t;
|
||||||
|
|
||||||
|
typedef struct phy_macsec_flow_action_bd_s
|
||||||
|
{
|
||||||
|
// 1 - enable statistics counting for the associated SA
|
||||||
|
// 0 - disable statistics counting for the associated SA
|
||||||
|
uint8 sa_in_use;
|
||||||
|
} phy_macsec_flow_action_bd_t;
|
||||||
|
|
||||||
|
typedef struct phy_macsec_flow_action_s
|
||||||
|
{
|
||||||
|
uint32 sa_index;
|
||||||
|
|
||||||
|
rtk_macsec_flow_type_t flow_type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
phy_macsec_flow_action_e_t egress;
|
||||||
|
phy_macsec_flow_action_i_t ingress;
|
||||||
|
phy_macsec_flow_action_bd_t bypass_drop;
|
||||||
|
} params;
|
||||||
|
|
||||||
|
uint8 dest_port;
|
||||||
|
|
||||||
|
} phy_macsec_flow_action_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// index for flow control rule entry
|
||||||
|
uint32 flow_index;
|
||||||
|
|
||||||
|
// Packet field values to match
|
||||||
|
|
||||||
|
// MAC source address
|
||||||
|
uint8 mac_sa[6];
|
||||||
|
|
||||||
|
// MAC destination address
|
||||||
|
uint8 mac_da[6];
|
||||||
|
|
||||||
|
// EtherType
|
||||||
|
uint16 etherType;
|
||||||
|
|
||||||
|
// SCI, for ingress only
|
||||||
|
uint8 sci[8];
|
||||||
|
|
||||||
|
// Parsed VLAN ID compare value
|
||||||
|
uint16 vlan_id;
|
||||||
|
|
||||||
|
// Parsed VLAN valid flag compare value
|
||||||
|
uint8 fVLANValid;
|
||||||
|
|
||||||
|
// Parsed QinQ found flag compare value
|
||||||
|
uint8 fQinQFound;
|
||||||
|
|
||||||
|
// Parsed STAG valid flag compare value
|
||||||
|
uint8 fSTagValid;
|
||||||
|
|
||||||
|
// Parsed QTAG valid flag compare value
|
||||||
|
uint8 fQTagFound;
|
||||||
|
|
||||||
|
// Parsed VLAN User Priority compare value
|
||||||
|
uint8 vlanUserPriority;
|
||||||
|
|
||||||
|
// Packet is a control packet (as pre-decoded) compare value
|
||||||
|
uint8 fControlPacket;
|
||||||
|
|
||||||
|
// true - allow packets without a MACsec tag to match
|
||||||
|
uint8 fUntagged;
|
||||||
|
|
||||||
|
// true - allow packets with a standard and valid MACsec tag to match
|
||||||
|
uint8 fTagged;
|
||||||
|
|
||||||
|
// true - allow packets with an invalid MACsec tag to match
|
||||||
|
uint8 fBadTag;
|
||||||
|
|
||||||
|
// true - allow packets with a MACsec tag indicating KaY handling
|
||||||
|
// to be done to match
|
||||||
|
uint8 fKayTag;
|
||||||
|
|
||||||
|
// Source port compare value
|
||||||
|
uint8 sourcePort;
|
||||||
|
|
||||||
|
// Priority of this entry for determining the actual transform used
|
||||||
|
// on a match when multiple entries match, 0 = lowest, 15 = highest.
|
||||||
|
// In case of identical priorities, the lowest numbered entry takes
|
||||||
|
// precedence.
|
||||||
|
uint8 matchPriority;
|
||||||
|
|
||||||
|
// MACsec TCI/AN byte compare value, bits are individually masked for
|
||||||
|
// comparing. The TCI bits are in bits [7:2] while the AN bits reside
|
||||||
|
// in bits [1:0]. the macsec_TCI_AN field should only be set to
|
||||||
|
// non-zero for an actual MACsec packet.
|
||||||
|
uint8 macsec_TCI_AN;
|
||||||
|
|
||||||
|
// Match mask for the SA flow rules, see MACSEC_SA_MATCH_MASK_*
|
||||||
|
uint32 matchMask;
|
||||||
|
|
||||||
|
// Parsed inner VLAN ID compare value
|
||||||
|
uint16 vlanIdInner;
|
||||||
|
|
||||||
|
// Parsed inner VLAN UP compare value
|
||||||
|
uint8 vlanUpInner;
|
||||||
|
|
||||||
|
} phy_macsec_flow_match_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8 key_offs;
|
||||||
|
uint8 hkey_offs;
|
||||||
|
uint8 seq_offs;
|
||||||
|
uint8 mask_offs;
|
||||||
|
uint8 ctx_salt_offs;
|
||||||
|
uint8 iv_offs;
|
||||||
|
uint8 upd_ctrl_offs;
|
||||||
|
} phy_macsec_sa_offset_t;
|
||||||
|
|
||||||
|
#define RTK_PHY_MACSEC_SA_FLAG_XPN 0x00000001U //Extended Packet Numbering
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32 context_id; //keep 0 for create
|
||||||
|
rtk_macsec_dir_t direction;
|
||||||
|
uint32 flow_index; //the flow entry index apply to this SA
|
||||||
|
uint32 flags; // a bitmap of RTK_PHY_MACSEC_SA_FLAG_*
|
||||||
|
|
||||||
|
uint8 an; // 2-bit AN inserted in SecTAG (egress).
|
||||||
|
uint8 sci[8]; // 8-byte SCI.([0:5] = MAC address, [6:7] = port index)
|
||||||
|
|
||||||
|
uint8 key[RTK_MACSEC_MAX_KEY_LEN]; // MACsec Key.
|
||||||
|
uint32 key_bytes; // Size of the MACsec key in bytes (16 for AES128, 32 for AES256).
|
||||||
|
|
||||||
|
uint8 salt[12]; // 12-byte salt (64-bit sequence numbers).
|
||||||
|
uint8 ssci[4]; // 4-byte SSCI value (64-bit sequence numbers).
|
||||||
|
|
||||||
|
uint32 seq; // sequence number.
|
||||||
|
uint32 seq_h; // High part of sequence number (64-bit sequence numbers)
|
||||||
|
uint32 replay_window; // Size of the replay window, 0 for strict ordering (ingress).
|
||||||
|
|
||||||
|
/* update ctrl */
|
||||||
|
uint32 next_sa_index; // SA index of the next chained SA (egress).
|
||||||
|
uint8 sa_expired_irq; // 1 if SA expired IRQ is to be generated.
|
||||||
|
uint8 next_sa_valid; // SA Index field is a valid SA.
|
||||||
|
uint8 update_en; // Set to true if the SA must be updated.
|
||||||
|
} phy_macsec_sa_params_t;
|
||||||
|
|
||||||
|
typedef void (*phy_macsec_aes_cb)(
|
||||||
|
const uint8 * const In_p,
|
||||||
|
uint8 * const Out_p,
|
||||||
|
const uint8 * const Key_p,
|
||||||
|
const unsigned int KeyByteCount);
|
||||||
|
|
||||||
|
#endif /* __RTK_PHYLIB_MACSEC_H */
|
||||||
896
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl8224.c
Normal file
896
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl8224.c
Normal file
|
|
@ -0,0 +1,896 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Realtek Semiconductor Corp.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is the proprietary software of Realtek Semiconductor
|
||||||
|
* Corporation and/or its licensors, and only be used, duplicated,
|
||||||
|
* modified or distributed under the authorized license from Realtek.
|
||||||
|
*
|
||||||
|
* ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
|
||||||
|
* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||||
|
*
|
||||||
|
* $Revision: $
|
||||||
|
* $Date: $
|
||||||
|
*
|
||||||
|
* Purpose : PHY 8224 Driver APIs.
|
||||||
|
*
|
||||||
|
* Feature : PHY 8224 Driver APIs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
#include "rtk_phy.h"
|
||||||
|
#include "rtk_phylib_rtl8224.h"
|
||||||
|
#include "phy_rtl8224_patch.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "rtk_osal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbol Definition
|
||||||
|
*/
|
||||||
|
#define RTL8224_SWREG_ADDR(_addr) ((_addr) & (0xffff))
|
||||||
|
|
||||||
|
rtk_port_t _phy_8224_base_port_get(uint32 unit, rtk_port_t port)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
|
||||||
|
return priv->basePort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function Declaration
|
||||||
|
*/
|
||||||
|
uint32
|
||||||
|
_phy_8224_mask(uint8 msb, uint8 lsb)
|
||||||
|
{
|
||||||
|
uint32 val = 0;
|
||||||
|
uint8 i = 0;
|
||||||
|
|
||||||
|
for (i = lsb; i <= msb; i++)
|
||||||
|
{
|
||||||
|
val |= (1 << i);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_mask_get(uint8 msb, uint8 lsb, uint32 *mask)
|
||||||
|
{
|
||||||
|
if ((msb > 31) || (lsb > 31) || (msb < lsb))
|
||||||
|
{
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
*mask = _phy_8224_mask(msb, lsb);
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 _phy_8224_intReg_get(uint32 unit, rtk_port_t port, uint32 reg_addr, uint8 msb, uint8 lsb, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
rtk_port_t base_port = 0;
|
||||||
|
uint32 addr;
|
||||||
|
uint32 l_data = 0;
|
||||||
|
uint32 h_data = 0;
|
||||||
|
uint32 reg_data = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
|
||||||
|
if ((msb > 31) || (lsb > 31) || (msb < lsb))
|
||||||
|
{
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_port = _phy_8224_base_port_get(unit, port);
|
||||||
|
|
||||||
|
/* Reg [15:0]*/
|
||||||
|
addr = RTL8224_SWREG_ADDR(reg_addr);
|
||||||
|
ret = phy_common_general_reg_mmd_get(unit, base_port, PHY_MMD_VEND1, addr, &l_data);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Reg [31:16]*/
|
||||||
|
ret = phy_common_general_reg_mmd_get(unit, base_port, PHY_MMD_VEND1, (addr+1), &h_data);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = _phy_8224_mask_get(msb, lsb, &mask);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
reg_data = ((h_data << 16) | (l_data));
|
||||||
|
*pData = (((reg_data) & (mask)) >> lsb);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 _phy_8224_intReg_set(uint32 unit, rtk_port_t port, uint32 reg_addr, uint8 msb, uint8 lsb, uint32 data)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
rtk_port_t base_port = 0;
|
||||||
|
uint32 addr;
|
||||||
|
uint32 l_data = 0;
|
||||||
|
uint32 h_data = 0;
|
||||||
|
uint32 reg_data = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
|
||||||
|
if ((msb > 31) || (lsb > 31) || (msb < lsb))
|
||||||
|
{
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_port = _phy_8224_base_port_get(unit, port);
|
||||||
|
|
||||||
|
/* Reg [15:0]*/
|
||||||
|
addr = RTL8224_SWREG_ADDR(reg_addr);
|
||||||
|
ret = phy_common_general_reg_mmd_get(unit, base_port, PHY_MMD_VEND1, addr, &l_data);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Reg [31:16]*/
|
||||||
|
ret = phy_common_general_reg_mmd_get(unit, base_port, PHY_MMD_VEND1, (addr+1), &h_data);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = _phy_8224_mask_get(msb, lsb, &mask);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
reg_data = ((h_data << 16) | (l_data));
|
||||||
|
reg_data &= ~(mask);
|
||||||
|
reg_data |= (((data) << lsb) & mask);
|
||||||
|
|
||||||
|
l_data = (reg_data & 0xffff);
|
||||||
|
h_data = ((reg_data >> 16)& 0xffff);
|
||||||
|
|
||||||
|
ret = phy_common_general_reg_mmd_set(unit, base_port, PHY_MMD_VEND1, addr, l_data);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = phy_common_general_reg_mmd_set(unit, base_port, PHY_MMD_VEND1, (addr+1), h_data);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 _phy_8224_intRegBit_set(uint32 unit, rtk_port_t port, uint32 reg_addr, uint8 bit, uint32 data)
|
||||||
|
{
|
||||||
|
if (bit > 31)
|
||||||
|
{
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
return _phy_8224_intReg_set(unit, port, reg_addr, bit, bit, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 _phy_8224_sram_get(uint32 unit, rtk_port_t port, uint32 sramAddr, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret;
|
||||||
|
|
||||||
|
ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xa436, sramAddr);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xa438, pData);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_interrupt_init(uint32 unit, rtk_port_t port)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
uint8 port_offset;
|
||||||
|
|
||||||
|
base_port = _phy_8224_base_port_get(unit, port);
|
||||||
|
if ((ret = phy_8224_get_port_offset(base_port, port, &port_offset)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Clean GPHY Interrupt Pending bits*/
|
||||||
|
/* Read and Clear*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA43A, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
/* Clean ISR_EXT_GPHY */
|
||||||
|
/* Write 1 to clear */
|
||||||
|
if ((ret = _phy_8224_intRegBit_set(unit, port, RTL8224_ISR_EXT_GPHY, port_offset, 1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (port == base_port)
|
||||||
|
{
|
||||||
|
/* Disable IMR_EXT_GPHY */
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_IMR_EXT_GPHY, RTL8224_IMR_EXT_GPHY_3_0_MSB, RTL8224_IMR_EXT_GPHY_3_0_OFFSET, 0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Disable Thermal/PTP 1588/MACsec IMR */
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, 0xbb005f78, RTL8224_INTER_REG_MSB, RTL8224_INTER_REG_LSB, 0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, 0xbb005f68, RTL8224_INTER_REG_MSB, RTL8224_INTER_REG_LSB, 0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Disable RLFD Interrupt pin output */
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, 0xbb005f64, RTL8224_INTER_REG_MSB, RTL8224_INTER_REG_LSB, 0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, 0xbb005f40, RTL8224_INTER_REG_MSB, RTL8224_INTER_REG_LSB, 0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
/* Enable RLFD IMR */
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_RLFD_CTRL_REG, RTL8224_RLFD_SEL_OFFSET, RTL8224_RLFD_EN_OFFSET, 1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_CFG_PHY_POLL_CMD1_REG, RTL8224_CMD_RD_EN_3_0_MSB, RTL8224_CMD_RD_EN_3_0_LSB, 7)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Enable Global IMR for interrupt GPIO output, high level trigger*/
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_ISR_SW_INT_MODE, RTL8224_SWITCH_IE_OFFSET, RTL8224_SWITCH_IE_OFFSET, 1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_ISR_SW_INT_MODE, RTL8224_SWITCH_INT_MODE_MSB, RTL8224_SWITCH_INT_MODE_OFFSET, PHY_8224_INT_MODE_LOW_LEVEL)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*All ports*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA442, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
phyData |= (0x1 << PHY_8224_RLFD_ENABLE_OFFSET);
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA442, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_rtctChannelLen_get(uint32 unit, rtk_port_t port, uint32 channel, uint32 *pChLen)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 channel_l, channel_h;
|
||||||
|
uint32 cable_len;
|
||||||
|
|
||||||
|
switch (channel)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x802c - 0x4), &channel_h)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x802d - 0x4), &channel_l)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x8030 - 0x4), &channel_h)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x8031 - 0x4), &channel_l)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x8034 - 0x4), &channel_h)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x8035 - 0x4), &channel_l)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x8038 - 0x4), &channel_h)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, (0x8039 - 0x4), &channel_l)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return RT_ERR_OUT_OF_RANGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cable_len = ((channel_h & 0xff00)+((channel_l >> 8) & 0xff));
|
||||||
|
if (cable_len >= RTL8224_RTCT_LEN_OFFSET)
|
||||||
|
cable_len = cable_len - RTL8224_RTCT_LEN_OFFSET;
|
||||||
|
else
|
||||||
|
cable_len = 0;
|
||||||
|
|
||||||
|
cable_len = (cable_len*10)/RTL8224_RTCT_LEN_CABLE_FACTOR;
|
||||||
|
|
||||||
|
*pChLen = cable_len;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_rtctStatus_convert(uint32 phyData,
|
||||||
|
uint32 *pShort, uint32 *pOpen,
|
||||||
|
uint32 *pMismatch, uint32 *pPairBusy)
|
||||||
|
{
|
||||||
|
if (phyData & BIT_6)
|
||||||
|
{
|
||||||
|
if (phyData & BIT_5)
|
||||||
|
{
|
||||||
|
/* normal */
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
else if (phyData & BIT_3)
|
||||||
|
{
|
||||||
|
*pOpen = 1;
|
||||||
|
}
|
||||||
|
else if (phyData & BIT_4)
|
||||||
|
{
|
||||||
|
*pShort = 1;
|
||||||
|
}
|
||||||
|
else if (phyData & BIT_0)
|
||||||
|
{
|
||||||
|
*pPairBusy = 1;
|
||||||
|
}
|
||||||
|
else if (phyData & BIT_7) /* Interpair short */
|
||||||
|
{
|
||||||
|
*pShort = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return RT_ERR_PHY_RTCT_NOT_FINISH;
|
||||||
|
}
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_common_c45_enable_get(uint32 unit, rtk_port_t port, rtk_enable_t *pEnable)
|
||||||
|
{
|
||||||
|
int32 ret;
|
||||||
|
uint32 phyData = 0;
|
||||||
|
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*pEnable = (phyData & BIT_11) ? (DISABLED) : (ENABLED);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_common_c45_speedDuplexStatusResReg_get(uint32 unit, rtk_port_t port, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_FAILED;
|
||||||
|
uint32 phyData, spd;
|
||||||
|
|
||||||
|
*pSpeed = PORT_SPEED_10M;
|
||||||
|
*pDuplex = PORT_HALF_DUPLEX;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA434, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* [10:9,5:4] */
|
||||||
|
spd = ((phyData & (0x3 << 9)) >> (9 - 2)) | ((phyData & (0x3 << 4)) >> 4);
|
||||||
|
switch (spd)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
*pSpeed = PORT_SPEED_10M;
|
||||||
|
break;
|
||||||
|
case 0x1:
|
||||||
|
*pSpeed = PORT_SPEED_100M;
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
*pSpeed = PORT_SPEED_1000M;
|
||||||
|
break;
|
||||||
|
case 0x3:
|
||||||
|
*pSpeed = PORT_SPEED_500M;
|
||||||
|
break;
|
||||||
|
case 0x4:
|
||||||
|
*pSpeed = PORT_SPEED_10G;
|
||||||
|
break;
|
||||||
|
case 0x5:
|
||||||
|
*pSpeed = PORT_SPEED_2_5G;
|
||||||
|
break;
|
||||||
|
case 0x6:
|
||||||
|
*pSpeed = PORT_SPEED_5G;
|
||||||
|
break;
|
||||||
|
case 0x7:
|
||||||
|
*pSpeed = PORT_SPEED_2_5G_LITE;
|
||||||
|
break;
|
||||||
|
case 0x8:
|
||||||
|
*pSpeed = PORT_SPEED_5G_LITE;
|
||||||
|
break;
|
||||||
|
case 0x9:
|
||||||
|
*pSpeed = PORT_SPEED_10G_LITE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*pSpeed = PORT_SPEED_10M;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pDuplex = (phyData & 0x8)? PORT_FULL_DUPLEX : PORT_HALF_DUPLEX;
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_tx_polarity_swap_set(rtk_port_t port, uint32 value)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData, msb_bit, lsb_bit;
|
||||||
|
uint32 unit = 0;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
uint8 port_offset = 0;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
if ((ret = phy_8224_get_port_offset(base_port, port, &port_offset)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
lsb_bit = (port_offset*RTL8224_PHY_TX_POLARITY_SWAP_OFFSET);
|
||||||
|
msb_bit = lsb_bit + (RTL8224_PHY_TX_POLARITY_SWAP_OFFSET - 1);
|
||||||
|
if ((ret = _phy_8224_intReg_get(unit, port, RTL8224_PHY_TX_POLARITY_SWAP, msb_bit, lsb_bit, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
phyData &= (~(BIT_0 | BIT_1 | BIT_2 | BIT_3));
|
||||||
|
phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_A)? (BIT_0) : (0);
|
||||||
|
phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_B)? (BIT_1) : (0);
|
||||||
|
phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_C)? (BIT_2) : (0);
|
||||||
|
phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_D)? (BIT_3) : (0);
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_PHY_TX_POLARITY_SWAP, msb_bit, lsb_bit, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_mdi_reverse_set(rtk_port_t port, uint32 value)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData;
|
||||||
|
uint32 unit = 0;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
uint8 port_offset = 0;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
if ((ret = phy_8224_get_port_offset(base_port, port, &port_offset)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_intReg_get(unit, port, RTL8224_PHY_MDI_REVERSE, port_offset, port_offset, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
/* PortOffset 0&1 --> 0: Reverse, 1: Normal */
|
||||||
|
/* PortOffset 2&3 --> 0: Normal, 1: Reverse */
|
||||||
|
if(value != 0) /*Need to reverse*/
|
||||||
|
{
|
||||||
|
switch(port_offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
phyData = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
phyData = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
switch(port_offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
phyData = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
phyData = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, RTL8224_PHY_MDI_REVERSE, port_offset, port_offset, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtk_port_t
|
||||||
|
_phy_8224_get_phydevice_by_offset(int32 unit, rtk_port_t baseId, uint8 offset)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)baseId->priv;
|
||||||
|
|
||||||
|
if(priv->memberPort[offset] != NULL)
|
||||||
|
{
|
||||||
|
return priv->memberPort[offset];
|
||||||
|
}else{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 _phy_8224_sdsRegField_set(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint8 msb, uint8 lsb, uint32 data)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
int32 ret;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
uint32 reg_data = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
|
||||||
|
if ((msb > 15) || (lsb > 15) || (msb < lsb))
|
||||||
|
{
|
||||||
|
return RT_ERR_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
phy_rtl8224_sdsReg_get(unit, base_port, sdsPage, sdsReg, ®_data);
|
||||||
|
|
||||||
|
ret = _phy_8224_mask_get(msb, lsb, &mask);
|
||||||
|
if(ret != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
reg_data &= ~(mask);
|
||||||
|
reg_data |= (((data) << lsb) & mask);
|
||||||
|
|
||||||
|
phy_rtl8224_sdsReg_set(unit, base_port, sdsPage, sdsReg, reg_data);
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_rtctResult_get(uint32 unit, rtk_port_t port, rtk_rtctResult_t *pRtctResult)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData = 0, speed = 0, duplex = 0;
|
||||||
|
uint32 channel_status = 0;
|
||||||
|
uint32 channel_length;
|
||||||
|
|
||||||
|
|
||||||
|
osal_memset(pRtctResult, 0, sizeof(rtk_rtctResult_t));
|
||||||
|
|
||||||
|
/* Check the port is link up or not?
|
||||||
|
* Due to bit 2 is LL(latching low), need to read twice to get current status
|
||||||
|
*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0x1, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0x1, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
_phy_8224_common_c45_speedDuplexStatusResReg_get(unit, port, &speed, &duplex);
|
||||||
|
if (phyData & BIT_2)
|
||||||
|
{
|
||||||
|
if (speed == PORT_SPEED_10M)
|
||||||
|
{
|
||||||
|
return RT_ERR_PORT_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
/* If the port link is up,
|
||||||
|
* return cable length from Channel Estimation
|
||||||
|
*/
|
||||||
|
osal_memset(pRtctResult, 0, sizeof(rtk_rtctResult_t));
|
||||||
|
if (speed == PORT_SPEED_2_5G) /* 2.5GM */
|
||||||
|
{
|
||||||
|
pRtctResult->linkType = PORT_SPEED_2_5G;
|
||||||
|
/* The channel A length is store in UC 0x8ff5 [15:8]*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xb87c, 0x8ff5)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xb87e, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelALen = ((phyData & 0xFF00) >> 8)*100;
|
||||||
|
|
||||||
|
/* The channel B length is store in UC 0x8ff6 [15:8]*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xb87c, 0x8ff6)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xb87e, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelBLen = ((phyData & 0xFF00) >> 8)*100;
|
||||||
|
|
||||||
|
/* The channel C length is store in UC 0x8ff7 [15:8]*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xb87c, 0x8ff7)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xb87e, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelCLen = ((phyData & 0xFF00) >> 8)*100;
|
||||||
|
|
||||||
|
/* The channel D length is store in UC 0x8ff8 [15:8]*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xb87c, 0x8ff8)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xb87e, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelDLen = ((phyData & 0xFF00) >> 8)*100;
|
||||||
|
}
|
||||||
|
else if (speed == PORT_SPEED_1000M) /* 1000M */
|
||||||
|
{
|
||||||
|
/* The Length is store in [7:0], and the unit is meter*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA880, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->linkType = PORT_SPEED_1000M;
|
||||||
|
pRtctResult->un.ge_result.channelALen = (phyData & 0x00FF)*100;
|
||||||
|
pRtctResult->un.ge_result.channelBLen = (phyData & 0x00FF)*100;
|
||||||
|
pRtctResult->un.ge_result.channelCLen = (phyData & 0x00FF)*100;
|
||||||
|
pRtctResult->un.ge_result.channelDLen = (phyData & 0x00FF)*100;
|
||||||
|
}
|
||||||
|
else /* 100M */
|
||||||
|
{
|
||||||
|
/* The Length is store in [7:0], and the unit is meter*/
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA880, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->linkType = PORT_SPEED_100M;
|
||||||
|
pRtctResult->un.fe_result.rxLen = (phyData & 0x00FF)*100;
|
||||||
|
pRtctResult->un.fe_result.txLen = (phyData & 0x00FF)*100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA422, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((phyData & BIT_15) == 0)
|
||||||
|
return RT_ERR_PHY_RTCT_NOT_FINISH;
|
||||||
|
|
||||||
|
pRtctResult->linkType = PORT_SPEED_1000M;
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_rtctChannelLen_get(unit, port, 0, &channel_length)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelALen = (channel_length*100); /* RTCT length unit is cm */
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL A]: Length 0x%d\n", __FUNCTION__, channel_length);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_rtctChannelLen_get(unit, port, 1, &channel_length)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelBLen = (channel_length*100); /* RTCT length unit is cm */
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL B]: Length 0x%d\n", __FUNCTION__, channel_length);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_rtctChannelLen_get(unit, port, 2, &channel_length)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelCLen = (channel_length*100); /* RTCT length unit is cm */
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL C]: Length 0x%d\n", __FUNCTION__, channel_length);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_rtctChannelLen_get(unit, port, 3, &channel_length)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
pRtctResult->un.ge_result.channelDLen = (channel_length*100); /* RTCT length unit is cm */
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL D]: Length 0x%d\n", __FUNCTION__, channel_length);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, 0x8026, &channel_status)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_rtctStatus_convert(channel_status,
|
||||||
|
&pRtctResult->un.ge_result.channelAShort, &pRtctResult->un.ge_result.channelAOpen,
|
||||||
|
&pRtctResult->un.ge_result.channelAMismatch, &pRtctResult->un.ge_result.channelAPairBusy)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL A]: Status 0x%04X\n", __FUNCTION__, channel_status);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, 0x802A, &channel_status)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_rtctStatus_convert(channel_status,
|
||||||
|
&pRtctResult->un.ge_result.channelBShort, &pRtctResult->un.ge_result.channelBOpen,
|
||||||
|
&pRtctResult->un.ge_result.channelBMismatch, &pRtctResult->un.ge_result.channelBPairBusy)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL B]: Status 0x%04X\n", __FUNCTION__, channel_status);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, 0x802E, &channel_status)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_rtctStatus_convert(channel_status,
|
||||||
|
&pRtctResult->un.ge_result.channelCShort, &pRtctResult->un.ge_result.channelCOpen,
|
||||||
|
&pRtctResult->un.ge_result.channelCMismatch, &pRtctResult->un.ge_result.channelCPairBusy)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL C]: Status 0x%04X\n", __FUNCTION__, channel_status);
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_sram_get(unit, port, 0x8032, &channel_status)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
if ((ret = _phy_8224_rtctStatus_convert(channel_status,
|
||||||
|
&pRtctResult->un.ge_result.channelDShort, &pRtctResult->un.ge_result.channelDOpen,
|
||||||
|
&pRtctResult->un.ge_result.channelDMismatch, &pRtctResult->un.ge_result.channelDPairBusy)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PORT), "%s[CHANNEL D]: Status 0x%04X\n", __FUNCTION__, channel_status);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_intr_enable(rtk_port_t port, uint32 enable)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData, bit_idx;
|
||||||
|
rtk_port_t base_port = 0;
|
||||||
|
uint8 port_offset = 0;
|
||||||
|
uint32 unit = 0;
|
||||||
|
|
||||||
|
base_port = _phy_8224_base_port_get(unit, port);
|
||||||
|
if ((ret = phy_8224_get_port_offset(base_port, port, &port_offset)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (enable == DISABLED)
|
||||||
|
phyData = 0;
|
||||||
|
else
|
||||||
|
phyData = 1;
|
||||||
|
|
||||||
|
bit_idx = (RTL8224_IMR_EXT_GPHY_3_0_OFFSET + port_offset);
|
||||||
|
ret = _phy_8224_intRegBit_set(unit, port, RTL8224_IMR_EXT_GPHY, bit_idx, phyData);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
_phy_8224_intr_read_clear(rtk_port_t port, uint32 *pStatus)
|
||||||
|
{
|
||||||
|
int32 ret = RT_ERR_OK;
|
||||||
|
uint32 phyData = 0;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
uint8 port_offset;
|
||||||
|
uint32 unit = 0;
|
||||||
|
|
||||||
|
base_port = _phy_8224_base_port_get(unit, port);
|
||||||
|
if ((ret = phy_8224_get_port_offset(base_port, port, &port_offset)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
/* Read and Clear */
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA43A, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Clean ISR_EXT_GPHY */
|
||||||
|
/* Write 1 to clear */
|
||||||
|
if ((ret = _phy_8224_intRegBit_set(unit, port, RTL8224_ISR_EXT_GPHY, port_offset, 1)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*pStatus = phyData;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_sdsReg_set(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 data)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
return phy_rtl8224_sdsReg_set(unit, base_port, sdsPage, sdsReg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_sdsOpCode_set(uint32 unit, rtk_port_t port, uint32 opCode)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
|
||||||
|
return _phy_8224_sdsRegField_set(unit, base_port, PHY_8224_NWAY_OPCODE_PAGE, PHY_8224_NWAY_OPCODE_REG, PHY_8224_NWAY_OPCODE_HIGH_BIT, PHY_8224_NWAY_OPCODE_LOW_BIT, opCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_sdsAmPeriod_set(uint32 unit, rtk_port_t port, uint32 amPeriod)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
|
||||||
|
return _phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PERIOD_PAGE, PHY_8224_AM_PERIOD_REG, PHY_8224_AM_PERIOD_HIGH_BIT, PHY_8224_AM_PERIOD_LOW_BIT, amPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_sdsAllAm_set(uint32 unit, rtk_port_t port, uint32 value)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
/* AM0 */
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG0_REG, PHY_8224_AM0_M0_HIGH_BIT, PHY_8224_AM0_M0_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG0_REG, PHY_8224_AM0_M1_HIGH_BIT, PHY_8224_AM0_M1_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG1_REG, PHY_8224_AM0_M2_HIGH_BIT, PHY_8224_AM0_M2_LOW_BIT, value);
|
||||||
|
/* AM1 */
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG1_REG, PHY_8224_AM1_M0_HIGH_BIT, PHY_8224_AM1_M0_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG2_REG, PHY_8224_AM1_M1_HIGH_BIT, PHY_8224_AM1_M1_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG2_REG, PHY_8224_AM1_M2_HIGH_BIT, PHY_8224_AM1_M2_LOW_BIT, value);
|
||||||
|
/* AM2 */
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG3_REG, PHY_8224_AM2_M0_HIGH_BIT, PHY_8224_AM2_M0_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG3_REG, PHY_8224_AM2_M1_HIGH_BIT, PHY_8224_AM2_M1_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG4_REG, PHY_8224_AM2_M2_HIGH_BIT, PHY_8224_AM2_M2_LOW_BIT, value);
|
||||||
|
/* AM3 */
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG4_REG, PHY_8224_AM3_M0_HIGH_BIT, PHY_8224_AM3_M0_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG5_REG, PHY_8224_AM3_M1_HIGH_BIT, PHY_8224_AM3_M1_LOW_BIT, value);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PAGE, PHY_8224_AM_CFG5_REG, PHY_8224_AM3_M2_HIGH_BIT, PHY_8224_AM3_M2_LOW_BIT, value);
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_sdsExtra_set(uint32 unit, rtk_port_t port)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_AM_PERIOD_PAGE, PHY_8224_TGR_PRO_0_REG17, PHY_8224_USXG_V2P1P2_RXOFF_HIGH_BIT, PHY_8224_USXG_V2P1P2_RXOFF_LOW_BIT, 0x1);
|
||||||
|
_phy_8224_sdsRegField_set(unit, base_port, PHY_8224_NWAY_OPCODE_PAGE, PHY_8224_TGR_PRO_1_REG19, PHY_8224_USXG_RXDV_OFF_HIGH_BIT, PHY_8224_USXG_RXDV_OFF_LOW_BIT, 0x1);
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function Name:
|
||||||
|
* phy_8224_chipVer_get
|
||||||
|
* Description:
|
||||||
|
* Set PHY registers.
|
||||||
|
* Input:
|
||||||
|
* unit - unit id
|
||||||
|
* port - port id
|
||||||
|
* Output:
|
||||||
|
* pVer - chip version
|
||||||
|
* Return:
|
||||||
|
* RT_ERR_OK - OK
|
||||||
|
* RT_ERR_FAILED - Failed
|
||||||
|
* Note:
|
||||||
|
* NA
|
||||||
|
*/
|
||||||
|
int32
|
||||||
|
phy_8224_chipVer_get(uint32 unit, rtk_port_t port, uint32 *pVer)
|
||||||
|
{
|
||||||
|
int32 ret;
|
||||||
|
uint32 regData;
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, 0xbb00000c, 19, 16, 0xa)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_intReg_get(unit, port, 0xbb00000c, 31, 28, ®Data)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*pVer = regData;
|
||||||
|
|
||||||
|
if ((ret = _phy_8224_intReg_set(unit, port, 0xbb00000c, 19, 16, 0x0)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_linkDownPowerSavingEnable_set(uint32 unit, rtk_port_t port, rtk_enable_t enable)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 phyData = 0;
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA430, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
phyData &= (~BIT_2);
|
||||||
|
phyData |= (enable == DISABLED) ? (0) : (BIT_2);
|
||||||
|
if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA430, phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_linkDownPowerSavingEnable_get(uint32 unit, rtk_port_t port, rtk_enable_t *pEnable)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 phyData = 0;
|
||||||
|
|
||||||
|
if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA430, &phyData)) != RT_ERR_OK)
|
||||||
|
return ret;
|
||||||
|
*pEnable = (phyData & BIT_2) ? (ENABLED) : (DISABLED);
|
||||||
|
|
||||||
|
return RT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
phy_8224_get_port_offset(rtk_port_t baseId, rtk_port_t port, uint8 *offset)
|
||||||
|
{
|
||||||
|
*offset = (uint8)((port->mdio.addr) - (baseId->mdio.addr));
|
||||||
|
if(*offset >= RTL8224_PORT_NUM)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
phy_8224_sdsReg_get(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 *pData)
|
||||||
|
{
|
||||||
|
struct rtl8224_priv_info *priv = (struct rtl8224_priv_info *)port->priv;
|
||||||
|
rtk_port_t base_port;
|
||||||
|
|
||||||
|
base_port = priv->basePort;
|
||||||
|
|
||||||
|
return phy_rtl8224_sdsReg_get(unit, base_port, sdsPage, sdsReg, pData);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
231
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl8224.h
Normal file
231
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl8224.h
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Realtek Semiconductor Corp.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is the proprietary software of Realtek Semiconductor
|
||||||
|
* Corporation and/or its licensors, and only be used, duplicated,
|
||||||
|
* modified or distributed under the authorized license from Realtek.
|
||||||
|
*
|
||||||
|
* ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
|
||||||
|
* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||||
|
*
|
||||||
|
* $Revision: $
|
||||||
|
* $Date: $
|
||||||
|
*
|
||||||
|
* Purpose : PHY 8224 Driver APIs.
|
||||||
|
*
|
||||||
|
* Feature : PHY 8224 Driver APIs.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __HAL_PHY_PHY_RTL8224_H__
|
||||||
|
#define __HAL_PHY_PHY_RTL8224_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbol Definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data Declaration
|
||||||
|
*/
|
||||||
|
//extern rt_phyInfo_t phy_8224_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro Declaration
|
||||||
|
*/
|
||||||
|
#define RTL8224_PORT_NUM (4)
|
||||||
|
#define RTL8224_PER_PORT_MAX_LED (4)
|
||||||
|
#define RTL8224_LED_PAD_MAX_INDEX (29)
|
||||||
|
|
||||||
|
|
||||||
|
#define RTL8224_INTER_REG_LSB (0)
|
||||||
|
#define RTL8224_INTER_REG_MSB (31)
|
||||||
|
|
||||||
|
#define RTL8224_PHY_MDI_REVERSE 0xbb000a90
|
||||||
|
#define RTL8224_MDI_REVERSE_OFFSET (0)
|
||||||
|
|
||||||
|
#define RTL8224_PHY_TX_POLARITY_SWAP 0xbb000a94
|
||||||
|
#define RTL8224_PHY_TX_POLARITY_SWAP_OFFSET (4)
|
||||||
|
|
||||||
|
#define RTL8224_CFG_PHY_POLL_CMD1_REG (0xbb000ad8)
|
||||||
|
#define RTL8224_CMD_RD_EN_3_0_MSB (3)
|
||||||
|
#define RTL8224_CMD_RD_EN_3_0_LSB (0)
|
||||||
|
|
||||||
|
|
||||||
|
/* Internal Register */
|
||||||
|
/* Global interrupt control */
|
||||||
|
#define PHY_8224_INT_MODE_HIGH_LEVEL (0)
|
||||||
|
#define PHY_8224_INT_MODE_LOW_LEVEL (1)
|
||||||
|
#define PHY_8224_INT_MODE_POS_EDGE (2)
|
||||||
|
#define PHY_8224_INT_MODE_NEG_EDGE (3)
|
||||||
|
|
||||||
|
#define RTL8224_ISR_SW_INT_MODE 0xbb005f84
|
||||||
|
#define RTL8224_SWITCH_IE_OFFSET (6)
|
||||||
|
#define RTL8224_SWITCH_INT_MODE_OFFSET (1)
|
||||||
|
#define RTL8224_SWITCH_INT_MODE_MSB (2)
|
||||||
|
|
||||||
|
/* GPHY interrupt control */
|
||||||
|
#define RTL8224_IMR_EXT_GPHY 0xbb005f5c
|
||||||
|
#define RTL8224_IMR_EXT_GPHY_3_0_OFFSET (0)
|
||||||
|
#define RTL8224_IMR_EXT_GPHY_3_0_MSB (3)
|
||||||
|
|
||||||
|
#define RTL8224_ISR_EXT_GPHY 0xbb005fb0
|
||||||
|
#define RTL8224_ISR_EXT_GPHY_OFFSET (0)
|
||||||
|
#define RTL8224_ISR_EXT_GPHY_MSB (3)
|
||||||
|
|
||||||
|
#define RTL8224_IMR_EXT_WOL 0xbb005f68
|
||||||
|
#define RTL8224_IMR_EXT_PHYWOL_PORT_3_0_OFFSET (9)
|
||||||
|
#define RTL8224_IMR_EXT_PHYWOL_PORT_3_0_MSB (12)
|
||||||
|
|
||||||
|
#define RTL8224_IMR_INT_RLFD 0xbb005f40
|
||||||
|
#define RTL8224_IMR_INT_RLFD_PORT_8_0_OFFSET (0)
|
||||||
|
|
||||||
|
#define RTL8224_IMR_EXT_RLFD 0xbb005f64
|
||||||
|
#define RTL8224_IMR_EXT_RLFD_PORT_8_0_OFFSET (0)
|
||||||
|
#define RTL8224_IMR_EXT_RLFD_PORT_SHIFT (4)
|
||||||
|
|
||||||
|
#define RTL8224_GPHY_INTR_STATUS_REG (0xbb00a43a)
|
||||||
|
#define GPHY_AN_ERROR_BIT (0)
|
||||||
|
#define GPHY_AN_NEXT_PAGE_RECEIVE_BIT (2)
|
||||||
|
#define GPHY_LINK_CHG_BIT (4)
|
||||||
|
#define GPHY_ALDPS_STS_CHG_BIT (9)
|
||||||
|
#define GPHY_FATEL_ERROR_BIT (11)
|
||||||
|
|
||||||
|
#define RTL8224_ISR_INT_TM_RLFD_REG (0xbb005f94)
|
||||||
|
#define RTL8224_ISR_INT_RLFD_PORT_8_0_OFFSET (0)
|
||||||
|
#define RTL8224_ISR_INT_RLFD_PORT_8_0_MSB (8)
|
||||||
|
|
||||||
|
#define RTL8224_ISR_EXT_TM_RLFD_REG (0xbb005fb8)
|
||||||
|
#define RTL8224_ISR_EXT_RLFD_PORT_8_0_OFFSET (0)
|
||||||
|
#define RTL8224_ISR_EXT_RLFD_PORT_8_0_MSB (8)
|
||||||
|
#define RTL8224_ISR_EXT_RLFD_PORT_SHIFT (4)
|
||||||
|
|
||||||
|
#define RTL8224_RLFD_CTRL_REG (0xbb006458)
|
||||||
|
#define RTL8224_RLFD_SEL_OFFSET (10)
|
||||||
|
#define RTL8224_RLFD_EN_OFFSET (9)
|
||||||
|
|
||||||
|
#define PHY_RTL8224_VER_A (0)
|
||||||
|
#define PHY_RTL8224_VER_B (1)
|
||||||
|
#define PHY_RTL8224_VER_C (2)
|
||||||
|
|
||||||
|
#define PHY_8224_NWAY_OPCODE_PAGE (0x7)
|
||||||
|
#define PHY_8224_NWAY_OPCODE_REG (16)
|
||||||
|
#define PHY_8224_NWAY_OPCODE_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_NWAY_OPCODE_LOW_BIT (0)
|
||||||
|
|
||||||
|
#define PHY_8224_NWAY_OPCODE_PAGE (0x7)
|
||||||
|
#define PHY_8224_TGR_PRO_1_REG19 (19)
|
||||||
|
#define PHY_8224_USXG_RXDV_OFF_HIGH_BIT (12)
|
||||||
|
#define PHY_8224_USXG_RXDV_OFF_LOW_BIT (12)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PERIOD_PAGE (0x6)
|
||||||
|
#define PHY_8224_TGR_PRO_0_REG17 (17)
|
||||||
|
#define PHY_8224_USXG_V2P1P2_RXOFF_HIGH_BIT (13)
|
||||||
|
#define PHY_8224_USXG_V2P1P2_RXOFF_LOW_BIT (13)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PERIOD_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_PERIOD_REG (18)
|
||||||
|
#define PHY_8224_AM_PERIOD_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM_PERIOD_LOW_BIT (0)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_CFG0_REG (19)
|
||||||
|
#define PHY_8224_AM0_M0_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_AM0_M0_LOW_BIT (0)
|
||||||
|
#define PHY_8224_AM0_M1_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM0_M1_LOW_BIT (8)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_CFG1_REG (20)
|
||||||
|
#define PHY_8224_AM0_M2_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_AM0_M2_LOW_BIT (0)
|
||||||
|
#define PHY_8224_AM1_M0_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM1_M0_LOW_BIT (8)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_CFG2_REG (21)
|
||||||
|
#define PHY_8224_AM1_M1_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_AM1_M1_LOW_BIT (0)
|
||||||
|
#define PHY_8224_AM1_M2_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM1_M2_LOW_BIT (8)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_CFG3_REG (22)
|
||||||
|
#define PHY_8224_AM2_M0_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_AM2_M0_LOW_BIT (0)
|
||||||
|
#define PHY_8224_AM2_M1_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM2_M1_LOW_BIT (8)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_CFG4_REG (23)
|
||||||
|
#define PHY_8224_AM2_M2_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_AM2_M2_LOW_BIT (0)
|
||||||
|
#define PHY_8224_AM3_M0_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM3_M0_LOW_BIT (8)
|
||||||
|
|
||||||
|
#define PHY_8224_AM_PAGE (0x6)
|
||||||
|
#define PHY_8224_AM_CFG5_REG (24)
|
||||||
|
#define PHY_8224_AM3_M1_HIGH_BIT (7)
|
||||||
|
#define PHY_8224_AM3_M1_LOW_BIT (0)
|
||||||
|
#define PHY_8224_AM3_M2_HIGH_BIT (15)
|
||||||
|
#define PHY_8224_AM3_M2_LOW_BIT (8)
|
||||||
|
|
||||||
|
#define PHY_8224_NWAY_AN_PAGE (0x7)
|
||||||
|
#define PHY_8224_NWAY_AN_REG (17)
|
||||||
|
#define PHY_8224_QHSG_AN_CH3_EN_BIT (3)
|
||||||
|
#define PHY_8224_QHSG_AN_CH2_EN_BIT (2)
|
||||||
|
#define PHY_8224_QHSG_AN_CH1_EN_BIT (1)
|
||||||
|
#define PHY_8224_QHSG_AN_CH0_EN_BIT (0)
|
||||||
|
|
||||||
|
#define RTL8224_RTCT_LEN_OFFSET (620)
|
||||||
|
#define RTL8224_RTCT_LEN_CABLE_FACTOR (780)
|
||||||
|
|
||||||
|
/* tapbin def bitmask */
|
||||||
|
#define RTL8224_TAPBIN_DEF_OFFSET (8)
|
||||||
|
#define RTL8224_TAPBIN_DEF_BITMASK (0x00000F00)
|
||||||
|
|
||||||
|
#define PHY_8224_RLFD_ENABLE_OFFSET (15)
|
||||||
|
|
||||||
|
#define INVALID_BASE_PORT_PHY_ADDRESS (255)
|
||||||
|
#define RTL8224_BASE_PORT_OFFSET (0)
|
||||||
|
#define RTL8224_MDI_PIN_SWAP (1)
|
||||||
|
#define RTL8224_MDI_PAIR_SWAP (0)
|
||||||
|
#define RT_ERR_PHY_RTCT_NOT_FINISH (-2)
|
||||||
|
|
||||||
|
struct rtl8224_priv_info
|
||||||
|
{
|
||||||
|
rtk_phylib_phy_t phytype;
|
||||||
|
struct phy_device * basePort;
|
||||||
|
struct phy_device * memberPort[RTL8224_PORT_NUM];
|
||||||
|
int32 is_basePort;
|
||||||
|
int32 port_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern int32 phy_8224_chipVer_get(uint32 unit, rtk_port_t port, uint32 *pVer);
|
||||||
|
extern int32 phy_8224_sdsReg_get(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 *pData);
|
||||||
|
extern int32 phy_8224_sdsReg_set(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 data);
|
||||||
|
extern int32 phy_8224_sdsOpCode_set(uint32 unit, rtk_port_t port, uint32 opCode);
|
||||||
|
extern int32 phy_8224_sdsAmPeriod_set(uint32 unit, rtk_port_t port, uint32 amPeriod);
|
||||||
|
extern int32 phy_8224_sdsAllAm_set(uint32 unit, rtk_port_t port, uint32 value);
|
||||||
|
extern int32 phy_8224_sdsExtra_set(uint32 unit, rtk_port_t port);
|
||||||
|
extern int phy_8224_get_port_offset(rtk_port_t baseId, rtk_port_t port, uint8 *offset);
|
||||||
|
extern int32 phy_8224_linkDownPowerSavingEnable_set(uint32 unit, rtk_port_t port, rtk_enable_t enable);
|
||||||
|
extern int32 phy_8224_linkDownPowerSavingEnable_get(uint32 unit, rtk_port_t port, rtk_enable_t *pEnable);
|
||||||
|
extern rtk_port_t _phy_8224_get_phydevice_by_offset(int32 unit, rtk_port_t baseId, uint8 offset);
|
||||||
|
extern int32 _phy_8224_tx_polarity_swap_set(rtk_port_t port, uint32 value);
|
||||||
|
extern int32 _phy_8224_mdi_reverse_set(rtk_port_t port, uint32 value);
|
||||||
|
extern int32 _phy_8224_common_c45_enable_get(uint32 unit, rtk_port_t port, rtk_enable_t *pEnable);
|
||||||
|
extern int32 _phy_8224_common_c45_speedDuplexStatusResReg_get(uint32 unit, rtk_port_t port, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex);
|
||||||
|
extern int32 _phy_8224_intr_enable(rtk_port_t port, uint32 enable);
|
||||||
|
extern int32 _phy_8224_intr_read_clear(rtk_port_t port, uint32 *pStatus);
|
||||||
|
extern int32 _phy_8224_interrupt_init(uint32 unit, rtk_port_t port);
|
||||||
|
extern int32 _phy_8224_rtctResult_get(uint32 unit, rtk_port_t port, rtk_rtctResult_t *pRtctResult);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __HAL_PHY_PHY_RTL8224_H__ */
|
||||||
572
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl826xb.c
Normal file
572
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl826xb.c
Normal file
|
|
@ -0,0 +1,572 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rtk_phylib_rtl826xb.h"
|
||||||
|
|
||||||
|
/* Indirect Register Access APIs */
|
||||||
|
int rtk_phylib_826xb_sds_read(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 op = (page & 0x3f) | ((reg & 0x1f) << 6) | (0x8000);
|
||||||
|
uint32 i = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
mask = UINT32_BITS_MASK(msb,lsb);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 323, 15, 0, op));
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 323, 15, 15, &rData));
|
||||||
|
if (rData == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rtk_phylib_udelay(10);
|
||||||
|
}
|
||||||
|
if (i == 10)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 322, 15, 0, &rData));
|
||||||
|
*pData = REG32_FIELD_GET(rData, lsb, mask);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_sds_write(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 wData = 0, rData = 0;
|
||||||
|
uint32 op = (page & 0x3f) | ((reg & 0x1f) << 6) | (0x8800);
|
||||||
|
uint32 mask = 0;
|
||||||
|
mask = UINT32_BITS_MASK(msb,lsb);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_sds_read(phydev, page, reg, 15, 0, &rData));
|
||||||
|
|
||||||
|
wData = REG32_FIELD_SET(rData, data, lsb, mask);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 321, 15, 0, wData));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 323, 15, 0, op));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_indirect_read(rtk_phydev *phydev, uint32 indr_addr, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 rData;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA436, 15, 0, indr_addr));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xA438, 15, 0, &rData));
|
||||||
|
*pData = rData;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_sram_read(rtk_phydev *phydev, uint32 indr_addr, uint8 msb, uint8 lsb, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 mask = 0, rData = 0;
|
||||||
|
|
||||||
|
mask = UINT32_BITS_MASK(msb,lsb);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_indirect_read(phydev, indr_addr, &rData));
|
||||||
|
*pData = REG32_FIELD_GET(rData, lsb, mask);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MACsec */
|
||||||
|
int rtk_phylib_826xb_macsec_read(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 data_h = 0, data_l = 0;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 mask = 0;
|
||||||
|
uint32 data_e = 0;
|
||||||
|
WAIT_COMPLETE_VAR();
|
||||||
|
|
||||||
|
mask = UINT32_BITS_MASK(msb,lsb);
|
||||||
|
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case RTK_MACSEC_DIR_EGRESS:
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02FB, 15, 0, reg));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02FC, 15, 0, 0x10));
|
||||||
|
WAIT_COMPLETE(10000000)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x02FC, 15, 0, &data_e));
|
||||||
|
if ((data_e & 0x10) == 0x0)
|
||||||
|
{
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
if (_t_wait != 0)
|
||||||
|
PR_DBG("[%s-%u] _t_wait: %u\n", __FUNCTION__, dir, _t_wait);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WAIT_COMPLETE_IS_TIMEOUT())
|
||||||
|
{
|
||||||
|
PR_ERR("[%s-%u] timeout!\n", __FUNCTION__, dir);
|
||||||
|
return RTK_PHYLIB_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x02F8, 15, 0, &data_h));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x02F9, 15, 0, &data_l));
|
||||||
|
break;
|
||||||
|
case RTK_MACSEC_DIR_INGRESS:
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA6EA, 1, 1, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x0300, 15, 0, reg));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x0301, 15, 0, 0x10));
|
||||||
|
WAIT_COMPLETE(10000000)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x0301, 15, 0, &data_e));
|
||||||
|
if ((data_e & 0x10) == 0x0)
|
||||||
|
{
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
if (_t_wait != 0)
|
||||||
|
PR_DBG("[%s-%u] _t_wait: %u\n", __FUNCTION__, dir, _t_wait);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WAIT_COMPLETE_IS_TIMEOUT())
|
||||||
|
{
|
||||||
|
PR_ERR("[%s-%u] timeout!\n", __FUNCTION__, dir);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA6EA, 1, 1, 0x0));
|
||||||
|
return RTK_PHYLIB_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x02FD, 15, 0, &data_h));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x02FE, 15, 0, &data_l));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA6EA, 1, 1, 0x0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rData = (data_h << 16) + data_l;
|
||||||
|
*pData = REG32_FIELD_GET(rData, lsb, mask);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_macsec_write(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 reg, uint8 msb, uint8 lsb, uint32 data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 data_l = data & 0xFFFF;
|
||||||
|
uint32 data_h = (data >> 16) & 0xFFFF;
|
||||||
|
uint32 data_e = 0;
|
||||||
|
WAIT_COMPLETE_VAR();
|
||||||
|
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case RTK_MACSEC_DIR_EGRESS:
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02F8 , 15, 0, data_h));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02F9 , 15, 0, data_l));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02FB , 15, 0, reg));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02FC, 15, 0, 0x1));
|
||||||
|
WAIT_COMPLETE(10000000)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x02FC, 15, 0, &data_e));
|
||||||
|
if ((data_e & 0x1) == 0x0)
|
||||||
|
{
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
if (_t_wait != 0)
|
||||||
|
PR_DBG("[%s-%u] _t_wait: %u\n", __FUNCTION__, dir, _t_wait);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WAIT_COMPLETE_IS_TIMEOUT())
|
||||||
|
{
|
||||||
|
PR_ERR("[%s-%u] timeout!\n", __FUNCTION__, dir);
|
||||||
|
return RTK_PHYLIB_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTK_MACSEC_DIR_INGRESS:
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA6EA, 1, 1, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02FD, 15, 0, data_h));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x02FE, 15, 0, data_l));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x0300, 15, 0, reg));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x0301, 15, 0, 0x1));
|
||||||
|
WAIT_COMPLETE(10000000)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x0301, 15, 0, &data_e));
|
||||||
|
if ((data_e & 0x1) == 0x0)
|
||||||
|
{
|
||||||
|
#ifdef MACSEC_DBG_PRINT
|
||||||
|
if (_t_wait != 0)
|
||||||
|
PR_DBG("[%s-%u] _t_wait: %u\n", __FUNCTION__, dir, _t_wait);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WAIT_COMPLETE_IS_TIMEOUT())
|
||||||
|
{
|
||||||
|
PR_ERR("[%s-%u] timeout!\n", __FUNCTION__, dir);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA6EA, 1, 1, 0x0));
|
||||||
|
return RTK_PHYLIB_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA6EA, 1, 1, 0x0));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RTK_PHYLIB_ERR_INPUT;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_macsec_init(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2e0, 1, 0, 0b11));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2d8, 15, 0, 0x5313));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2da, 15, 0, 0x0101));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2dc, 15, 0, 0x0101));
|
||||||
|
|
||||||
|
//MACSEC_RXSYS_CFG4
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3c6, 7, 0, 0xa));
|
||||||
|
//MACSEC_TXLINE_CFG4
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x37b, 7, 0, 0x6));
|
||||||
|
//loopback fifo_setting
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2f7, 15, 0, 0x486c));
|
||||||
|
//RA_setting
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3f1, 15, 0, 0x72));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3f0, 15, 0, 0x0b0b));
|
||||||
|
//RA ifg
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3ee, 15, 13, 0x2));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_macsec_bypass_set(rtk_phydev *phydev, uint32 bypass)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
if (bypass != 0)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2d8, 15, 0, 0x5313));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3f1, 15, 0, 0x72));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3f0, 15, 0, 0x0b0b));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x398, 2, 0, 0x7));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2d8, 15, 0, 0x5111));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3f1, 15, 0, 0xe871));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x3f0, 15, 0, 0x0c0c));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x398, 2, 0, 0x5));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_macsec_bypass_get(rtk_phydev *phydev, uint32 *pBypass)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 bypass_rx = 0;
|
||||||
|
uint32 bypass_tx = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x2d8, 9, 9, &bypass_rx));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0x2d8, 1, 1, &bypass_tx));
|
||||||
|
|
||||||
|
*pBypass = (bypass_rx == 0 && bypass_tx == 0) ? 0 : 1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTCT */
|
||||||
|
int rtk_phylib_826xb_cable_test_start(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xa4a0, 10, 10, 1));
|
||||||
|
rtk_phylib_mdelay(1000);
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xa422, 15, 0, 0xF2));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xa422, 0, 0, 1));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_cable_test_finished_get(rtk_phydev *phydev, uint32 *finished)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 rData = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xA422, 15, 15, &rData));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xa4a0, 10, 10, 0));
|
||||||
|
*finished = rData;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_cable_test_result_get(rtk_phydev *phydev, uint32 pair, rtk_rtct_channel_result_t *result)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 cable_factor = 7820;
|
||||||
|
uint32 cable_offset = 585;
|
||||||
|
uint32 indr_add_ss = 0x8027 + (pair * 0x4);
|
||||||
|
uint32 indr_add_lh = 0x8028 + (pair * 0x4);
|
||||||
|
uint32 indr_add_ll = 0x8029 + (pair * 0x4);
|
||||||
|
uint32 rtct_status = 0;
|
||||||
|
uint32 rtct_len_h = 0;
|
||||||
|
uint32 rtct_len_l = 0;
|
||||||
|
int32 len_cnt = 0;
|
||||||
|
|
||||||
|
if (pair > 3)
|
||||||
|
return RTK_PHYLIB_ERR_INPUT;
|
||||||
|
|
||||||
|
rtk_phylib_memset(result, 0x0, sizeof(rtk_rtct_channel_result_t));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_sram_read(phydev, indr_add_ss, 15, 8, &rtct_status));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_sram_read(phydev, indr_add_lh, 15, 8, &rtct_len_h));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_sram_read(phydev, indr_add_ll, 15, 8, &rtct_len_l));
|
||||||
|
|
||||||
|
result->cable_status = RTK_PHYLIB_CABLE_STATUS_NORMAL;
|
||||||
|
switch (rtct_status)
|
||||||
|
{
|
||||||
|
case 0x60: /* normal */
|
||||||
|
result->cable_status = RTK_PHYLIB_CABLE_STATUS_NORMAL;
|
||||||
|
break;
|
||||||
|
case 0x48: /* open */
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_OPEN;
|
||||||
|
break;
|
||||||
|
case 0x50: /* short */
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_SHORT;
|
||||||
|
break;
|
||||||
|
case 0xC0: /* inter pair short */
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_INTER_PAIR_SHORT;
|
||||||
|
break;
|
||||||
|
case 0x42: /* mismatch-open */
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_MISMATCH;
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_OPEN;
|
||||||
|
break;
|
||||||
|
case 0x44: /* mismatch-short */
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_MISMATCH;
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_SHORT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result->cable_status |= RTK_PHYLIB_CABLE_STATUS_INTER_PAIR_SHORT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
len_cnt = ((int32)rtct_len_h << 8) + (int32)rtct_len_l - cable_offset;
|
||||||
|
if (len_cnt < 0)
|
||||||
|
result->length_cm = 0;
|
||||||
|
else
|
||||||
|
result->length_cm = ((uint32)len_cnt * 10000)/cable_factor;
|
||||||
|
|
||||||
|
if ((rtct_status == 0x60) && (result->length_cm < 1500)) //status is normal && length < 15M
|
||||||
|
result->length_cm = result->length_cm/2;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interrupt */
|
||||||
|
int rtk_phylib_826xb_intr_enable(rtk_phydev *phydev, uint32 en)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
/* enable normal interrupt IMR_INT_PHY0 */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0xE1, 0, 0, (en == 0) ? 0x0 : 0x1));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_intr_read_clear(rtk_phydev *phydev, uint32 *status)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 rData = 0;
|
||||||
|
uint32 rStatus = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xA43A, 15, 0, &rData));
|
||||||
|
if(rData & BIT_1)
|
||||||
|
rStatus |= RTK_PHY_INTR_RLFD;
|
||||||
|
if(rData & BIT_2)
|
||||||
|
rStatus |= RTK_PHY_INTR_NEXT_PAGE_RECV;
|
||||||
|
if(rData & BIT_3)
|
||||||
|
rStatus |= RTK_PHY_INTR_AN_COMPLETE;
|
||||||
|
if(rData & BIT_4)
|
||||||
|
rStatus |= RTK_PHY_INTR_LINK_CHANGE;
|
||||||
|
if(rData & BIT_9)
|
||||||
|
rStatus |= RTK_PHY_INTR_ALDPS_STATE_CHANGE;
|
||||||
|
if(rData & BIT_11)
|
||||||
|
rStatus |= RTK_PHY_INTR_FATAL_ERROR;
|
||||||
|
if(rData & BIT_7)
|
||||||
|
rStatus |= RTK_PHY_INTR_WOL;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 0xE2, 15, 0, &rData));
|
||||||
|
if(rData & BIT_3)
|
||||||
|
rStatus |= RTK_PHY_INTR_TM_LOW;
|
||||||
|
if(rData & BIT_4)
|
||||||
|
rStatus |= RTK_PHY_INTR_TM_HIGH;
|
||||||
|
if(rData & BIT_6)
|
||||||
|
rStatus |= RTK_PHY_INTR_MACSEC;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0xE2, 15, 0, 0xFF));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x2DC, 15, 0, 0xFF));
|
||||||
|
|
||||||
|
*status = rStatus;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_intr_init(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 status = 0;
|
||||||
|
|
||||||
|
/* Disable all IMR*/
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0xE1, 15, 0, 0));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0xE3, 15, 0, 0));
|
||||||
|
|
||||||
|
/* source */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0xE4, 15, 0, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0xE0, 15, 0, 0x2F));
|
||||||
|
|
||||||
|
/* init common link change */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA424, 15, 0, 0x10));
|
||||||
|
/* init rlfd */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA442, 15, 15, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA448, 7, 7, 0x1));
|
||||||
|
/* init tm */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x1A0, 11, 11, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x19D, 11, 11, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x1A1, 11, 11, 0x1));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 0x19F, 11, 11, 0x1));
|
||||||
|
/* init WOL */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA424, 7, 7, 0x1));
|
||||||
|
|
||||||
|
/* clear status */
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_intr_read_clear(phydev, &status));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_link_down_power_saving_set(rtk_phydev *phydev, uint32 ena)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 data = (ena > 0) ? 0x1 : 0x0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xA430, 2, 2, data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_link_down_power_saving_get(rtk_phydev *phydev, uint32 *pEna)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 data = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xA430, 2, 2, &data));
|
||||||
|
*pEna = data;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_wol_reset(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A2, 15, 15, 0));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A2, 15, 15, 1));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_wol_set(rtk_phydev *phydev, uint32 wol_opts)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A0, 13, 13, (wol_opts & RTK_WOL_OPT_LINK) ? 1 : 0));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A0, 12, 12, (wol_opts & RTK_WOL_OPT_MAGIC) ? 1 : 0));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A0, 10, 10, (wol_opts & RTK_WOL_OPT_UCAST) ? 1 : 0));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A0, 9, 9, (wol_opts & RTK_WOL_OPT_MCAST) ? 1 : 0));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8A0, 8, 8, (wol_opts & RTK_WOL_OPT_BCAST) ? 1 : 0));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_wol_get(rtk_phydev *phydev, uint32 *pWol_opts)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 data = 0;
|
||||||
|
uint32 wol_opts = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xD8A0, 13, 13, &data));
|
||||||
|
wol_opts |= ((data) ? RTK_WOL_OPT_LINK : 0);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xD8A0, 12, 12, &data));
|
||||||
|
wol_opts |= ((data) ? RTK_WOL_OPT_MAGIC : 0);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xD8A0, 10, 10, &data));
|
||||||
|
wol_opts |= ((data) ? RTK_WOL_OPT_UCAST : 0);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xD8A0, 9, 9, &data));
|
||||||
|
wol_opts |= ((data) ? RTK_WOL_OPT_MCAST : 0);
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, 0xD8A0, 8, 8, &data));
|
||||||
|
wol_opts |= ((data) ? RTK_WOL_OPT_BCAST : 0);
|
||||||
|
|
||||||
|
*pWol_opts = wol_opts;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_wol_unicast_addr_set(rtk_phydev *phydev, uint8 *mac_addr)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8C0, 15, 0, (mac_addr[1] << 8 | mac_addr[0])));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8C2, 15, 0, (mac_addr[3] << 8 | mac_addr[2])));
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, 0xD8C4, 15, 0, (mac_addr[5] << 8 | mac_addr[4])));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 rtk_phylib_826xb_wol_multicast_mac2offset(uint8 *mac_addr)
|
||||||
|
{
|
||||||
|
uint32 crc = 0xFFFFFFFF;
|
||||||
|
uint32 i = 0, j = 0;
|
||||||
|
uint32 b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
crc ^= mac_addr[i];
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
if (crc & 1) {
|
||||||
|
crc = (crc >> 1) ^ 0xEDB88320;
|
||||||
|
} else {
|
||||||
|
crc >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crc = ~crc;
|
||||||
|
|
||||||
|
b5 = ((crc & 0b000001) << 5 );
|
||||||
|
b4 = ((crc & 0b000010) << 3 );
|
||||||
|
b3 = ((crc & 0b000100) << 1 );
|
||||||
|
b2 = (((crc & 0b001000) ? 0 : 1) << 2 );
|
||||||
|
b1 = (((crc & 0b010000) ? 0 : 1) << 1 );
|
||||||
|
b0 = (((crc & 0b100000) ? 0 : 1) << 0 );
|
||||||
|
|
||||||
|
return (b5 | b4 | b3 | b2 | b1 | b0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_wol_multicast_mask_add(rtk_phydev *phydev, uint32 offset)
|
||||||
|
{
|
||||||
|
const uint32 cfg_reg[4] = {0xD8C6, 0xD8C8, 0xD8CA, 0xD8CC};
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 idx = offset/16;
|
||||||
|
uint32 multicast_cfg = 0;
|
||||||
|
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 31, cfg_reg[idx], 15, 0, &multicast_cfg));
|
||||||
|
|
||||||
|
multicast_cfg = (multicast_cfg | (0b1 << (offset % 16)));
|
||||||
|
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, cfg_reg[idx], 15, 0, multicast_cfg));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtk_phylib_826xb_wol_multicast_mask_reset(rtk_phydev *phydev)
|
||||||
|
{
|
||||||
|
const uint32 cfg_reg[4] = {0xD8C6, 0xD8C8, 0xD8CA, 0xD8CC};
|
||||||
|
int32 ret = 0;
|
||||||
|
uint32 idx = 0;
|
||||||
|
|
||||||
|
for (idx = 0; idx < 4; idx++)
|
||||||
|
{
|
||||||
|
RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 31, cfg_reg[idx], 15, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
46
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl826xb.h
Normal file
46
sources/rtk-gp3000/src/hal/phy/rtk_phylib_rtl826xb.h
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RTK_PHYLIB_RTL826XB_H
|
||||||
|
#define __RTK_PHYLIB_RTL826XB_H
|
||||||
|
|
||||||
|
#include "rtk_phylib.h"
|
||||||
|
|
||||||
|
/* Register Access*/
|
||||||
|
int rtk_phylib_826xb_sds_read(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData);
|
||||||
|
int rtk_phylib_826xb_sds_write(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 data);
|
||||||
|
|
||||||
|
/* Interrupt */
|
||||||
|
int rtk_phylib_826xb_intr_enable(rtk_phydev *phydev, uint32 en);
|
||||||
|
int rtk_phylib_826xb_intr_read_clear(rtk_phydev *phydev, uint32 *status);
|
||||||
|
int rtk_phylib_826xb_intr_init(rtk_phydev *phydev);
|
||||||
|
|
||||||
|
/* Cable Test */
|
||||||
|
int rtk_phylib_826xb_cable_test_start(rtk_phydev *phydev);;
|
||||||
|
int rtk_phylib_826xb_cable_test_finished_get(rtk_phydev *phydev, uint32 *finished);
|
||||||
|
int rtk_phylib_826xb_cable_test_result_get(rtk_phydev *phydev, uint32 pair, rtk_rtct_channel_result_t *result);
|
||||||
|
|
||||||
|
/* MACsec */
|
||||||
|
int rtk_phylib_826xb_macsec_init(rtk_phydev *phydev);
|
||||||
|
int rtk_phylib_826xb_macsec_read(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData);
|
||||||
|
int rtk_phylib_826xb_macsec_write(rtk_phydev *phydev, rtk_macsec_dir_t dir, uint32 reg, uint8 msb, uint8 lsb, uint32 data);
|
||||||
|
int rtk_phylib_826xb_macsec_bypass_set(rtk_phydev *phydev, uint32 bypass);
|
||||||
|
int rtk_phylib_826xb_macsec_bypass_get(rtk_phydev *phydev, uint32 *pBypass);
|
||||||
|
|
||||||
|
/* Link-down-power-saving/EDPD */
|
||||||
|
int rtk_phylib_826xb_link_down_power_saving_set(rtk_phydev *phydev, uint32 ena);
|
||||||
|
int rtk_phylib_826xb_link_down_power_saving_get(rtk_phydev *phydev, uint32 *pEna);
|
||||||
|
|
||||||
|
/* Wake on Lan */
|
||||||
|
int rtk_phylib_826xb_wol_reset(rtk_phydev *phydev);
|
||||||
|
int rtk_phylib_826xb_wol_set(rtk_phydev *phydev, uint32 wol_opts);
|
||||||
|
int rtk_phylib_826xb_wol_get(rtk_phydev *phydev, uint32 *pWol_opts);
|
||||||
|
int rtk_phylib_826xb_wol_unicast_addr_set(rtk_phydev *phydev, uint8 *mac_addr);
|
||||||
|
int rtk_phylib_826xb_wol_multicast_mask_add(rtk_phydev *phydev, uint32 offset);
|
||||||
|
int rtk_phylib_826xb_wol_multicast_mask_reset(rtk_phydev *phydev);
|
||||||
|
uint32 rtk_phylib_826xb_wol_multicast_mac2offset(uint8 *mac_addr);
|
||||||
|
|
||||||
|
#endif /* __RTK_PHYLIB_RTL826XB_H */
|
||||||
117
sources/rtk-gp3000/src/hal/phy/type.h
Normal file
117
sources/rtk-gp3000/src/hal/phy/type.h
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMMON_TYPE_H__
|
||||||
|
#define __COMMON_TYPE_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbol Definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USING_RTSTK_PKT_AS_RAIL
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ETHER_ADDR_LEN
|
||||||
|
#define ETHER_ADDR_LEN 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IP6_ADDR_LEN
|
||||||
|
#define IP6_ADDR_LEN 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data Type Declaration
|
||||||
|
*/
|
||||||
|
#ifndef uint64
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef int64
|
||||||
|
typedef signed long long int64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef uint32
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef int32
|
||||||
|
typedef signed int int32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef uint16
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef int16
|
||||||
|
typedef signed short int16;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef uint8
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef int8
|
||||||
|
typedef signed char int8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#define CONFIG_SDK_WORDSIZE_64 /* not ready */
|
||||||
|
#ifdef CONFIG_SDK_WORDSIZE_64
|
||||||
|
typedef long int intptr;
|
||||||
|
typedef unsigned long int uintptr;
|
||||||
|
#else
|
||||||
|
typedef int intptr;
|
||||||
|
typedef unsigned int uintptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ipaddr_t
|
||||||
|
typedef uint32 ipaddr_t; /* ipv4 address type */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* configuration mode type */
|
||||||
|
typedef enum rtk_enable_e
|
||||||
|
{
|
||||||
|
DISABLED = 0,
|
||||||
|
ENABLED,
|
||||||
|
RTK_ENABLE_END
|
||||||
|
} rtk_enable_t;
|
||||||
|
|
||||||
|
/* initial state of module */
|
||||||
|
typedef enum init_state_e
|
||||||
|
{
|
||||||
|
INIT_NOT_COMPLETED = 0,
|
||||||
|
INIT_COMPLETED,
|
||||||
|
INIT_STATE_END
|
||||||
|
} init_state_t;
|
||||||
|
|
||||||
|
/* ethernet address type */
|
||||||
|
typedef struct rtk_mac_s
|
||||||
|
{
|
||||||
|
uint8 octet[ETHER_ADDR_LEN];
|
||||||
|
} rtk_mac_t;
|
||||||
|
|
||||||
|
typedef uint32 osal_time_t;
|
||||||
|
typedef uint32 osal_usecs_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro Definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* __COMMON_TYPE_H__ */
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue