Merge "board: arm: devsoc: add QCA8033 ethernet PHY support"

This commit is contained in:
Linux Build Service Account 2022-07-07 05:50:44 -07:00 committed by Gerrit - the friendly Code Review server
commit ced5244d01
14 changed files with 1945 additions and 53 deletions

View file

@ -41,4 +41,14 @@ config IPQ_TINY_SPI_NOR
config ART_COMPRESSED
bool "Enable uncompress support"
config QCA8033_PHY
bool "Enable QCA8033 PHY support"
config QCA8081_PHY
bool "Enable QCA8081 PHY support"
config QCA8084_PHY
depends on QCA8081_PHY
bool "Enable QCA8084 PHY support"
endif

View file

@ -100,7 +100,11 @@ CONFIG_CMD_SETEXPR=y
#
# Network PHY
#
CONFIG_IPQ_QCA_AQUANTIA_PHY=y
CONFIG_QCA8033_PHY=y
CONFIG_QCA8081_PHY=y
CONFIG_QCA8084_PHY=y
CONFIG_ATHRS17C_SWITCH=y
CONFIG_CMD_NET=y
# CONFIG_CMD_TFTPPUT is not set

View file

@ -110,3 +110,13 @@ config ZYNQ_GEM
This MAC is present in Xilinx Zynq and ZynqMP SoCs.
endif # NETDEVICES
config IPQ_QCA_AQUANTIA_PHY
bool "Aquantia PHY support"
help
Enable Aquantia PHY support.
config ATHRS17C_SWITCH
bool "QTI S17C switch support"
help
Enable QTI S17C switch support.

View file

@ -106,9 +106,11 @@ obj-$(CONFIG_QCA8075_PHY) += ipq_common/ipq_qca8075.o
obj-$(CONFIG_QCA8084_PHY) += ipq_common/ipq_qca8084.o
obj-$(CONFIG_QCA8084_PHY) += ipq_common/ipq_qca8084_clk.o
obj-$(CONFIG_QCA8084_PHY) += ipq_common/ipq_qca8084_interface_ctrl.o
obj-$(CONFIG_ATHRS17C_SWITCH) += ipq_common/athrs17_phy.o
obj-$(CONFIG_IPQ9574_QCA8075_PHY) += ipq9574/ipq9574_qca8075.o
obj-$(CONFIG_QCA8033_PHY) += ipq_common/ipq_qca8033.o
obj-$(CONFIG_QCA8081_PHY) += ipq_common/ipq_qca8081.o
obj-$(CONFIG_IPQ_QCA_AQUANTIA_PHY) += ipq_common/ipq_aquantia_phy.o
obj-$(CONFIG_QCA_AQUANTIA_PHY) += ipq807x/ipq807x_aquantia_phy.o
obj-$(CONFIG_IPQ6018_QCA_AQUANTIA_PHY) += ipq6018/ipq6018_aquantia_phy.o
obj-$(CONFIG_IPQ9574_QCA_AQUANTIA_PHY) += ipq9574/ipq9574_aquantia_phy.o

View file

@ -18,7 +18,6 @@
**************************************************************************
*/
#include <common.h>
#include <net.h>
#include <asm-generic/errno.h>
#include <asm/io.h>
#include <malloc.h>
@ -49,9 +48,12 @@ static struct devsoc_eth_dev *devsoc_edma_dev[DEVSOC_EDMA_DEV];
uchar devsoc_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD};
phy_info_t *phy_info[DEVSOC_PHY_MAX] = {0};
phy_info_t *swt_info[QCA8084_MAX_PORTS] = {0};
int sgmii_mode[2] = {0};
#ifndef CONFIG_DEVSOC_RUMI
extern void ipq_phy_addr_fixup(void);
extern void ipq_clock_init(void);
extern int ipq_sw_mdio_init(const char *);
extern int ipq_mdio_read(int mii_id, int regnum, ushort *data);
extern void devsoc_qca8075_phy_map_ops(struct phy_ops **ops);
@ -61,9 +63,27 @@ extern int ipq_qca8033_phy_init(struct phy_ops **ops, u32 phy_id);
extern int ipq_qca8081_phy_init(struct phy_ops **ops, u32 phy_id);
extern int ipq_qca_aquantia_phy_init(struct phy_ops **ops, u32 phy_id);
extern int ipq_board_fw_download(unsigned int phy_addr);
extern int ipq_qca8084_hw_init(phy_info_t * phy_info[]);
extern int ipq_qca8084_link_update(phy_info_t * phy_info[]);
extern void ipq_qca8084_switch_hw_reset(int gpio);
#ifdef CONFIG_ATHRS17C_SWITCH
extern void ppe_uniphy_set_forceMode(uint32_t uniphy_index);
extern int ipq_qca8337_switch_init(ipq_s17c_swt_cfg_t *s17c_swt_cfg);
extern int ipq_qca8337_link_update(ipq_s17c_swt_cfg_t *s17c_swt_cfg);
extern void ipq_s17c_switch_reset(int gpio);
ipq_s17c_swt_cfg_t s17c_swt_cfg;
#endif
#endif
static int tftp_acl_our_port;
#ifndef CONFIG_DEVSOC_RUMI
#ifdef CONFIG_QCA8084_PHY
static int qca8084_swt_enb = 0;
static int qca8084_chip_detect = 0;
#endif
#endif
/*
* EDMA hardware instance
@ -902,49 +922,70 @@ static int devsoc_eth_init(struct eth_device *eth_dev, bd_t *this)
*/
for (i = 0; i < DEVSOC_PHY_MAX; i++) {
#ifndef CONFIG_DEVSOC_RUMI
if (!priv->ops[i]) {
printf("Phy ops not mapped\n");
if (phy_info[i]->phy_type == UNUSED_PHY_TYPE)
continue;
#ifdef CONFIG_QCA8084_PHY
else if ((qca8084_swt_enb && qca8084_chip_detect) &&
(phy_info[i]->phy_type == QCA8084_PHY_TYPE)) {
if (!ipq_qca8084_link_update(swt_info))
linkup++;
continue;
}
phy_get_ops = priv->ops[i];
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf("Error:Link status/Get speed/Get duplex not mapped\n");
return -1;
}
if (phy_node >= 0) {
/*
* For each ethernet port, one node should be added
* inside port_phyinfo with appropriate phy address
*/
phy_addr = phy_info[i]->phy_address;
} else {
printf("Error:Phy addresses not configured in DT\n");
return -1;
}
status = phy_get_ops->phy_get_link_status(priv->mac_unit, phy_addr);
phy_get_ops->phy_get_speed(priv->mac_unit, phy_addr, &curr_speed[i]);
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
if (status == 0) {
linkup++;
if (old_speed[i] == curr_speed[i]) {
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], curr_speed[i],
dp[duplex]);
#endif
#ifdef CONFIG_ATHRS17C_SWITCH
else if (phy_info[i]->phy_type == ATHRS17C_SWITCH_TYPE) {
if (s17c_swt_cfg.chip_detect) {
if (!ipq_qca8337_link_update(&s17c_swt_cfg))
linkup++;
continue;
}
}
#endif
else {
if (!priv->ops[i]) {
printf("Phy ops not mapped\n");
continue;
}
phy_get_ops = priv->ops[i];
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf("Error:Link status/Get speed/Get duplex not mapped\n");
return -1;
}
if (phy_node >= 0) {
/*
* For each ethernet port, one node should be added
* inside port_phyinfo with appropriate phy address
*/
phy_addr = phy_info[i]->phy_address;
} else {
printf("Error:Phy addresses not configured in DT\n");
return -1;
}
status = phy_get_ops->phy_get_link_status(priv->mac_unit, phy_addr);
phy_get_ops->phy_get_speed(priv->mac_unit, phy_addr, &curr_speed[i]);
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
if (status == 0) {
linkup++;
if (old_speed[i] == curr_speed[i]) {
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], curr_speed[i],
dp[duplex]);
continue;
} else {
old_speed[i] = curr_speed[i];
}
} else {
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], curr_speed[i],
dp[duplex]);
continue;
} else {
old_speed[i] = curr_speed[i];
}
} else {
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], curr_speed[i],
dp[duplex]);
continue;
}
#endif
@ -1631,13 +1672,14 @@ int devsoc_edma_hw_init(struct devsoc_edma_hw *ehw)
return 0;
}
void get_phy_address(int offset)
void get_phy_address(int offset, phy_info_t * phy_info[], int max_phy_ports)
{
int phy_type;
int phy_address;
int forced_speed, forced_duplex;
int i;
for (i = 0; i < DEVSOC_PHY_MAX; i++)
for (i = 0; i < max_phy_ports; i++)
phy_info[i] = devsoc_alloc_mem(sizeof(phy_info_t));
i = 0;
for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0;
@ -1646,7 +1688,13 @@ void get_phy_address(int offset)
offset, "phy_address", 0);
phy_type = fdtdec_get_uint(gd->fdt_blob,
offset, "phy_type", 0);
forced_speed = fdtdec_get_uint(gd->fdt_blob,
offset, "forced-speed", 0);
forced_duplex = fdtdec_get_uint(gd->fdt_blob,
offset, "forced-duplex", 0);
phy_info[i]->phy_address = phy_address;
phy_info[i]->forced_speed = forced_speed;
phy_info[i]->forced_duplex = forced_duplex;
phy_info[i++]->phy_type = phy_type;
}
}
@ -1666,8 +1714,15 @@ int devsoc_edma_init(void *edma_board_cfg)
#ifdef CONFIG_DEVSOC_QCA8075_PHY
static int sw_init_done = 0;
#endif
int node, phy_addr, aquantia_port[2] = {-1, -1}, aquantia_port_cnt = -1;
int mode, phy_node = -1, res = -1;
#ifdef CONFIG_QCA8084_PHY
static int qca8084_init_done = 0;
int qca8084_gpio, clk[4] = {0};
#endif
#ifdef CONFIG_ATHRS17C_SWITCH
int s17c_swt_enb = 0, s17c_rst_gpio = 0;
#endif
int node, phy_addr, mode, phy_node = -1, res = -1;
int aquantia_port[2] = {-1, -1}, aquantia_port_cnt = -1;
/*
* Init non cache buffer
@ -1687,9 +1742,50 @@ int devsoc_edma_init(void *edma_board_cfg)
}
}
#ifdef CONFIG_QCA8084_PHY
qca8084_swt_enb = fdtdec_get_uint(gd->fdt_blob, node, "qca8084_switch_enable", 0);
if (qca8084_swt_enb) {
qca8084_gpio = fdtdec_get_uint(gd->fdt_blob, node, "qca808x_gpio", 0);
if (qca8084_gpio)
ipq_qca8084_switch_hw_reset(qca8084_gpio);
}
phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/qca8084_swt_info");
if (phy_node >= 0)
get_phy_address(phy_node, swt_info, QCA8084_MAX_PORTS);
#endif
#ifdef CONFIG_ATHRS17C_SWITCH
s17c_swt_enb = fdtdec_get_uint(gd->fdt_blob, node,
"s17c_switch_enable", 0);
if (s17c_swt_enb) {
s17c_swt_cfg.chip_detect = 0;
s17c_rst_gpio = fdtdec_get_uint(gd->fdt_blob, node,
"s17c_rst_gpio", 0);
ipq_s17c_switch_reset(s17c_rst_gpio);
/*
* Set ref clock 25MHZ and enable Force mode
*/
ppe_uniphy_set_forceMode(PORT0);
phy_node = fdt_path_offset(gd->fdt_blob,
"/ess-switch/s17c_swt_info");
s17c_swt_cfg.port_count = fdtdec_get_uint(gd->fdt_blob,
phy_node, "s17c_mac_pwr", 0);
s17c_swt_cfg.port_count = fdtdec_get_uint(gd->fdt_blob,
phy_node, "s17c_port_count", 0);
fdtdec_get_int_array(gd->fdt_blob, phy_node,
"s17c_port_address",
s17c_swt_cfg.port_phy_address,
s17c_swt_cfg.port_count);
}
#endif
phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo");
if (phy_node >= 0)
get_phy_address(phy_node);
get_phy_address(phy_node, phy_info, DEVSOC_PHY_MAX);
mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode0", -1);
if (mode < 0) {
@ -1785,6 +1881,13 @@ int devsoc_edma_init(void *edma_board_cfg)
printf("Error:Phy addresses not configured in DT\n");
goto init_failed;
}
#ifdef CONFIG_QCA8084_PHY
if (phy_info[phy_id]->phy_type == QCA8084_PHY_TYPE && !qca8084_init_done) {
ipq_phy_addr_fixup();
ipq_clock_init();
qca8084_init_done = 1;
}
#endif
phy_chip_id1 = ipq_mdio_read(phy_addr, QCA_PHY_ID1, NULL);
phy_chip_id2 = ipq_mdio_read(phy_addr, QCA_PHY_ID2, NULL);
@ -1826,7 +1929,18 @@ int devsoc_edma_init(void *edma_board_cfg)
ipq_qca8081_phy_init(&devsoc_edma_dev[i]->ops[phy_id], phy_addr);
break;
#endif
#ifdef CONFIG_DEVSOC_QCA_AQUANTIA_PHY
#ifdef CONFIG_QCA8084_PHY
case QCA8084_PHY:
qca8084_chip_detect = 1;
break;
#endif
#ifdef CONFIG_ATHRS17C_SWITCH
case QCA8337_PHY:
if (s17c_swt_enb)
s17c_swt_cfg.chip_detect = 1;
break;
#endif
#ifdef CONFIG_IPQ_QCA_AQUANTIA_PHY
case AQUANTIA_PHY_107:
case AQUANTIA_PHY_109:
case AQUANTIA_PHY_111:
@ -1856,6 +1970,35 @@ int devsoc_edma_init(void *edma_board_cfg)
if (ret)
goto init_failed;
#ifndef CONFIG_DEVSOC_RUMI
#ifdef CONFIG_QCA8084_PHY
/** QCA8084 switch specific configurations */
if (qca8084_swt_enb && qca8084_chip_detect) {
/** Force speed devsoc 2nd port for QCA8084 switch mode */
clk[0] = 0x301;
clk[1] = 0x0;
clk[2] = 0x401;
clk[3] = 0x0;
pr_debug("Force speed devsoc 2nd PORT for QCA8084 switch mode \n");
devsoc_speed_clock_set(PORT1, clk);
/** Force Link-speed: 1000M
* Force Link-status: enable */
devsoc_pqsgmii_speed_set(PORT1, 0x2, 0x0);
ret = ipq_qca8084_hw_init(swt_info);
if (ret < 0) {
printf("Error: ipq_qca8084_hw_init failed \n");
goto init_failed;
}
}
#endif
#ifdef CONFIG_ATHRS17C_SWITCH
if (s17c_swt_cfg.chip_detect)
ipq_qca8337_switch_init(&s17c_swt_cfg);
#endif
#endif
eth_register(dev[i]);
}

View file

@ -24,13 +24,9 @@
#include <asm/io.h>
#include <malloc.h>
#include <phy.h>
#include <net.h>
#include <miiphy.h>
#define DEVSOC_PPE_BASE_ADDR 0x3a000000
#define PORT1 1
#define PORT2 2
#define DEVSOC_PORT5_MUX_PCS_UNIPHY0 0x0
#define DEVSOC_PORT5_MUX_PCS_UNIPHY1 0x1

View file

@ -202,10 +202,32 @@ static void ppe_uniphy_qsgmii_mode_set(uint32_t uniphy_index)
mdelay(100);
}
void ppe_uniphy_set_forceMode(uint32_t uniphy_index)
{
uint32_t reg_value;
reg_value = readl(PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
reg_value |= UNIPHY_FORCE_SPEED_25M;
writel(reg_value, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
}
static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
{
writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
if ((uniphy_index == 1) && (mode == EPORT_WRAPPER_SGMII_PLUS)) {
writel(UNIPHY_MISC_SRC_PHY_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC_SOURCE_SELECTION_REG_OFFSET);
ppe_uniphy_set_forceMode(uniphy_index);
writel(UNIPHY_MISC2_REG_SGMII_PLUS_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
} else {
writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
}
writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET);
@ -238,7 +260,11 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
break;
case EPORT_WRAPPER_SGMII_PLUS:
writel(0x820, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
if (uniphy_index == 1)
writel(0x20, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
else
writel(0x820, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
break;

View file

@ -41,6 +41,12 @@
#define UNIPHY_MISC2_REG_VALUE 0x70
#define UNIPHY_MISC_SOURCE_SELECTION_REG_OFFSET 0x21c
#define UNIPHY_MISC_SRC_PHY_MODE 0xa882
#define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4 0x480
#define UNIPHY_FORCE_SPEED_25M (1 << 3)
#define UNIPHY_PLL_RESET_REG_OFFSET 0x780
#define UNIPHY_PLL_RESET_REG_VALUE 0x02bf
#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff

View file

@ -0,0 +1,419 @@
/*
* Copyright (c) 2015-2016, 2020 The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
* Manage the QTI S17C ethernet PHY.
*
* All definitions in this file are operating system independent!
*/
#include <common.h>
#include "athrs17_phy.h"
/*
* Externel Common mdio read, PHY Name : IPQ MDIO1
*/
extern int ipq_mdio_write(int mii_id, int regnum, u16 value);
extern int ipq_mdio_read(int mii_id, int regnum, ushort *data);
/******************************************************************************
* FUNCTION DESCRIPTION: Read switch internal register.
* Switch internal register is accessed through the
* MDIO interface. MDIO access is only 16 bits wide so
* it needs the two time access to complete the internal
* register access.
* INPUT : register address
* OUTPUT : Register value
*
*****************************************************************************/
static uint32_t athrs17_reg_read(uint32_t reg_addr)
{
uint32_t reg_word_addr;
uint32_t phy_addr, reg_val;
uint16_t phy_val;
uint16_t tmp_val;
uint8_t phy_reg;
/* change reg_addr to 16-bit word address, 32-bit aligned */
reg_word_addr = (reg_addr & 0xfffffffc) >> 1;
/* configure register high address */
phy_addr = 0x18;
phy_reg = 0x0;
phy_val = (uint16_t) ((reg_word_addr >> 8) & 0x1ff); /* bit16-8 of reg address */
ipq_mdio_write(phy_addr, phy_reg, phy_val);
/*
* For some registers such as MIBs, since it is read/clear, we should
* read the lower 16-bit register then the higher one
*/
/* read register in lower address */
phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
phy_reg = (uint8_t) (reg_word_addr & 0x1f); /* bit4-0 of reg address */
ipq_mdio_read(phy_addr, phy_reg, &phy_val);
/* read register in higher address */
reg_word_addr++;
phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
phy_reg = (uint8_t) (reg_word_addr & 0x1f); /* bit4-0 of reg address */
ipq_mdio_read(phy_addr, phy_reg, &tmp_val);
reg_val = (tmp_val << 16 | phy_val);
return reg_val;
}
/******************************************************************************
* FUNCTION DESCRIPTION: Write switch internal register.
* Switch internal register is accessed through the
* MDIO interface. MDIO access is only 16 bits wide so
* it needs the two time access to complete the internal
* register access.
* INPUT : register address, value to be written
* OUTPUT : NONE
*
*****************************************************************************/
static void athrs17_reg_write(uint32_t reg_addr, uint32_t reg_val)
{
uint32_t reg_word_addr;
uint32_t phy_addr;
uint16_t phy_val;
uint8_t phy_reg;
/* change reg_addr to 16-bit word address, 32-bit aligned */
reg_word_addr = (reg_addr & 0xfffffffc) >> 1;
/* configure register high address */
phy_addr = 0x18;
phy_reg = 0x0;
phy_val = (uint16_t) ((reg_word_addr >> 8) & 0x1ff); /* bit16-8 of reg address */
ipq_mdio_write(phy_addr, phy_reg, phy_val);
/*
* For some registers such as ARL and VLAN, since they include BUSY bit
* in lower address, we should write the higher 16-bit register then the
* lower one
*/
/* read register in higher address */
reg_word_addr++;
phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
phy_reg = (uint8_t) (reg_word_addr & 0x1f); /* bit4-0 of reg address */
phy_val = (uint16_t) ((reg_val >> 16) & 0xffff);
ipq_mdio_write(phy_addr, phy_reg, phy_val);
/* write register in lower address */
reg_word_addr--;
phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
phy_reg = (uint8_t) (reg_word_addr & 0x1f); /* bit4-0 of reg address */
phy_val = (uint16_t) (reg_val & 0xffff);
ipq_mdio_write(phy_addr, phy_reg, phy_val);
}
/*********************************************************************
* FUNCTION DESCRIPTION: V-lan configuration given by Switch team
Vlan 1:PHY0,1,2,3 and Mac 6 of s17c
Vlan 2:PHY4 and Mac 0 of s17c
* INPUT : NONE
* OUTPUT: NONE
*********************************************************************/
void athrs17_vlan_config(void)
{
athrs17_reg_write(S17_P0LOOKUP_CTRL_REG, 0x00140020);
athrs17_reg_write(S17_P0VLAN_CTRL0_REG, 0x20001);
athrs17_reg_write(S17_P1LOOKUP_CTRL_REG, 0x0014005c);
athrs17_reg_write(S17_P1VLAN_CTRL0_REG, 0x10001);
athrs17_reg_write(S17_P2LOOKUP_CTRL_REG, 0x0014005a);
athrs17_reg_write(S17_P2VLAN_CTRL0_REG, 0x10001);
athrs17_reg_write(S17_P3LOOKUP_CTRL_REG, 0x00140056);
athrs17_reg_write(S17_P3VLAN_CTRL0_REG, 0x10001);
athrs17_reg_write(S17_P4LOOKUP_CTRL_REG, 0x0014004e);
athrs17_reg_write(S17_P4VLAN_CTRL0_REG, 0x10001);
athrs17_reg_write(S17_P5LOOKUP_CTRL_REG, 0x00140001);
athrs17_reg_write(S17_P5VLAN_CTRL0_REG, 0x20001);
athrs17_reg_write(S17_P6LOOKUP_CTRL_REG, 0x0014001e);
athrs17_reg_write(S17_P6VLAN_CTRL0_REG, 0x10001);
printf("%s ...done\n", __func__);
}
/*******************************************************************
* FUNCTION DESCRIPTION: Reset S17 register
* INPUT: NONE
* OUTPUT: NONE
*******************************************************************/
int athrs17_init_switch(void)
{
uint32_t data;
uint32_t i = 0;
/* Reset the switch before initialization */
athrs17_reg_write(S17_MASK_CTRL_REG, S17_MASK_CTRL_SOFT_RET);
do {
udelay(10);
data = athrs17_reg_read(S17_MASK_CTRL_REG);
i++;
if (i == 10){
printf("QCA_8337: Failed to reset\n");
return -1;
}
} while (data & S17_MASK_CTRL_SOFT_RET);
i = 0;
do {
udelay(10);
data = athrs17_reg_read(S17_GLOBAL_INT0_REG);
i++;
if (i == 10)
return -1;
} while ((data & S17_GLOBAL_INITIALIZED_STATUS) != S17_GLOBAL_INITIALIZED_STATUS);
return 0;
}
/*********************************************************************
* FUNCTION DESCRIPTION: Configure S17 register
* INPUT : NONE
* OUTPUT: NONE
*********************************************************************/
void athrs17_reg_init(ipq_s17c_swt_cfg_t *swt_cfg)
{
athrs17_reg_write(S17_MAC_PWR_REG, swt_cfg->mac_pwr);
athrs17_reg_write(S17_P0STATUS_REG, (S17_SPEED_1000M |
S17_TXMAC_EN |
S17_RXMAC_EN |
S17_DUPLEX_FULL));
athrs17_reg_write(S17_GLOFW_CTRL1_REG, (S17_IGMP_JOIN_LEAVE_DPALL |
S17_BROAD_DPALL |
S17_MULTI_FLOOD_DPALL |
S17_UNI_FLOOD_DPALL));
athrs17_reg_write(S17_P5PAD_MODE_REG, S17_MAC0_RGMII_RXCLK_DELAY);
athrs17_reg_write(S17_P0PAD_MODE_REG, (S17_MAC0_RGMII_EN |
S17_MAC0_RGMII_TXCLK_DELAY |
S17_MAC0_RGMII_RXCLK_DELAY |
(0x1 << S17_MAC0_RGMII_TXCLK_SHIFT) |
(0x2 << S17_MAC0_RGMII_RXCLK_SHIFT)));
printf("%s: complete\n", __func__);
}
/*********************************************************************
* FUNCTION DESCRIPTION: Configure S17 register
* INPUT : NONE
* OUTPUT: NONE
*********************************************************************/
void athrs17_reg_init_lan(ipq_s17c_swt_cfg_t *swt_cfg)
{
uint32_t reg_val;
athrs17_reg_write(S17_P6STATUS_REG, (S17_SPEED_1000M |
S17_TXMAC_EN |
S17_RXMAC_EN |
S17_DUPLEX_FULL));
athrs17_reg_write(S17_MAC_PWR_REG, swt_cfg->mac_pwr);
reg_val = athrs17_reg_read(S17_P6PAD_MODE_REG);
athrs17_reg_write(S17_P6PAD_MODE_REG, (reg_val | S17_MAC6_SGMII_EN));
athrs17_reg_write(S17_PWS_REG, 0x2613a0);
athrs17_reg_write(S17_SGMII_CTRL_REG,(S17c_SGMII_EN_PLL |
S17c_SGMII_EN_RX |
S17c_SGMII_EN_TX |
S17c_SGMII_EN_SD |
S17c_SGMII_BW_HIGH |
S17c_SGMII_SEL_CLK125M |
S17c_SGMII_TXDR_CTRL_600mV |
S17c_SGMII_CDR_BW_8 |
S17c_SGMII_DIS_AUTO_LPI_25M |
S17c_SGMII_MODE_CTRL_SGMII_PHY |
S17c_SGMII_PAUSE_SG_TX_EN_25M |
S17c_SGMII_ASYM_PAUSE_25M |
S17c_SGMII_PAUSE_25M |
S17c_SGMII_HALF_DUPLEX_25M |
S17c_SGMII_FULL_DUPLEX_25M));
athrs17_reg_write(S17_MODULE_EN_REG, S17_MIB_COUNTER_ENABLE);
}
struct athrs17_regmap {
uint32_t start;
uint32_t end;
};
struct athrs17_regmap regmap[] = {
{ 0x000, 0x0e4 },
{ 0x100, 0x168 },
{ 0x200, 0x270 },
{ 0x400, 0x454 },
{ 0x600, 0x718 },
{ 0x800, 0xb70 },
{ 0xC00, 0xC80 },
{ 0x1100, 0x11a7 },
{ 0x1200, 0x12a7 },
{ 0x1300, 0x13a7 },
{ 0x1400, 0x14a7 },
{ 0x1600, 0x16a7 },
};
int do_ar8xxx_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
int i;
for (i = 0; i < ARRAY_SIZE(regmap); i++) {
uint32_t reg;
struct athrs17_regmap *section = &regmap[i];
for (reg = section->start; reg <= section->end; reg += sizeof(uint32_t)) {
uint32_t val = athrs17_reg_read(reg);
printf("%03zx: %08zx\n", reg, val);
}
}
return 0;
};
U_BOOT_CMD(
ar8xxx_dump, 1, 1, do_ar8xxx_dump,
"Dump ar8xxx registers",
"\n - print all ar8xxx registers\n"
);
/*********************************************************************
*
* FUNCTION DESCRIPTION: This function invokes RGMII,
* SGMII switch init routines.
* INPUT : ipq_s17c_swt_cfg_t *
* OUTPUT: NONE
*
**********************************************************************/
int ipq_athrs17_init(ipq_s17c_swt_cfg_t *swt_cfg)
{
int ret;
if (swt_cfg == NULL)
return -1;
ret = athrs17_init_switch();
if (ret != -1) {
athrs17_reg_init(swt_cfg);
athrs17_reg_init_lan(swt_cfg);
athrs17_vlan_config();
printf ("S17c init done\n");
}
return ret;
}
int ipq_qca8337_switch_init(ipq_s17c_swt_cfg_t *s17c_swt_cfg)
{
int port;
for (port = 0; port < s17c_swt_cfg->port_count; ++port) {
u32 phy_val;
/* phy powerdown */
ipq_mdio_write(s17c_swt_cfg->port_phy_address[port], 0x0,
0x0800);
phy_val = ipq_mdio_read(s17c_swt_cfg->port_phy_address[port],
0x3d, NULL);
phy_val &= ~0x0040;
ipq_mdio_write(s17c_swt_cfg->port_phy_address[port], 0x3d,
phy_val);
/*
* PHY will stop the tx clock for a while when link is down
* en_anychange debug port 0xb bit13 = 0 //speed up link down tx_clk
* sel_rst_80us debug port 0xb bit10 = 0 //speed up speed mode change to 2'b10 tx_clk
*/
phy_val = ipq_mdio_read(s17c_swt_cfg->port_phy_address[port],
0xb, NULL);
phy_val &= ~0x2400;
ipq_mdio_write(s17c_swt_cfg->port_phy_address[port], 0xb,
phy_val);
mdelay(100);
}
if (ipq_athrs17_init(s17c_swt_cfg) != 0) {
printf("QCA_8337 switch init failed \n");
return 0;
}
for (port = 0; port < s17c_swt_cfg->port_count; ++port) {
ipq_mdio_write(s17c_swt_cfg->port_phy_address[port],
MII_ADVERTISE, ADVERTISE_ALL |
ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
/* phy reg 0x9, b10,1 = Prefer multi-port device (master) */
ipq_mdio_write(s17c_swt_cfg->port_phy_address[port],
MII_CTRL1000, (0x0400|ADVERTISE_1000FULL));
ipq_mdio_write(s17c_swt_cfg->port_phy_address[port],
MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
mdelay(100);
}
return 1;
}
int ipq_qca8337_link_update(ipq_s17c_swt_cfg_t *s17c_swt_cfg)
{
uint16_t phy_data;
int status = 1;
for(int i = 0; i < s17c_swt_cfg->port_count; ++i){
phy_data = ipq_mdio_read(s17c_swt_cfg->port_phy_address[i],
0x11, NULL);
if (phy_data == 0x50)
continue;
/* Atleast one port should be link up*/
if (phy_data & LINK_UP)
status = 0;
printf("Port%d %s ", i + 1, LINK(phy_data));
switch(SPEED(phy_data)){
case SPEED_1000M:
printf("Speed :1000M ");
break;
case SPEED_100M:
printf("Speed :100M ");
break;
default:
printf("Speed :10M ");
}
printf ("%s \n", DUPLEX(phy_data));
}
return status;
}
void ipq_s17c_switch_reset(int gpio)
{
unsigned int *switch_gpio_base =
(unsigned int *)GPIO_CONFIG_ADDR(gpio);
writel(0x203, switch_gpio_base);
writel(0x0, GPIO_IN_OUT_ADDR(gpio));
mdelay(500);
writel(0x2, GPIO_IN_OUT_ADDR(gpio));
}

View file

@ -0,0 +1,621 @@
/*
* Copyright (c) 2015-2016, 2020 The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _ATHRS17_PHY_H
#define _ATHRS17_PHY_H
/*****************/
/* PHY Registers */
/*****************/
#define ATHR_PHY_CONTROL 0
#define ATHR_PHY_STATUS 1
#define ATHR_PHY_ID1 2
#define ATHR_PHY_ID2 3
#define ATHR_AUTONEG_ADVERT 4
#define ATHR_LINK_PARTNER_ABILITY 5
#define ATHR_AUTONEG_EXPANSION 6
#define ATHR_NEXT_PAGE_TRANSMIT 7
#define ATHR_LINK_PARTNER_NEXT_PAGE 8
#define ATHR_1000BASET_CONTROL 9
#define ATHR_1000BASET_STATUS 10
#define ATHR_PHY_SPEC_CONTROL 16
#define ATHR_PHY_SPEC_STATUS 17
#define ATHR_DEBUG_PORT_ADDRESS 29
#define ATHR_DEBUG_PORT_DATA 30
/* ATHR_PHY_CONTROL fields */
#define ATHR_CTRL_SOFTWARE_RESET 0x8000
#define ATHR_CTRL_SPEED_LSB 0x2000
#define ATHR_CTRL_AUTONEGOTIATION_ENABLE 0x1000
#define ATHR_CTRL_RESTART_AUTONEGOTIATION 0x0200
#define ATHR_CTRL_SPEED_FULL_DUPLEX 0x0100
#define ATHR_CTRL_SPEED_MSB 0x0040
#define ATHR_RESET_DONE(phy_control) \
(((phy_control) & (ATHR_CTRL_SOFTWARE_RESET)) == 0)
/* Phy status fields */
#define ATHR_STATUS_AUTO_NEG_DONE 0x0020
#define ATHR_AUTONEG_DONE(ip_phy_status) \
(((ip_phy_status) & \
(ATHR_STATUS_AUTO_NEG_DONE)) == \
(ATHR_STATUS_AUTO_NEG_DONE))
/* Link Partner ability */
#define ATHR_LINK_100BASETX_FULL_DUPLEX 0x0100
#define ATHR_LINK_100BASETX 0x0080
#define ATHR_LINK_10BASETX_FULL_DUPLEX 0x0040
#define ATHR_LINK_10BASETX 0x0020
/* Advertisement register. */
#define ATHR_ADVERTISE_NEXT_PAGE 0x8000
#define ATHR_ADVERTISE_ASYM_PAUSE 0x0800
#define ATHR_ADVERTISE_PAUSE 0x0400
#define ATHR_ADVERTISE_100FULL 0x0100
#define ATHR_ADVERTISE_100HALF 0x0080
#define ATHR_ADVERTISE_10FULL 0x0040
#define ATHR_ADVERTISE_10HALF 0x0020
#define ATHR_ADVERTISE_ALL (ATHR_ADVERTISE_ASYM_PAUSE | ATHR_ADVERTISE_PAUSE | \
ATHR_ADVERTISE_10HALF | ATHR_ADVERTISE_10FULL | \
ATHR_ADVERTISE_100HALF | ATHR_ADVERTISE_100FULL)
/* 1000BASET_CONTROL */
#define ATHR_ADVERTISE_1000FULL 0x0200
/* Phy Specific status fields */
#define ATHER_STATUS_LINK_MASK 0xC000
#define ATHER_STATUS_LINK_SHIFT 14
#define ATHER_STATUS_FULL_DEPLEX 0x2000
#define ATHR_STATUS_LINK_PASS 0x0400
#define ATHR_STATUS_RESOVLED 0x0800
/*phy debug port register */
#define ATHER_DEBUG_SERDES_REG 5
/* Serdes debug fields */
#define ATHER_SERDES_BEACON 0x0100
/* S17 CSR Registers */
#define S17_ENABLE_CPU_BROADCAST (1 << 26)
#define S17_PHY_LINK_CHANGE_REG 0x4
#define S17_PHY_LINK_UP 0x400
#define S17_PHY_LINK_DOWN 0x800
#define S17_PHY_LINK_DUPLEX_CHANGE 0x2000
#define S17_PHY_LINK_SPEED_CHANGE 0x4000
#define S17_PHY_LINK_INTRS (PHY_LINK_UP | PHY_LINK_DOWN | PHY_LINK_DUPLEX_CHANGE | PHY_LINK_SPEED_CHANGE)
#define S17_MASK_CTRL_REG 0x0000
#define S17_P0PAD_MODE_REG 0x0004
#define S17_P5PAD_MODE_REG 0x0008
#define S17_P6PAD_MODE_REG 0x000c
#define S17_PWS_REG 0x0010
#define S17_GLOBAL_INT0_REG 0x0020
#define S17_GLOBAL_INT1_REG 0x0024
#define S17_GLOBAL_INTMASK0 0x0028
#define S17_GLOBAL_INTMASK1 0x002c
#define S17_MODULE_EN_REG 0x0030
#define S17_MIB_REG 0x0034
#define S17_INTF_HIADDR_REG 0x0038
#define S17_MDIO_CTRL_REG 0x003c
#define S17_BIST_CTRL_REG 0x0040
#define S17_BIST_REC_REG 0x0044
#define S17_SERVICE_REG 0x0048
#define S17_LED_CTRL0_REG 0x0050
#define S17_LED_CTRL1_REG 0x0054
#define S17_LED_CTRL2_REG 0x0058
#define S17_LED_CTRL3_REG 0x005c
#define S17_MACADDR0_REG 0x0060
#define S17_MACADDR1_REG 0x0064
#define S17_MAX_FRAME_SIZE_REG 0x0078
#define S17_P0STATUS_REG 0x007c
#define S17_P1STATUS_REG 0x0080
#define S17_P2STATUS_REG 0x0084
#define S17_P3STATUS_REG 0x0088
#define S17_P4STATUS_REG 0x008c
#define S17_P5STATUS_REG 0x0090
#define S17_P6STATUS_REG 0x0094
#define S17_HDRCTRL_REG 0x0098
#define S17_P0HDRCTRL_REG 0x009c
#define S17_P1HDRCTRL_REG 0x00A0
#define S17_P2HDRCTRL_REG 0x00a4
#define S17_P3HDRCTRL_REG 0x00a8
#define S17_P4HDRCTRL_REG 0x00ac
#define S17_P5HDRCTRL_REG 0x00b0
#define S17_P6HDRCTRL_REG 0x00b4
#define S17_SGMII_CTRL_REG 0x00e0
#define S17_MAC_PWR_REG 0x00e4
#define S17_EEE_CTRL_REG 0x0100
/* ACL Registers */
#define S17_ACL_FUNC0_REG 0x0400
#define S17_ACL_FUNC1_REG 0x0404
#define S17_ACL_FUNC2_REG 0x0408
#define S17_ACL_FUNC3_REG 0x040c
#define S17_ACL_FUNC4_REG 0x0410
#define S17_ACL_FUNC5_REG 0x0414
#define S17_PRIVATE_IP_REG 0x0418
#define S17_P0VLAN_CTRL0_REG 0x0420
#define S17_P0VLAN_CTRL1_REG 0x0424
#define S17_P1VLAN_CTRL0_REG 0x0428
#define S17_P1VLAN_CTRL1_REG 0x042c
#define S17_P2VLAN_CTRL0_REG 0x0430
#define S17_P2VLAN_CTRL1_REG 0x0434
#define S17_P3VLAN_CTRL0_REG 0x0438
#define S17_P3VLAN_CTRL1_REG 0x043c
#define S17_P4VLAN_CTRL0_REG 0x0440
#define S17_P4VLAN_CTRL1_REG 0x0444
#define S17_P5VLAN_CTRL0_REG 0x0448
#define S17_P5VLAN_CTRL1_REG 0x044c
#define S17_P6VLAN_CTRL0_REG 0x0450
#define S17_P6VLAN_CTRL1_REG 0x0454
/* Table Lookup Registers */
#define S17_ATU_DATA0_REG 0x0600
#define S17_ATU_DATA1_REG 0x0604
#define S17_ATU_DATA2_REG 0x0608
#define S17_ATU_FUNC_REG 0x060C
#define S17_VTU_FUNC0_REG 0x0610
#define S17_VTU_FUNC1_REG 0x0614
#define S17_ARL_CTRL_REG 0x0618
#define S17_GLOFW_CTRL0_REG 0x0620
#define S17_GLOFW_CTRL1_REG 0x0624
#define S17_GLOLEARN_LIMIT_REG 0x0628
#define S17_TOS_PRIMAP_REG0 0x0630
#define S17_TOS_PRIMAP_REG1 0x0634
#define S17_TOS_PRIMAP_REG2 0x0638
#define S17_TOS_PRIMAP_REG3 0x063c
#define S17_TOS_PRIMAP_REG4 0x0640
#define S17_TOS_PRIMAP_REG5 0x0644
#define S17_TOS_PRIMAP_REG6 0x0648
#define S17_TOS_PRIMAP_REG7 0x064c
#define S17_VLAN_PRIMAP_REG0 0x0650
#define S17_LOOP_CHECK_REG 0x0654
#define S17_P0LOOKUP_CTRL_REG 0x0660
#define S17_P0PRI_CTRL_REG 0x0664
#define S17_P0LEARN_LMT_REG 0x0668
#define S17_P1LOOKUP_CTRL_REG 0x066c
#define S17_P1PRI_CTRL_REG 0x0670
#define S17_P1LEARN_LMT_REG 0x0674
#define S17_P2LOOKUP_CTRL_REG 0x0678
#define S17_P2PRI_CTRL_REG 0x067c
#define S17_P2LEARN_LMT_REG 0x0680
#define S17_P3LOOKUP_CTRL_REG 0x0684
#define S17_P3PRI_CTRL_REG 0x0688
#define S17_P3LEARN_LMT_REG 0x068c
#define S17_P4LOOKUP_CTRL_REG 0x0690
#define S17_P4PRI_CTRL_REG 0x0694
#define S17_P4LEARN_LMT_REG 0x0698
#define S17_P5LOOKUP_CTRL_REG 0x069c
#define S17_P5PRI_CTRL_REG 0x06a0
#define S17_P5LEARN_LMT_REG 0x06a4
#define S17_P6LOOKUP_CTRL_REG 0x06a8
#define S17_P6PRI_CTRL_REG 0x06ac
#define S17_P6LEARN_LMT_REG 0x06b0
#define S17_GLO_TRUNK_CTRL0_REG 0x0700
#define S17_GLO_TRUNK_CTRL1_REG 0x0704
#define S17_GLO_TRUNK_CTRL2_REG 0x0708
/* Queue Management Registers */
#define S17_PORT0_HOL_CTRL0 0x0970
#define S17_PORT0_HOL_CTRL1 0x0974
#define S17_PORT1_HOL_CTRL0 0x0978
#define S17_PORT1_HOL_CTRL1 0x097c
#define S17_PORT2_HOL_CTRL0 0x0980
#define S17_PORT2_HOL_CTRL1 0x0984
#define S17_PORT3_HOL_CTRL0 0x0988
#define S17_PORT3_HOL_CTRL1 0x098c
#define S17_PORT4_HOL_CTRL0 0x0990
#define S17_PORT4_HOL_CTRL1 0x0994
#define S17_PORT5_HOL_CTRL0 0x0998
#define S17_PORT5_HOL_CTRL1 0x099c
#define S17_PORT6_HOL_CTRL0 0x09a0
#define S17_PORT6_HOL_CTRL1 0x09a4
/* Port flow control registers */
#define S17_P0_FLCTL_REG 0x09b0
#define S17_P1_FLCTL_REG 0x09b4
#define S17_P2_FLCTL_REG 0x09b8
#define S17_P3_FLCTL_REG 0x09bc
#define S17_P4_FLCTL_REG 0x09c0
#define S17_P5_FLCTL_REG 0x09c4
/* Packet Edit registers */
#define S17_PKT_EDIT_CTRL 0x0c00
#define S17_P0Q_REMAP_REG0 0x0c40
#define S17_P0Q_REMAP_REG1 0x0c44
#define S17_P1Q_REMAP_REG0 0x0c48
#define S17_P2Q_REMAP_REG0 0x0c4c
#define S17_P3Q_REMAP_REG0 0x0c50
#define S17_P4Q_REMAP_REG0 0x0c54
#define S17_P5Q_REMAP_REG0 0x0c58
#define S17_P5Q_REMAP_REG1 0x0c5c
#define S17_P6Q_REMAP_REG0 0x0c60
#define S17_P6Q_REMAP_REG1 0x0c64
#define S17_ROUTER_VID0 0x0c70
#define S17_ROUTER_VID1 0x0c74
#define S17_ROUTER_VID2 0x0c78
#define S17_ROUTER_VID3 0x0c7c
#define S17_ROUTER_EG_VLAN_MODE 0x0c80
/* L3 Registers */
#define S17_HROUTER_CTRL_REG 0x0e00
#define S17_HROUTER_PBCTRL0_REG 0x0e04
#define S17_HROUTER_PBCTRL1_REG 0x0e08
#define S17_HROUTER_PBCTRL2_REG 0x0e0c
#define S17_WCMP_HASH_TABLE0_REG 0x0e10
#define S17_WCMP_HASH_TABLE1_REG 0x0e14
#define S17_WCMP_HASH_TABLE2_REG 0x0e18
#define S17_WCMP_HASH_TABLE3_REG 0x0e1c
#define S17_WCMP_NHOP_TABLE0_REG 0x0e20
#define S17_WCMP_NHOP_TABLE1_REG 0x0e24
#define S17_WCMP_NHOP_TABLE2_REG 0x0e28
#define S17_WCMP_NHOP_TABLE3_REG 0x0e2c
#define S17_ARP_ENTRY_CTRL_REG 0x0e30
#define S17_ARP_USECNT_REG 0x0e34
#define S17_HNAT_CTRL_REG 0x0e38
#define S17_NAPT_ENTRY_CTRL0_REG 0x0e3c
#define S17_NAPT_ENTRY_CTRL1_REG 0x0e40
#define S17_NAPT_USECNT_REG 0x0e44
#define S17_ENTRY_EDIT_DATA0_REG 0x0e48
#define S17_ENTRY_EDIT_DATA1_REG 0x0e4c
#define S17_ENTRY_EDIT_DATA2_REG 0x0e50
#define S17_ENTRY_EDIT_DATA3_REG 0x0e54
#define S17_ENTRY_EDIT_CTRL_REG 0x0e58
#define S17_HNAT_PRIVATE_IP_REG 0x0e5c
/* MIB counters */
#define S17_MIB_PORT0 0x1000
#define S17_MIB_PORT1 0x1100
#define S17_MIB_PORT2 0x1200
#define S17_MIB_PORT3 0x1300
#define S17_MIB_PORT4 0x1400
#define S17_MIB_PORT5 0x1500
#define S17_MIB_PORT6 0x1600
#define S17_MIB_COUNTER_ENABLE (1 << 0)
#define S17_MIB_NON_CLEAR (1 << 20)
#define S17_MIB_RXBROAD 0x0
#define S17_MIB_RXPAUSE 0x4
#define S17_MIB_RXMULTI 0x8
#define S17_MIB_RXFCSERR 0xC
#define S17_MIB_RXALIGNERR 0x10
#define S17_MIB_RXUNDERSIZE 0x14
#define S17_MIB_RXFRAG 0x18
#define S17_MIB_RX64B 0x1C
#define S17_MIB_RX128B 0x20
#define S17_MIB_RX256B 0x24
#define S17_MIB_RX512B 0x28
#define S17_MIB_RX1024B 0x2C
#define S17_MIB_RX1518B 0x30
#define S17_MIB_RXMAXB 0x34
#define S17_MIB_RXTOOLONG 0x38
#define S17_MIB_RXBYTE1 0x3C
#define S17_MIB_RXBYTE2 0x40
#define S17_MIB_RXOVERFLOW 0x4C
#define S17_MIB_FILTERED 0x50
#define S17_MIB_TXBROAD 0x54
#define S17_MIB_TXPAUSE 0x58
#define S17_MIB_TXMULTI 0x5C
#define S17_MIB_TXUNDERRUN 0x60
#define S17_MIB_TX64B 0x64
#define S17_MIB_TX128B 0x68
#define S17_MIB_TX256B 0x6c
#define S17_MIB_TX512B 0x70
#define S17_MIB_TX1024B 0x74
#define S17_MIB_TX1518B 0x78
#define S17_MIB_TXMAXB 0x7C
#define S17_MIB_TXOVERSIZE 0x80
#define S17_MIB_TXBYTE1 0x84
#define S17_MIB_TXBYTE2 0x88
#define S17_MIB_TXCOL 0x8C
#define S17_MIB_TXABORTCOL 0x90
#define S17_MIB_TXMULTICOL 0x94
#define S17_MIB_TXSINGLECOL 0x98
#define S17_MIB_TXEXCDEFER 0x9C
#define S17_MIB_TXDEFER 0xA0
#define S17_MIB_TXLATECOL 0xA4
/* Register fields */
#define S17_CHIPID_V1_0 0x1201
#define S17_CHIPID_V1_1 0x1202
#define S17_MASK_CTRL_SOFT_RET (1 << 31)
#define S17_GLOBAL_INT0_ACL_INI_INT (1<<29)
#define S17_GLOBAL_INT0_LOOKUP_INI_INT (1<<28)
#define S17_GLOBAL_INT0_QM_INI_INT (1<<27)
#define S17_GLOBAL_INT0_MIB_INI_INT (1<<26)
#define S17_GLOBAL_INT0_OFFLOAD_INI_INT (1<<25)
#define S17_GLOBAL_INT0_HARDWARE_INI_DONE (1<<24)
#define S17_GLOBAL_INITIALIZED_STATUS \
( \
S17_GLOBAL_INT0_ACL_INI_INT | \
S17_GLOBAL_INT0_LOOKUP_INI_INT | \
S17_GLOBAL_INT0_QM_INI_INT | \
S17_GLOBAL_INT0_MIB_INI_INT | \
S17_GLOBAL_INT0_OFFLOAD_INI_INT | \
S17_GLOBAL_INT0_HARDWARE_INI_DONE \
)
#define S17_MAC0_MAC_MII_RXCLK_SEL (1 << 0)
#define S17_MAC0_MAC_MII_TXCLK_SEL (1 << 1)
#define S17_MAC0_MAC_MII_EN (1 << 2)
#define S17_MAC0_MAC_GMII_RXCLK_SEL (1 << 4)
#define S17_MAC0_MAC_GMII_TXCLK_SEL (1 << 5)
#define S17_MAC0_MAC_GMII_EN (1 << 6)
#define S17_MAC0_SGMII_EN (1 << 7)
#define S17_MAC0_PHY_MII_RXCLK_SEL (1 << 8)
#define S17_MAC0_PHY_MII_TXCLK_SEL (1 << 9)
#define S17_MAC0_PHY_MII_EN (1 << 10)
#define S17_MAC0_PHY_MII_PIPE_SEL (1 << 11)
#define S17_MAC0_PHY_GMII_RXCLK_SEL (1 << 12)
#define S17_MAC0_PHY_GMII_TXCLK_SEL (1 << 13)
#define S17_MAC0_PHY_GMII_EN (1 << 14)
#define S17_MAC0_RGMII_RXCLK_SHIFT 20
#define S17_MAC0_RGMII_TXCLK_SHIFT 22
#define S17_MAC0_RGMII_RXCLK_DELAY (1 << 24)
#define S17_MAC0_RGMII_TXCLK_DELAY (1 << 25)
#define S17_MAC0_RGMII_EN (1 << 26)
#define S17_MAC5_MAC_MII_RXCLK_SEL (1 << 0)
#define S17_MAC5_MAC_MII_TXCLK_SEL (1 << 1)
#define S17_MAC5_MAC_MII_EN (1 << 2)
#define S17_MAC5_PHY_MII_RXCLK_SEL (1 << 8)
#define S17_MAC5_PHY_MII_TXCLK_SEL (1 << 9)
#define S17_MAC5_PHY_MII_EN (1 << 10)
#define S17_MAC5_PHY_MII_PIPE_SEL (1 << 11)
#define S17_MAC5_RGMII_RXCLK_SHIFT 20
#define S17_MAC5_RGMII_TXCLK_SHIFT 22
#define S17_MAC5_RGMII_RXCLK_DELAY (1 << 24)
#define S17_MAC5_RGMII_TXCLK_DELAY (1 << 25)
#define S17_MAC5_RGMII_EN (1 << 26)
#define S17_MAC6_MAC_MII_RXCLK_SEL (1 << 0)
#define S17_MAC6_MAC_MII_TXCLK_SEL (1 << 1)
#define S17_MAC6_MAC_MII_EN (1 << 2)
#define S17_MAC6_MAC_GMII_RXCLK_SEL (1 << 4)
#define S17_MAC6_MAC_GMII_TXCLK_SEL (1 << 5)
#define S17_MAC6_MAC_GMII_EN (1 << 6)
#define S17_MAC6_SGMII_EN (1 << 7)
#define S17_MAC6_PHY_MII_RXCLK_SEL (1 << 8)
#define S17_MAC6_PHY_MII_TXCLK_SEL (1 << 9)
#define S17_MAC6_PHY_MII_EN (1 << 10)
#define S17_MAC6_PHY_MII_PIPE_SEL (1 << 11)
#define S17_MAC6_PHY_GMII_RXCLK_SEL (1 << 12)
#define S17_MAC6_PHY_GMII_TXCLK_SEL (1 << 13)
#define S17_MAC6_PHY_GMII_EN (1 << 14)
#define S17_PHY4_GMII_EN (1 << 16)
#define S17_PHY4_RGMII_EN (1 << 17)
#define S17_PHY4_MII_EN (1 << 18)
#define S17_MAC6_RGMII_RXCLK_SHIFT 20
#define S17_MAC6_RGMII_TXCLK_SHIFT 22
#define S17_MAC6_RGMII_RXCLK_DELAY (1 << 24)
#define S17_MAC6_RGMII_TXCLK_DELAY (1 << 25)
#define S17_MAC6_RGMII_EN (1 << 26)
#define S17_SPEED_10M (0 << 0)
#define S17_SPEED_100M (1 << 0)
#define S17_SPEED_1000M (2 << 0)
#define S17_TXMAC_EN (1 << 2)
#define S17_RXMAC_EN (1 << 3)
#define S17_TX_FLOW_EN (1 << 4)
#define S17_RX_FLOW_EN (1 << 5)
#define S17_DUPLEX_FULL (1 << 6)
#define S17_DUPLEX_HALF (0 << 6)
#define S17_TX_HALF_FLOW_EN (1 << 7)
#define S17_LINK_EN (1 << 9)
#define S17_FLOW_LINK_EN (1 << 12)
#define S17_PORT_STATUS_DEFAULT (S17_SPEED_1000M | S17_TXMAC_EN | \
S17_RXMAC_EN | S17_TX_FLOW_EN | \
S17_RX_FLOW_EN | S17_DUPLEX_FULL | \
S17_TX_HALF_FLOW_EN)
#define S17_PORT_STATUS_AZ_DEFAULT (S17_SPEED_1000M | S17_TXMAC_EN | \
S17_RXMAC_EN | S17_TX_FLOW_EN | \
S17_RX_FLOW_EN | S17_DUPLEX_FULL)
#define S17_HDRLENGTH_SEL (1 << 16)
#define S17_HDR_VALUE 0xAAAA
#define S17_TXHDR_MODE_NO 0
#define S17_TXHDR_MODE_MGM 1
#define S17_TXHDR_MODE_ALL 2
#define S17_RXHDR_MODE_NO (0 << 2)
#define S17_RXHDR_MODE_MGM (1 << 2)
#define S17_RXHDR_MODE_ALL (2 << 2)
#define S17_CPU_PORT_EN (1 << 10)
#define S17_PPPOE_REDIR_EN (1 << 8)
#define S17_MIRROR_PORT_SHIFT 4
#define S17_IGMP_COPY_EN (1 << 3)
#define S17_RIP_COPY_EN (1 << 2)
#define S17_EAPOL_REDIR_EN (1 << 0)
#define S17_IGMP_JOIN_LEAVE_DP_SHIFT 24
#define S17_BROAD_DP_SHIFT 16
#define S17_MULTI_FLOOD_DP_SHIFT 8
#define S17_UNI_FLOOD_DP_SHIFT 0
#define S17_IGMP_JOIN_LEAVE_DPALL (0x7f << S17_IGMP_JOIN_LEAVE_DP_SHIFT)
#define S17_BROAD_DPALL (0x7f << S17_BROAD_DP_SHIFT)
#define S17_MULTI_FLOOD_DPALL (0x7f << S17_MULTI_FLOOD_DP_SHIFT)
#define S17_UNI_FLOOD_DPALL (0x7f << S17_UNI_FLOOD_DP_SHIFT)
#define S17_PWS_CHIP_AR8327 (1 << 30)
#define S17c_PWS_SERDES_ANEG_DISABLE (1 << 7)
/* S17_PHY_CONTROL fields */
#define S17_CTRL_SOFTWARE_RESET 0x8000
#define S17_CTRL_SPEED_LSB 0x2000
#define S17_CTRL_AUTONEGOTIATION_ENABLE 0x1000
#define S17_CTRL_RESTART_AUTONEGOTIATION 0x0200
#define S17_CTRL_SPEED_FULL_DUPLEX 0x0100
#define S17_CTRL_SPEED_MSB 0x0040
/* For EEE_CTRL_REG */
#define S17_LPI_DISABLE_P1 (1 << 4)
#define S17_LPI_DISABLE_P2 (1 << 6)
#define S17_LPI_DISABLE_P3 (1 << 8)
#define S17_LPI_DISABLE_P4 (1 << 10)
#define S17_LPI_DISABLE_P5 (1 << 12)
#define S17_LPI_DISABLE_ALL 0x1550
/* For MMD register control */
#define S17_MMD_FUNC_ADDR (0 << 14)
#define S17_MMD_FUNC_DATA (1 << 14)
#define S17_MMD_FUNC_DATA_2 (2 << 14)
#define S17_MMD_FUNC_DATA_3 (3 << 14)
/* For phyInfo_t azFeature */
#define S17_8023AZ_PHY_ENABLED (1 << 0)
#define S17_8023AZ_PHY_LINKED (1 << 1)
/* Queue Management registe fields */
#define S17_HOL_CTRL0_LAN 0x2a008888 /* egress priority 8, eg_portq = 0x2a */
#define S17_HOL_CTRL0_WAN 0x2a666666 /* egress priority 6, eg_portq = 0x2a */
#define S17_HOL_CTRL1_DEFAULT 0xc6 /* enable HOL control */
/* Packet Edit register fields */
#define S17_ROUTER_EG_UNMOD 0x0 /* unmodified */
#define S17_ROUTER_EG_WOVLAN 0x1 /* without VLAN */
#define S17_ROUTER_EG_WVLAN 0x2 /* with VLAN */
#define S17_ROUTER_EG_UNTOUCH 0x3 /* untouched */
#define S17_ROUTER_EG_MODE_DEFAULT 0x01111111 /* all ports without VLAN */
#define S17_RESET_DONE(phy_control) \
(((phy_control) & (S17_CTRL_SOFTWARE_RESET)) == 0)
/* Phy status fields */
#define S17_STATUS_AUTO_NEG_DONE 0x0020
#define S17_AUTONEG_DONE(ip_phy_status) \
(((ip_phy_status) & \
(S17_STATUS_AUTO_NEG_DONE)) == \
(S17_STATUS_AUTO_NEG_DONE))
/* Link Partner ability */
#define S17_LINK_100BASETX_FULL_DUPLEX 0x0100
#define S17_LINK_100BASETX 0x0080
#define S17_LINK_10BASETX_FULL_DUPLEX 0x0040
#define S17_LINK_10BASETX 0x0020
/* Advertisement register. */
#define S17_ADVERTISE_NEXT_PAGE 0x8000
#define S17_ADVERTISE_ASYM_PAUSE 0x0800
#define S17_ADVERTISE_PAUSE 0x0400
#define S17_ADVERTISE_100FULL 0x0100
#define S17_ADVERTISE_100HALF 0x0080
#define S17_ADVERTISE_10FULL 0x0040
#define S17_ADVERTISE_10HALF 0x0020
#define S17_ADVERTISE_ALL (S17_ADVERTISE_ASYM_PAUSE | S17_ADVERTISE_PAUSE | \
S17_ADVERTISE_10HALF | S17_ADVERTISE_10FULL | \
S17_ADVERTISE_100HALF | S17_ADVERTISE_100FULL)
/* 1000BASET_CONTROL */
#define S17_ADVERTISE_1000FULL 0x0200
/* Phy Specific status fields */
#define S17_STATUS_LINK_MASK 0xC000
#define S17_STATUS_LINK_SHIFT 14
#define S17_STATUS_FULL_DEPLEX 0x2000
#define S17_STATUS_LINK_PASS 0x0400
#define S17_STATUS_RESOLVED 0x0800
#define S17_STATUS_LINK_10M 0
#define S17_STATUS_LINK_100M 1
#define S17_STATUS_LINK_1000M 2
#define S17_GLOBAL_INT_PHYMASK (1 << 15)
#define S17_PHY_LINK_UP 0x400
#define S17_PHY_LINK_DOWN 0x800
#define S17_PHY_LINK_DUPLEX_CHANGE 0x2000
#define S17_PHY_LINK_SPEED_CHANGE 0x4000
/* For Port flow control registers */
#define S17_PORT_FLCTL_XON_DEFAULT (0x3a << 16)
#define S17_PORT_FLCTL_XOFF_DEFAULT (0x4a)
/* Module enable Register */
#define S17_MODULE_L3_EN (1 << 2)
#define S17_MODULE_ACL_EN (1 << 1)
#define S17_MODULE_MIB_EN (1 << 0)
/* MIB Function Register 1 */
#define S17_MIB_FUNC_ALL (3 << 24)
#define S17_MIB_CPU_KEEP (1 << 20)
#define S17_MIB_BUSY (1 << 17)
#define S17_MIB_AT_HALF_EN (1 << 16)
#define S17_MIB_TIMER_DEFAULT 0x100
#define S17_MAC_MAX 7
/* MAC power selector bit definitions */
#define S17_RGMII0_1_8V (1 << 19)
#define S17_RGMII1_1_8V (1 << 18)
/* SGMII_CTRL bit definitions */
#define S17c_SGMII_EN_LCKDT (1 << 0)
#define S17c_SGMII_EN_PLL (1 << 1)
#define S17c_SGMII_EN_RX (1 << 2)
#define S17c_SGMII_EN_TX (1 << 3)
#define S17c_SGMII_EN_SD (1 << 4)
#define S17c_SGMII_BW_HIGH (1 << 6)
#define S17c_SGMII_SEL_CLK125M (1 << 7)
#define S17c_SGMII_TXDR_CTRL_600mV (1 << 10)
#define S17c_SGMII_CDR_BW_8 (3 << 13)
#define S17c_SGMII_DIS_AUTO_LPI_25M (1 << 16)
#define S17c_SGMII_MODE_CTRL_SGMII_PHY (1 << 22)
#define S17c_SGMII_PAUSE_SG_TX_EN_25M (1 << 24)
#define S17c_SGMII_ASYM_PAUSE_25M (1 << 25)
#define S17c_SGMII_PAUSE_25M (1 << 26)
#define S17c_SGMII_HALF_DUPLEX_25M (1 << 30)
#define S17c_SGMII_FULL_DUPLEX_25M (1 << 31)
#ifndef BOOL
#define BOOL int
#endif
/*add feature define here*/
#ifdef CONFIG_AR7242_S17_PHY
#undef HEADER_REG_CONF
#undef HEADER_EN
#endif
#define LINK_UP 0x400
#define LINK(_data) (_data & LINK_UP)? "Up" : "Down"
#define DUPLEX(_data) (_data & 0x2000)?\
"Full duplex" : "Half duplex"
#define SPEED(_data) ((_data & 0xC000) >> 12)
#define SPEED_1000M (1 << 3)
#define SPEED_100M (1 << 2)
#define S17C_MAX_PORT 4
typedef struct {
u32 mac_pwr;
int port_count;
int chip_detect;
u32 port_phy_address[S17C_MAX_PORT];
} ipq_s17c_swt_cfg_t;
#endif

View file

@ -0,0 +1,597 @@
/*
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <net.h>
#include <asm-generic/errno.h>
#include <asm/io.h>
#include <malloc.h>
#include <phy.h>
#include <miiphy.h>
#include "ipq_phy.h"
#include "ipq_aquantia_phy.h"
#include <crc.h>
#include <mmc.h>
#include <asm/errno.h>
#include <nand.h>
#include <spi_flash.h>
#include <spi.h>
#include <asm/global_data.h>
#include <fdtdec.h>
DECLARE_GLOBAL_DATA_PTR;
typedef struct {
unsigned int image_type;
unsigned int header_vsn_num;
unsigned int image_src;
unsigned char *image_dest_ptr;
unsigned int image_size;
unsigned int code_size;
unsigned char *signature_ptr;
unsigned int signature_size;
unsigned char *cert_chain_ptr;
unsigned int cert_chain_size;
} mbn_header_t;
mbn_header_t *fwimg_header;
static int debug = 0;
#ifdef CONFIG_QCA_MMC
extern qca_mmc mmc_host;
static qca_mmc *host = &mmc_host;
#endif
extern int ipq_mdio_write(int mii_id,
int regnum, u16 value);
extern int ipq_mdio_read(int mii_id,
int regnum, ushort *data);
extern int ipq_sw_mdio_init(const char *);
extern void devsoc_eth_initialize(void);
static int program_ethphy_fw(unsigned int phy_addr,
uint32_t load_addr,uint32_t file_size );
static qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
u16 aq_phy_reg_write(u32 dev_id, u32 phy_id,
u32 reg_id, u16 reg_val)
{
ipq_mdio_write(phy_id, reg_id, reg_val);
return 0;
}
u16 aq_phy_reg_read(u32 dev_id, u32 phy_id, u32 reg_id)
{
return ipq_mdio_read(phy_id, reg_id, NULL);
}
u8 aq_phy_get_link_status(u32 dev_id, u32 phy_id)
{
u16 phy_data;
uint32_t reg;
reg = AQ_PHY_AUTO_STATUS_REG | AQUANTIA_MII_ADDR_C45;
phy_data = aq_phy_reg_read(dev_id, phy_id, reg);
phy_data = aq_phy_reg_read(dev_id, phy_id, reg);
if (((phy_data >> 2) & 0x1) & PORT_LINK_UP)
return 0;
return 1;
}
u32 aq_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex)
{
u16 phy_data;
uint32_t reg;
reg = AQ_PHY_LINK_STATUS_REG | AQUANTIA_MII_ADDR_C45;
phy_data = aq_phy_reg_read(dev_id, phy_id, reg);
/*
* Read duplex
*/
phy_data = phy_data & 0x1;
if (phy_data & 0x1)
*duplex = FAL_FULL_DUPLEX;
else
*duplex = FAL_HALF_DUPLEX;
return 0;
}
u32 aq_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed)
{
u16 phy_data;
uint32_t reg;
reg = AQ_PHY_LINK_STATUS_REG | AQUANTIA_MII_ADDR_C45;
phy_data = aq_phy_reg_read(dev_id, phy_id, reg);
switch ((phy_data >> 1) & 0x7) {
case SPEED_10G:
*speed = FAL_SPEED_10000;
break;
case SPEED_5G:
*speed = FAL_SPEED_5000;
break;
case SPEED_2_5G:
*speed = FAL_SPEED_2500;
break;
case SPEED_1000MBS:
*speed = FAL_SPEED_1000;
break;
case SPEED_100MBS:
*speed = FAL_SPEED_100;
break;
case SPEED_10MBS:
*speed = FAL_SPEED_10;
break;
default:
return -EINVAL;
}
return 0;
}
void aquantia_phy_restart_autoneg(u32 phy_id)
{
u16 phy_data;
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS,
AQUANTIA_PHY_XS_USX_TRANSMIT));
if (!(phy_data & AQUANTIA_PHY_USX_AUTONEG_ENABLE))
aq_phy_reg_write(0x0, phy_id,AQUANTIA_REG_ADDRESS(
AQUANTIA_MMD_PHY_XS_REGISTERS,
AQUANTIA_PHY_XS_USX_TRANSMIT),
phy_data | AQUANTIA_PHY_USX_AUTONEG_ENABLE);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG,
AQUANTIA_AUTONEG_STANDARD_CONTROL1));
phy_data |= AQUANTIA_CTRL_AUTONEGOTIATION_ENABLE;
aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG,
AQUANTIA_AUTONEG_STANDARD_CONTROL1),
phy_data | AQUANTIA_CTRL_RESTART_AUTONEGOTIATION);
}
int ipq_qca_aquantia_phy_init(struct phy_ops **ops, u32 phy_id)
{
u16 phy_data;
struct phy_ops *aq_phy_ops;
aq_phy_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
if (!aq_phy_ops)
return -ENOMEM;
aq_phy_ops->phy_get_link_status = aq_phy_get_link_status;
aq_phy_ops->phy_get_speed = aq_phy_get_speed;
aq_phy_ops->phy_get_duplex = aq_phy_get_duplex;
*ops = aq_phy_ops;
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS,
AQUANTIA_PHY_XS_USX_TRANSMIT));
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(1, QCA_PHY_ID1));
printf ("PHY ID1: 0x%x\n", phy_data);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(1, QCA_PHY_ID2));
printf ("PHY ID2: 0x%x\n", phy_data);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS,
AQUANTIA_PHY_XS_USX_TRANSMIT));
phy_data |= AQUANTIA_PHY_USX_AUTONEG_ENABLE;
aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS,
AQUANTIA_PHY_XS_USX_TRANSMIT), phy_data);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG,
AQUANTIA_AUTONEG_TRANSMIT_VENDOR_INTR_MASK));
phy_data |= AQUANTIA_INTR_LINK_STATUS_CHANGE;
aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG,
AQUANTIA_AUTONEG_TRANSMIT_VENDOR_INTR_MASK), phy_data);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS,
AQUANTIA_GLOBAL_INTR_STANDARD_MASK));
phy_data |= AQUANTIA_ALL_VENDOR_ALARMS_INTERRUPT_MASK;
aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS,
AQUANTIA_GLOBAL_INTR_STANDARD_MASK), phy_data);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS,
AQUANTIA_GLOBAL_INTR_VENDOR_MASK));
phy_data |= AQUANTIA_AUTO_AND_ALARMS_INTR_MASK;
aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS,
AQUANTIA_GLOBAL_INTR_VENDOR_MASK), phy_data);
phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS,
AQUANTIA_PHY_XS_USX_TRANSMIT));
return 0;
}
static int do_aq_phy_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned int phy_addr = AQU_PHY_ADDR;
if (argc > 2)
return CMD_RET_USAGE;
if (argc == 2)
phy_addr = simple_strtoul(argv[1], NULL, 16);
aquantia_phy_restart_autoneg(phy_addr);
return 0;
}
int ipq_board_fw_download(unsigned int phy_addr)
{
char runcmd[256];
int ret,i=0;
uint32_t start; /* block number */
uint32_t size; /* no. of blocks */
qca_part_entry_t ethphyfw;
unsigned int *ethphyfw_load_addr = NULL;
struct { char *name; qca_part_entry_t *part; } entries[] = {
{ "0:ETHPHYFW", &ethphyfw },
};
#ifdef CONFIG_QCA_MMC
block_dev_desc_t *blk_dev;
disk_partition_t disk_info;
#endif
/* check the smem info to see which flash used for booting */
if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) {
if (debug) {
printf("Using nor device \n");
}
} else if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) {
if (debug) {
printf("Using nand device 0\n");
}
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
if (debug) {
printf("Using MMC device\n");
}
} else if (sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH) {
if (debug) {
printf("Using qspi nand device 0\n");
}
} else {
printf("Unsupported BOOT flash type\n");
return -1;
}
ret = smem_getpart(entries[i].name, &start, &size);
if (ret < 0) {
debug("cdp: get part failed for %s\n", entries[i].name);
} else {
qca_set_part_entry(entries[i].name, sfi, entries[i].part, start, size);
}
if ((sfi->flash_type == SMEM_BOOT_NAND_FLASH) ||
(sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH) ||
(sfi->flash_type == SMEM_BOOT_SPI_FLASH)) {
ethphyfw_load_addr = (uint *)malloc(AQ_ETHPHYFW_IMAGE_SIZE);
/* We only need memory equivalent to max size ETHPHYFW
* which is currently assumed as 512 KB.
*/
if (ethphyfw_load_addr == NULL) {
printf("ETHPHYFW Loading failed, size = %llu\n",
ethphyfw.size);
return -1;
} else {
memset(ethphyfw_load_addr, 0, AQ_ETHPHYFW_IMAGE_SIZE);
}
}
if ((sfi->flash_type == SMEM_BOOT_NAND_FLASH) ||
(sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH)) {
/*
* Kernel is in a separate partition
*/
snprintf(runcmd, sizeof(runcmd),
/* NOR is treated as psuedo NAND */
"nand read 0x%p 0x%llx 0x%llx && ",
ethphyfw_load_addr, ethphyfw.offset, (long long unsigned int) AQ_ETHPHYFW_IMAGE_SIZE);
if (debug)
printf("%s", runcmd);
if (run_command(runcmd, 0) != CMD_RET_SUCCESS) {
free(ethphyfw_load_addr);
return CMD_RET_FAILURE;
}
} else if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) {
snprintf(runcmd, sizeof(runcmd),
"sf probe && " "sf read 0x%p 0x%llx 0x%llx && ",
ethphyfw_load_addr, ethphyfw.offset, (long long unsigned int) AQ_ETHPHYFW_IMAGE_SIZE);
if (debug)
printf("%s", runcmd);
if (run_command(runcmd, 0) != CMD_RET_SUCCESS) {
free(ethphyfw_load_addr);
return CMD_RET_FAILURE;
}
#ifdef CONFIG_QCA_MMC
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH ) {
blk_dev = mmc_get_dev(host->dev_num);
ret = get_partition_info_efi_by_name(blk_dev,
"0:ETHPHYFW", &disk_info);
ethphyfw_load_addr = (uint *)malloc(((uint)disk_info.size) *
((uint)disk_info.blksz));
if (ethphyfw_load_addr == NULL) {
printf("ETHPHYFW Loading failed, size = %lu\n",
((long unsigned int)(uint)disk_info.size) * ((uint)disk_info.blksz));
return -1;
} else {
memset(ethphyfw_load_addr, 0,
(((uint)disk_info.size) *
((uint)disk_info.blksz)));
}
if (ret == 0) {
snprintf(runcmd, sizeof(runcmd),
"mmc read 0x%p 0x%X 0x%X",
ethphyfw_load_addr,
(uint)disk_info.start, (uint)disk_info.size);
if (run_command(runcmd, 0) != CMD_RET_SUCCESS) {
free(ethphyfw_load_addr);
return CMD_RET_FAILURE;
}
}
#endif
}
fwimg_header = (mbn_header_t *)(ethphyfw_load_addr);
if (fwimg_header->image_type == 0x13 &&
fwimg_header->header_vsn_num == 0x3) {
program_ethphy_fw(phy_addr,
(uint32_t)(((uint32_t)ethphyfw_load_addr)
+ sizeof(mbn_header_t)),
(uint32_t)(fwimg_header->image_size));
} else {
printf("bad magic on ETHPHYFW partition\n");
free(ethphyfw_load_addr);
return -1;
}
free(ethphyfw_load_addr);
return 0;
}
#define AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD 0x300
static int program_ethphy_fw(unsigned int phy_addr, uint32_t load_addr, uint32_t file_size)
{
int i;
uint8_t *buf;
uint16_t file_crc;
uint16_t computed_crc;
uint32_t reg1, reg2;
uint16_t recorded_ggp8_val;
uint16_t daisy_chain_dis;
uint32_t primary_header_ptr = 0x00000000;
uint32_t primary_iram_ptr = 0x00000000;
uint32_t primary_dram_ptr = 0x00000000;
uint32_t primary_iram_sz = 0x00000000;
uint32_t primary_dram_sz = 0x00000000;
uint32_t phy_img_hdr_off;
uint32_t byte_sz;
uint32_t dword_sz;
uint32_t byte_ptr;
uint16_t msw = 0;
uint16_t lsw = 0;
uint8_t msb1;
uint8_t msb2;
uint8_t lsb1;
uint8_t lsb2;
uint16_t mailbox_crc;
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x300), 0xdead);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x301), 0xbeaf);
reg1 = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x300));
reg2 = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x301));
if(reg1 != 0xdead && reg2 != 0xbeaf) {
printf("PHY::Scratchpad Read/Write test fail\n");
return 0;
}
buf = (uint8_t *)load_addr;
file_crc = buf[file_size - 2] << 8 | buf[file_size - 1];
computed_crc = cyg_crc16(buf, file_size - 2);
if (file_crc != computed_crc) {
printf("CRC check failed on phy fw file\n");
return 0;
} else {
printf("CRC check good on phy fw file (0x%04X)\n",computed_crc);
}
daisy_chain_dis = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc452));
if (!(daisy_chain_dis & 0x1))
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc452), 0x1);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc471), 0x40);
recorded_ggp8_val = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc447));
if ((recorded_ggp8_val & 0x1f) != phy_addr)
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc447), phy_addr);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc441), 0x4000);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x41);
primary_header_ptr = (((buf[0x9] & 0x0F) << 8) | buf[0x8]) << 12;
phy_img_hdr_off = AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD;
primary_iram_ptr = (buf[primary_header_ptr + phy_img_hdr_off + 0x4 + 2] << 16) |
(buf[primary_header_ptr + phy_img_hdr_off + 0x4 + 1] << 8) |
buf[primary_header_ptr + phy_img_hdr_off + 0x4];
primary_iram_sz = (buf[primary_header_ptr + phy_img_hdr_off + 0x7 + 2] << 16) |
(buf[primary_header_ptr + phy_img_hdr_off + 0x7 + 1] << 8) |
buf[primary_header_ptr + phy_img_hdr_off + 0x7];
primary_dram_ptr = (buf[primary_header_ptr + phy_img_hdr_off + 0xA + 2] << 16) |
(buf[primary_header_ptr + phy_img_hdr_off + 0xA + 1] << 8) |
buf[primary_header_ptr + phy_img_hdr_off + 0xA];
primary_dram_sz = (buf[primary_header_ptr + phy_img_hdr_off + 0xD + 2] << 16) |
(buf[primary_header_ptr + phy_img_hdr_off + 0xD + 1] << 8) |
buf[primary_header_ptr + phy_img_hdr_off + 0xD];
primary_iram_ptr += primary_header_ptr;
primary_dram_ptr += primary_header_ptr;
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0x1000);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0x0);
computed_crc = 0;
printf("PHYFW:Loading IRAM...........");
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x202), 0x4000);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x203), 0x0);
byte_sz = primary_iram_sz;
dword_sz = byte_sz >> 2;
byte_ptr = primary_iram_ptr;
for (i = 0; i < dword_sz; i++) {
lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
msw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000);
msb1 = msw >> 8;
msb2 = msw & 0xFF;
lsb1 = lsw >> 8;
lsb2 = lsw & 0xFF;
computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc);
}
switch (byte_sz & 0x3) {
case 0x1:
lsw = buf[byte_ptr++];
msw = 0x0000;
break;
case 0x2:
lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
msw = 0x0000;
break;
case 0x3:
lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
msw = buf[byte_ptr++];
break;
}
if (byte_sz & 0x3) {
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000);
msb1 = msw >> 8;
msb2 = msw & 0xFF;
lsb1 = lsw >> 8;
lsb2 = lsw & 0xFF;
computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc);
}
printf("done.\n");
printf("PHYFW:Loading DRAM..............");
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x202), 0x3ffe);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x203), 0x0);
byte_sz = primary_dram_sz;
dword_sz = byte_sz >> 2;
byte_ptr = primary_dram_ptr;
for (i = 0; i < dword_sz; i++) {
lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
msw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000);
msb1 = msw >> 8;
msb2 = msw & 0xFF;
lsb1 = lsw >> 8;
lsb2 = lsw & 0xFF;
computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc);
}
switch (byte_sz & 0x3) {
case 0x1:
lsw = buf[byte_ptr++];
msw = 0x0000;
break;
case 0x2:
lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
msw = 0x0000;
break;
case 0x3:
lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr];
byte_ptr += 2;
msw = buf[byte_ptr++];
break;
}
if (byte_sz & 0x3) {
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000);
msb1 = msw >> 8;
msb2 = msw & 0xFF;
lsb1 = lsw >> 8;
lsb2 = lsw & 0xFF;
computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc);
computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc);
}
printf("done.\n");
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc441), 0x2010);
mailbox_crc = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x201));
if (mailbox_crc != computed_crc) {
printf("phy fw image load CRC-16 (0x%X) does not match calculated CRC-16 (0x%X)\n", mailbox_crc, computed_crc);
return 0;
} else
printf("phy fw image load good CRC-16 matches (0x%X)\n", mailbox_crc);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x0), 0x0);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x41);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x8041);
mdelay(100);
aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x40);
mdelay(100);
aquantia_phy_restart_autoneg(phy_addr);
return 0;
}
static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned int phy_addr = AQU_PHY_ADDR;
if (argc > 2)
return CMD_RET_USAGE;
if (argc == 2)
phy_addr = simple_strtoul(argv[1], NULL, 16);
miiphy_init();
devsoc_eth_initialize();
ipq_sw_mdio_init("IPQ MDIO0");
ipq_board_fw_download(phy_addr);
return 0;
}
U_BOOT_CMD(
aq_load_fw, 5, 1, do_load_fw,
"LOAD aq-fw-binary",
""
);
U_BOOT_CMD(
aq_phy_restart, 5, 1, do_aq_phy_restart,
"Restart Aquantia phy",
""
);

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define AQ_ETHPHYFW_IMAGE_SIZE 0x80000
#define AQUANTIA_MII_ADDR_C45 (1<<30)
#define AQUANTIA_REG_ADDRESS(dev_ad, reg_num) (AQUANTIA_MII_ADDR_C45 |\
((dev_ad & 0x1f) << 16) | (reg_num & 0xFFFF))
#define AQUANTIA_MMD_PHY_XS_REGISTERS 4
#define AQUANTIA_PHY_XS_USX_TRANSMIT 0xc441
#define AQUANTIA_PHY_USX_AUTONEG_ENABLE 0x8
#define AQUANTIA_MMD_AUTONEG 0x7
#define AQUANTIA_AUTONEG_TRANSMIT_VENDOR_INTR_MASK 0xD401
#define AQUANTIA_INTR_LINK_STATUS_CHANGE 0x0001
#define AQUANTIA_MMD_GLOABLE_REGISTERS 0x1E
#define AQUANTIA_GLOBAL_INTR_STANDARD_MASK 0xff00
#define AQUANTIA_ALL_VENDOR_ALARMS_INTERRUPT_MASK 0x0001
#define AQUANTIA_GLOBAL_INTR_VENDOR_MASK 0xff01
#define AQUANTIA_AUTO_AND_ALARMS_INTR_MASK 0x1001
#define AQUANTIA_AUTONEG_STANDARD_CONTROL1 0
#define AQUANTIA_CTRL_AUTONEGOTIATION_ENABLE 0x1000
#define AQUANTIA_CTRL_RESTART_AUTONEGOTIATION 0x0200
#define AQ_PHY_AUTO_STATUS_REG 0x70001
#define AQ_PHY_LINK_STATUS_REG 0x7c800
#define SPEED_5G 5
#define SPEED_2_5G 4
#define SPEED_10G 3
#define SPEED_1000MBS 2
#define SPEED_100MBS 1
#define SPEED_10MBS 0

View file

@ -16,6 +16,9 @@
#include <common.h>
#include <net.h>
#ifdef CONFIG_ATHRS17C_SWITCH
#include "athrs17_phy.h"
#endif
#define PHY_MAX 6
#define IPQ9574_PHY_MAX 6
@ -40,6 +43,7 @@
#define GP_PU_RES(x) (x << 13)
#define QCA8075_RST_VAL (GP_PULL_DOWN | GP_OE_EN | \
GP_VM_EN | GP_PU_RES(2))
#define QCA8337_PHY 0x004DD036
#define QCA8075_PHY_V1_0_5P 0x004DD0B0
#define QCA8075_PHY_V1_1_5P 0x004DD0B1
#define QCA8075_PHY_V1_1_2P 0x004DD0B2
@ -144,6 +148,7 @@ enum phy_mode {
QCA8033_PHY_TYPE = 4,
SFP_PHY_TYPE = 5,
QCA8084_PHY_TYPE = 6,
ATHRS17C_SWITCH_TYPE = 7,
UNUSED_PHY_TYPE = 0xFF,
};

View file

@ -46,5 +46,8 @@
#define AQ_PHY_TYPE 0x3
#define QCA8033_PHY_TYPE 0x4
#define SFP_PHY_TYPE 0x5
#define QCA8084_PHY_TYPE 0x6
#define ATHRS17C_SWITCH_TYPE 0x7
#define UNUSED_PHY_TYPE 0xFF
#endif