mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
drivers: net: Add support for QCA8084 PHY
This patch adds initial support for qca8084 PHY which is based on qca8081 PHY. qca8084 PHY has support for 4x2.5G. Change-Id: Ic767c19fad050e5ee9a97ad7fa50c1b6b27893dd Signed-off-by: Selvam Sathappan Periakaruppan <quic_speriaka@quicinc.com>
This commit is contained in:
parent
5837a5e6c6
commit
18d2b93ab3
15 changed files with 2698 additions and 0 deletions
|
|
@ -18,4 +18,6 @@ config IPQ9574_QCA_AQUANTIA_PHY
|
||||||
config IPQ9574_QCA8075_PHY
|
config IPQ9574_QCA8075_PHY
|
||||||
bool "Enable Malibu PHY support for ipq9574"
|
bool "Enable Malibu PHY support for ipq9574"
|
||||||
|
|
||||||
|
config QCA8084_PHY
|
||||||
|
bool "Enable QCA8084 PHY support for ipq9574"
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ CONFIG_CMD_NFS=y
|
||||||
CONFIG_IPQ9574_QCA_AQUANTIA_PHY=y
|
CONFIG_IPQ9574_QCA_AQUANTIA_PHY=y
|
||||||
# CONFIG_QCA8033_PHY is not set
|
# CONFIG_QCA8033_PHY is not set
|
||||||
CONFIG_QCA8081_PHY=y
|
CONFIG_QCA8081_PHY=y
|
||||||
|
CONFIG_QCA8084_PHY=y
|
||||||
CONFIG_IPQ9574_QCA8075_PHY=y
|
CONFIG_IPQ9574_QCA8075_PHY=y
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,9 @@ obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/athrs17_phy.o
|
||||||
obj-$(CONFIG_IPQ_MDIO) += ipq_common/ipq_mdio.o
|
obj-$(CONFIG_IPQ_MDIO) += ipq_common/ipq_mdio.o
|
||||||
obj-$(CONFIG_GEPHY) += ipq_common/ipq_gephy.o
|
obj-$(CONFIG_GEPHY) += ipq_common/ipq_gephy.o
|
||||||
obj-$(CONFIG_QCA8075_PHY) += ipq_common/ipq_qca8075.o
|
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_IPQ9574_QCA8075_PHY) += ipq9574/ipq9574_qca8075.o
|
obj-$(CONFIG_IPQ9574_QCA8075_PHY) += ipq9574/ipq9574_qca8075.o
|
||||||
obj-$(CONFIG_QCA8033_PHY) += ipq_common/ipq_qca8033.o
|
obj-$(CONFIG_QCA8033_PHY) += ipq_common/ipq_qca8033.o
|
||||||
obj-$(CONFIG_QCA8081_PHY) += ipq_common/ipq_qca8081.o
|
obj-$(CONFIG_QCA8081_PHY) += ipq_common/ipq_qca8081.o
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <miiphy.h>
|
#include <miiphy.h>
|
||||||
|
|
@ -19,6 +21,12 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "ipq_mdio.h"
|
#include "ipq_mdio.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define pr_debug(fmt, args...) printf(fmt, ##args);
|
||||||
|
#else
|
||||||
|
#define pr_debug(fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ipq_mdio_data {
|
struct ipq_mdio_data {
|
||||||
struct mii_bus *bus;
|
struct mii_bus *bus;
|
||||||
int phy_irq[PHY_MAX_ADDR];
|
int phy_irq[PHY_MAX_ADDR];
|
||||||
|
|
@ -162,6 +170,202 @@ int ipq_phy_read(struct mii_dev *bus,
|
||||||
return ipq_mdio_read(addr, regnum, NULL);
|
return ipq_mdio_read(addr, regnum, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_QCA8084_PHY
|
||||||
|
static inline void split_addr(uint32_t regaddr, uint16_t *r1, uint16_t *r2,
|
||||||
|
uint16_t *page, uint16_t *switch_phy_id)
|
||||||
|
{
|
||||||
|
*r1 = regaddr & 0x1c;
|
||||||
|
|
||||||
|
regaddr >>= 5;
|
||||||
|
*r2 = regaddr & 0x7;
|
||||||
|
|
||||||
|
regaddr >>= 3;
|
||||||
|
*page = regaddr & 0xffff;
|
||||||
|
|
||||||
|
regaddr >>= 16;
|
||||||
|
*switch_phy_id = regaddr & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ipq_mii_read(uint32_t reg)
|
||||||
|
{
|
||||||
|
uint16_t r1, r2, page, switch_phy_id;
|
||||||
|
uint16_t lo, hi;
|
||||||
|
|
||||||
|
split_addr((uint32_t) reg, &r1, &r2, &page, &switch_phy_id);
|
||||||
|
|
||||||
|
mutex_lock(&switch_mdio_lock);
|
||||||
|
ipq_mdio_write(0x18 | (switch_phy_id >> 5), switch_phy_id & 0x1f, page);
|
||||||
|
udelay(100);
|
||||||
|
lo = ipq_mdio_read(0x10 | r2, r1, NULL);
|
||||||
|
hi = ipq_mdio_read(0x10 | r2, r1 + 2, NULL);
|
||||||
|
mutex_unlock(&switch_mdio_lock);
|
||||||
|
|
||||||
|
return (hi << 16) | lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipq_mii_write(uint32_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
uint16_t r1, r2, page, switch_phy_id;
|
||||||
|
uint16_t lo, hi;
|
||||||
|
|
||||||
|
split_addr((uint32_t) reg, &r1, &r2, &page, &switch_phy_id);
|
||||||
|
lo = val & 0xffff;
|
||||||
|
hi = (uint16_t) (val >> 16);
|
||||||
|
|
||||||
|
mutex_lock(&switch_mdio_lock);
|
||||||
|
ipq_mdio_write(0x18 | (switch_phy_id >> 5), switch_phy_id & 0x1f, page);
|
||||||
|
udelay(100);
|
||||||
|
ipq_mdio_write(0x10 | r2, r1, lo);
|
||||||
|
ipq_mdio_write(0x10 | r2, r1 + 2, hi);
|
||||||
|
mutex_unlock(&switch_mdio_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipq_mii_update(uint32_t reg, uint32_t mask, uint32_t val)
|
||||||
|
{
|
||||||
|
uint32_t new_val = 0, org_val = 0;
|
||||||
|
|
||||||
|
org_val = ipq_mii_read(reg);
|
||||||
|
|
||||||
|
new_val = org_val & ~mask;
|
||||||
|
new_val |= val & mask;
|
||||||
|
|
||||||
|
if (new_val != org_val)
|
||||||
|
ipq_mii_write(reg, new_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipq_clk_enable(uint32_t reg)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = ipq_mii_read(reg);
|
||||||
|
val |= BIT(0);
|
||||||
|
ipq_mii_write(reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipq_clk_disable(uint32_t reg)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = ipq_mii_read(reg);
|
||||||
|
val &= ~BIT(0);
|
||||||
|
ipq_mii_write(reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipq_clk_reset(uint32_t reg)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = ipq_mii_read(reg);
|
||||||
|
val |= BIT(2);
|
||||||
|
ipq_mii_write(reg, val);
|
||||||
|
|
||||||
|
udelay(21000);
|
||||||
|
|
||||||
|
val &= ~BIT(2);
|
||||||
|
ipq_mii_write(reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipq_clock_init(void)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Enable serdes */
|
||||||
|
ipq_clk_enable(SRDS0_SYS_CBCR);
|
||||||
|
ipq_clk_enable(SRDS1_SYS_CBCR);
|
||||||
|
|
||||||
|
/* Reset serdes */
|
||||||
|
ipq_clk_reset(SRDS0_SYS_CBCR);
|
||||||
|
ipq_clk_reset(SRDS1_SYS_CBCR);
|
||||||
|
|
||||||
|
/* Disable EPHY GMII clock */
|
||||||
|
i = 0;
|
||||||
|
while (i < 2 * PHY_ADDR_NUM) {
|
||||||
|
ipq_clk_disable(GEPHY0_TX_CBCR + i*0x20);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable ephy */
|
||||||
|
ipq_clk_enable(EPHY0_SYS_CBCR);
|
||||||
|
ipq_clk_enable(EPHY1_SYS_CBCR);
|
||||||
|
ipq_clk_enable(EPHY2_SYS_CBCR);
|
||||||
|
ipq_clk_enable(EPHY3_SYS_CBCR);
|
||||||
|
|
||||||
|
/* Reset ephy */
|
||||||
|
ipq_clk_reset(EPHY0_SYS_CBCR);
|
||||||
|
ipq_clk_reset(EPHY1_SYS_CBCR);
|
||||||
|
ipq_clk_reset(EPHY2_SYS_CBCR);
|
||||||
|
ipq_clk_reset(EPHY3_SYS_CBCR);
|
||||||
|
|
||||||
|
/* Deassert EPHY DSP */
|
||||||
|
val = ipq_mii_read(GCC_GEPHY_MISC);
|
||||||
|
val &= ~GENMASK(4, 0);
|
||||||
|
ipq_mii_write(GCC_GEPHY_MISC, val);
|
||||||
|
|
||||||
|
/* Enable efuse loading into analog circuit */
|
||||||
|
val = ipq_mii_read(EPHY_CFG);
|
||||||
|
/* BIT20 for PHY0 and PHY1, BIT21 for PHY2 and PHY3 */
|
||||||
|
val &= ~GENMASK(21, 20);
|
||||||
|
ipq_mii_write(EPHY_CFG, val);
|
||||||
|
|
||||||
|
udelay(11000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipq_phy_addr_fixup(void)
|
||||||
|
{
|
||||||
|
int phy_index, addr;
|
||||||
|
u32 val;
|
||||||
|
unsigned long phyaddr_mask = 0;
|
||||||
|
|
||||||
|
val = ipq_mii_read(EPHY_CFG);
|
||||||
|
|
||||||
|
for (phy_index = 0, addr = 1; addr <= 4; phy_index++, addr++) {
|
||||||
|
phyaddr_mask |= BIT(addr);
|
||||||
|
addr &= GENMASK(4, 0);
|
||||||
|
val &= ~(GENMASK(4, 0) << (phy_index * PHY_ADDR_LENGTH));
|
||||||
|
val |= addr << (phy_index * PHY_ADDR_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("programme EPHY reg 0x%x with 0x%x\n", EPHY_CFG, val);
|
||||||
|
ipq_mii_write(EPHY_CFG, val);
|
||||||
|
|
||||||
|
/* Programe the UNIPHY address if uniphyaddr_fixup specified.
|
||||||
|
* the UNIPHY address will select three MDIO address from
|
||||||
|
* unoccupied MDIO address space.
|
||||||
|
*/
|
||||||
|
val = ipq_mii_read(UNIPHY_CFG);
|
||||||
|
|
||||||
|
/* For qca8386, the switch occupies the other 16 MDIO address,
|
||||||
|
* for example, if the phy address is in the range of 0 to 15,
|
||||||
|
* the switch will occupy the MDIO address from 16 to 31.
|
||||||
|
*/
|
||||||
|
phyaddr_mask |= GENMASK(31, 16);
|
||||||
|
|
||||||
|
phy_index = 0;
|
||||||
|
|
||||||
|
for_each_clear_bit_from(addr, &phyaddr_mask, PHY_MAX_ADDR) {
|
||||||
|
if (phy_index >= UNIPHY_ADDR_NUM)
|
||||||
|
break;
|
||||||
|
val &= ~(GENMASK(4, 0) << (phy_index * PHY_ADDR_LENGTH));
|
||||||
|
val |= addr << (phy_index * PHY_ADDR_LENGTH);
|
||||||
|
phy_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phy_index < UNIPHY_ADDR_NUM) {
|
||||||
|
for_each_clear_bit(addr, &phyaddr_mask, PHY_MAX_ADDR) {
|
||||||
|
if (phy_index >= UNIPHY_ADDR_NUM)
|
||||||
|
break;
|
||||||
|
val &= ~(GENMASK(4, 0) << (phy_index * PHY_ADDR_LENGTH));
|
||||||
|
val |= addr << (phy_index * PHY_ADDR_LENGTH);
|
||||||
|
phy_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("programme UNIPHY reg 0x%x with 0x%x\n", UNIPHY_CFG, val);
|
||||||
|
ipq_mii_write(UNIPHY_CFG, val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int ipq_sw_mdio_init(const char *name)
|
int ipq_sw_mdio_init(const char *name)
|
||||||
{
|
{
|
||||||
struct mii_dev *bus = mdio_alloc();
|
struct mii_dev *bus = mdio_alloc();
|
||||||
|
|
@ -169,6 +373,7 @@ int ipq_sw_mdio_init(const char *name)
|
||||||
printf("Failed to allocate IPQ MDIO bus\n");
|
printf("Failed to allocate IPQ MDIO bus\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus->read = ipq_phy_read;
|
bus->read = ipq_phy_read;
|
||||||
bus->write = ipq_phy_write;
|
bus->write = ipq_phy_write;
|
||||||
bus->reset = NULL;
|
bus->reset = NULL;
|
||||||
|
|
@ -176,6 +381,47 @@ int ipq_sw_mdio_init(const char *name)
|
||||||
return mdio_register(bus);
|
return mdio_register(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_QCA8084_PHY
|
||||||
|
static int do_ipq_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
char op[2];
|
||||||
|
unsigned int reg = 0;
|
||||||
|
unsigned short data = 0;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
|
||||||
|
op[0] = argv[1][0];
|
||||||
|
if (strlen(argv[1]) > 1)
|
||||||
|
op[1] = argv[1][1];
|
||||||
|
else
|
||||||
|
op[1] = '\0';
|
||||||
|
|
||||||
|
if (argc >= 3)
|
||||||
|
reg = simple_strtoul(argv[2], NULL, 16);
|
||||||
|
if (argc >= 4)
|
||||||
|
data = simple_strtoul(argv[3], NULL, 16);
|
||||||
|
|
||||||
|
if (op[0] == 'r') {
|
||||||
|
data = ipq_mii_read(reg);
|
||||||
|
printf("0x%x\n", data);
|
||||||
|
} else if (op[0] == 'w') {
|
||||||
|
ipq_mii_write(reg, data);
|
||||||
|
} else {
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_CMD(
|
||||||
|
ipq_mii, 4, 1, do_ipq_mii,
|
||||||
|
"IPQ mii utility commands",
|
||||||
|
"ipq_mii read <reg> - read IPQ MII register <reg>\n"
|
||||||
|
"ipq_mii write <reg> <data> - write IPQ MII register <reg> with <data>\n"
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int do_ipq_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
static int do_ipq_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
{
|
{
|
||||||
char op[2];
|
char op[2];
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,24 @@
|
||||||
#endif
|
#endif
|
||||||
#define IPQ_MDIO_RETRY 1000
|
#define IPQ_MDIO_RETRY 1000
|
||||||
#define IPQ_MDIO_DELAY 5
|
#define IPQ_MDIO_DELAY 5
|
||||||
|
|
||||||
|
/* QCA8084 related MDIO Init macros */
|
||||||
|
#define UNIPHY_CFG 0xC90F014
|
||||||
|
#define EPHY_CFG 0xC90F018
|
||||||
|
#define GEPHY0_TX_CBCR 0xC800058
|
||||||
|
#define SRDS0_SYS_CBCR 0xC8001A8
|
||||||
|
#define SRDS1_SYS_CBCR 0xC8001AC
|
||||||
|
#define EPHY0_SYS_CBCR 0xC8001B0
|
||||||
|
#define EPHY1_SYS_CBCR 0xC8001B4
|
||||||
|
#define EPHY2_SYS_CBCR 0xC8001B8
|
||||||
|
#define EPHY3_SYS_CBCR 0xC8001BC
|
||||||
|
#define GCC_GEPHY_MISC 0xC800304
|
||||||
|
#define PHY_ADDR_LENGTH 5
|
||||||
|
#define PHY_ADDR_NUM 4
|
||||||
|
#define UNIPHY_ADDR_NUM 3
|
||||||
|
#define MII_HIGH_ADDR_PREFIX 0x18
|
||||||
|
#define MII_LOW_ADDR_PREFIX 0x10
|
||||||
|
|
||||||
|
DEFINE_MUTEX(switch_mdio_lock);
|
||||||
|
|
||||||
#endif /* End _IPQ_MDIO_H */
|
#endif /* End _IPQ_MDIO_H */
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
#define QCA8033_PHY_ADDR 0x6
|
#define QCA8033_PHY_ADDR 0x6
|
||||||
#define QCA8081_PHY 0x004DD100
|
#define QCA8081_PHY 0x004DD100
|
||||||
#define QCA8081_1_1_PHY 0x004DD101
|
#define QCA8081_1_1_PHY 0x004DD101
|
||||||
|
#define QCA8084_PHY 0x004DD180
|
||||||
#define AQUANTIA_PHY_107 0x03a1b4e2
|
#define AQUANTIA_PHY_107 0x03a1b4e2
|
||||||
#define AQUANTIA_PHY_109 0x03a1b502
|
#define AQUANTIA_PHY_109 0x03a1b502
|
||||||
#define AQUANTIA_PHY_111 0x03a1b610
|
#define AQUANTIA_PHY_111 0x03a1b610
|
||||||
|
|
@ -113,6 +114,8 @@ enum eport_wrapper_cfg {
|
||||||
EPORT_WRAPPER_RGMII,
|
EPORT_WRAPPER_RGMII,
|
||||||
EPORT_WRAPPER_PSGMII_FIBER,
|
EPORT_WRAPPER_PSGMII_FIBER,
|
||||||
EPORT_WRAPPER_SGMII_FIBER,
|
EPORT_WRAPPER_SGMII_FIBER,
|
||||||
|
EPORT_WRAPPER_UQXGMII, /* for four channels qca8084 phy mode*/
|
||||||
|
EPORT_WRAPPER_UQXGMII_3CHANNELS, /* for three channels qca8084 phy mode */
|
||||||
EPORT_WRAPPER_MAX = 0xFF
|
EPORT_WRAPPER_MAX = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -134,6 +137,8 @@ enum phy_mode {
|
||||||
AQ_PHY_TYPE = 3,
|
AQ_PHY_TYPE = 3,
|
||||||
QCA8033_PHY_TYPE = 4,
|
QCA8033_PHY_TYPE = 4,
|
||||||
SFP_PHY_TYPE = 5,
|
SFP_PHY_TYPE = 5,
|
||||||
|
QCA8084_PHY_TYPE = 6,
|
||||||
|
UNUSED_PHY_TYPE = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
280
drivers/net/ipq_common/ipq_qca8084.c
Normal file
280
drivers/net/ipq_common/ipq_qca8084.c
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, The Linux Foundation. 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 "ipq_phy.h"
|
||||||
|
#include "ipq_qca8081.h"
|
||||||
|
#include "ipq_qca8084.h"
|
||||||
|
#include "ipq_qca8084_clk.h"
|
||||||
|
#include <linux/compat.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define pr_debug(fmt, args...) printf(fmt, ##args);
|
||||||
|
#else
|
||||||
|
#define pr_debug(fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int ipq_mdio_read(int mii_id,
|
||||||
|
int regnum, ushort *data);
|
||||||
|
extern int ipq_mdio_write(int mii_id,
|
||||||
|
int regnum, u16 data);
|
||||||
|
extern void qca8084_interface_uqxgmii_mode_set(void);
|
||||||
|
extern void qca8084_gcc_clock_init(void);
|
||||||
|
extern u8 qca8081_phy_get_link_status(u32 dev_id, u32 phy_id);
|
||||||
|
extern u32 qca8081_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex);
|
||||||
|
extern u32 qca8081_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed);
|
||||||
|
extern void qca8084_uniphy_xpcs_autoneg_restart(uint32_t qca8084_port_id);
|
||||||
|
extern void qca8084_port_speed_clock_set(uint32_t qca8084_port_id,
|
||||||
|
fal_port_speed_t speed);
|
||||||
|
extern void qca8084_uniphy_xpcs_speed_set(uint32_t qca8084_port_id,
|
||||||
|
fal_port_speed_t speed);
|
||||||
|
extern void qca8084_port_clk_en_set(uint32_t qca8084_port_id, uint8_t mask,
|
||||||
|
uint8_t enable);
|
||||||
|
extern void qca8084_port_clk_reset(uint32_t qca8084_port_id, uint8_t mask);
|
||||||
|
extern void qca8084_uniphy_uqxgmii_function_reset(uint32_t qca8084_port_id);
|
||||||
|
|
||||||
|
u16 qca8084_phy_reg_read(u32 phy_addr, u32 reg_id)
|
||||||
|
{
|
||||||
|
return ipq_mdio_read(phy_addr, reg_id, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 qca8084_phy_reg_write(u32 phy_addr, u32 reg_id, u16 value)
|
||||||
|
{
|
||||||
|
return ipq_mdio_write(phy_addr, reg_id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 qca8084_phy_mmd_read(u32 phy_addr, u16 mmd_num, u16 reg_id)
|
||||||
|
{
|
||||||
|
uint32_t reg_id_c45 = QCA8084_REG_C45_ADDRESS(mmd_num, reg_id);
|
||||||
|
|
||||||
|
return ipq_mdio_read(phy_addr, reg_id_c45, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 qca8084_phy_mmd_write(u32 phy_addr, u16 mmd_num, u16 reg_id, u16 value)
|
||||||
|
{
|
||||||
|
uint32_t reg_id_c45 = QCA8084_REG_C45_ADDRESS(mmd_num, reg_id);
|
||||||
|
|
||||||
|
return ipq_mdio_write(phy_addr, reg_id_c45, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_modify_mii(uint32_t phy_addr, uint32_t mii_reg, uint32_t mask,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
uint16_t phy_data = 0, new_phy_data = 0;
|
||||||
|
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, mii_reg);
|
||||||
|
new_phy_data = (phy_data & ~mask) | value;
|
||||||
|
qca8084_phy_reg_write(phy_addr, mii_reg, new_phy_data);
|
||||||
|
/*check the mii register value*/
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, mii_reg);
|
||||||
|
pr_debug("phy_addr:0x%x, mii_reg:0x%x, phy_data:0x%x\n",
|
||||||
|
phy_addr, mii_reg, phy_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_modify_mmd(uint32_t phy_addr, uint32_t mmd_num,
|
||||||
|
uint32_t mmd_reg, uint32_t mask, uint32_t value)
|
||||||
|
{
|
||||||
|
uint16_t phy_data = 0, new_phy_data = 0;
|
||||||
|
|
||||||
|
phy_data = qca8084_phy_mmd_read(phy_addr, mmd_num, mmd_reg);
|
||||||
|
new_phy_data = (phy_data & ~mask) | value;
|
||||||
|
qca8084_phy_mmd_write(phy_addr, mmd_num, mmd_reg, new_phy_data);
|
||||||
|
/* check the mmd register value */
|
||||||
|
phy_data = qca8084_phy_mmd_read(phy_addr, mmd_num, mmd_reg);
|
||||||
|
pr_debug("phy_addr:0x%x, mmd_reg:0x%x, phy_data:0x%x\n",
|
||||||
|
phy_addr, mmd_reg, phy_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_ipg_config(uint32_t phy_id, fal_port_speed_t speed)
|
||||||
|
{
|
||||||
|
uint16_t phy_data = 0;
|
||||||
|
|
||||||
|
phy_data = qca8084_phy_mmd_read(phy_id, QCA8084_PHY_MMD7_NUM,
|
||||||
|
QCA8084_PHY_MMD7_IPG_10_11_ENABLE);
|
||||||
|
|
||||||
|
phy_data &= ~QCA8084_PHY_MMD7_IPG_11_EN;
|
||||||
|
|
||||||
|
/*If speed is 1G, enable 11 ipg tuning*/
|
||||||
|
pr_debug("if speed is 1G, enable 11 ipg tuning\n");
|
||||||
|
if (speed == FAL_SPEED_1000)
|
||||||
|
phy_data |= QCA8084_PHY_MMD7_IPG_11_EN;
|
||||||
|
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD7_NUM,
|
||||||
|
QCA8084_PHY_MMD7_IPG_10_11_ENABLE, phy_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_function_reset(uint32_t phy_id)
|
||||||
|
{
|
||||||
|
uint16_t phy_data = 0;
|
||||||
|
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_id, QCA8084_PHY_FIFO_CONTROL);
|
||||||
|
|
||||||
|
qca8084_phy_reg_write(phy_id, QCA8084_PHY_FIFO_CONTROL,
|
||||||
|
phy_data & (~QCA8084_PHY_FIFO_RESET));
|
||||||
|
|
||||||
|
mdelay(50);
|
||||||
|
|
||||||
|
qca8084_phy_reg_write(phy_id, QCA8084_PHY_FIFO_CONTROL,
|
||||||
|
phy_data | QCA8084_PHY_FIFO_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_uqxgmii_speed_fixup(uint32_t phy_addr, uint32_t qca8084_port_id,
|
||||||
|
uint32_t status, fal_port_speed_t new_speed)
|
||||||
|
{
|
||||||
|
uint32_t port_clock_en = 0;
|
||||||
|
|
||||||
|
/*Restart the auto-neg of uniphy*/
|
||||||
|
pr_debug("Restart the auto-neg of uniphy\n");
|
||||||
|
qca8084_uniphy_xpcs_autoneg_restart(qca8084_port_id);
|
||||||
|
|
||||||
|
/*set gmii+ clock to uniphy1 and ethphy*/
|
||||||
|
pr_debug("set gmii,xgmii clock to uniphy and gmii to ethphy\n");
|
||||||
|
qca8084_port_speed_clock_set(qca8084_port_id, new_speed);
|
||||||
|
|
||||||
|
/*set xpcs speed*/
|
||||||
|
pr_debug("set xpcs speed\n");
|
||||||
|
qca8084_uniphy_xpcs_speed_set(qca8084_port_id, new_speed);
|
||||||
|
|
||||||
|
/*GMII/XGMII clock and ETHPHY GMII clock enable/disable*/
|
||||||
|
pr_debug("GMII/XGMII clock and ETHPHY GMII clock enable/disable\n");
|
||||||
|
if (status == 0)
|
||||||
|
port_clock_en = 1;
|
||||||
|
qca8084_port_clk_en_set(qca8084_port_id,
|
||||||
|
QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY,
|
||||||
|
port_clock_en);
|
||||||
|
|
||||||
|
pr_debug("UNIPHY GMII/XGMII interface and ETHPHY GMII interface reset and release\n");
|
||||||
|
qca8084_port_clk_reset(qca8084_port_id,
|
||||||
|
QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY);
|
||||||
|
|
||||||
|
pr_debug("ipg_tune and xgmii2gmii reset for uniphy and ETHPHY, function reset\n");
|
||||||
|
qca8084_uniphy_uqxgmii_function_reset(qca8084_port_id);
|
||||||
|
|
||||||
|
/*do ethphy function reset: PHY_FIFO_RESET*/
|
||||||
|
pr_debug("do ethphy function reset\n");
|
||||||
|
qca8084_phy_function_reset(phy_addr);
|
||||||
|
|
||||||
|
/*change IPG from 10 to 11 for 1G speed*/
|
||||||
|
qca8084_phy_ipg_config(phy_addr, new_speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_interface_mode_set(void)
|
||||||
|
{
|
||||||
|
pr_debug("Configure QCA8084 as PORT_UQXGMII..\n");
|
||||||
|
/*the work mode is PORT_UQXGMII in default*/
|
||||||
|
qca8084_interface_uqxgmii_mode_set();
|
||||||
|
|
||||||
|
/*init clock for PORT_UQXGMII*/
|
||||||
|
qca8084_gcc_clock_init();
|
||||||
|
|
||||||
|
/*init pinctrl for phy mode to be added later*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_cdt_thresh_init(u32 phy_id)
|
||||||
|
{
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL3,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL3_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL4,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL4_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL5,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL5_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL6,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL6_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL7,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL7_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL9,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL9_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL13,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL13_VAL);
|
||||||
|
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
|
||||||
|
QCA8084_PHY_MMD3_CDT_THRESH_CTRL14,
|
||||||
|
QCA8084_PHY_MMD3_NEAR_ECHO_THRESH_VAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_modify_debug(u32 phy_addr, u32 debug_reg,
|
||||||
|
u32 mask, u32 value)
|
||||||
|
{
|
||||||
|
u16 phy_data = 0, new_phy_data = 0;
|
||||||
|
|
||||||
|
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_DEBUG_PORT_DATA);
|
||||||
|
if (phy_data == PHY_INVALID_DATA)
|
||||||
|
pr_debug("qca8084_phy_reg_read failed\n");
|
||||||
|
|
||||||
|
new_phy_data = (phy_data & ~mask) | value;
|
||||||
|
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
|
||||||
|
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_DATA, new_phy_data);
|
||||||
|
|
||||||
|
/* check debug register value */
|
||||||
|
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_DEBUG_PORT_DATA);
|
||||||
|
pr_debug("phy_addr:0x%x, debug_reg:0x%x, phy_data:0x%x\n",
|
||||||
|
phy_addr, debug_reg, phy_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_reset(u32 phy_addr)
|
||||||
|
{
|
||||||
|
u16 phy_data;
|
||||||
|
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_PHY_CONTROL);
|
||||||
|
qca8084_phy_reg_write(phy_addr, QCA8084_PHY_CONTROL,
|
||||||
|
phy_data | QCA8084_CTRL_SOFTWARE_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_phy_adc_edge_set(u32 phy_addr, u32 adc_edge)
|
||||||
|
{
|
||||||
|
qca8084_phy_modify_debug(phy_addr,
|
||||||
|
QCA8084_PHY_DEBUG_ANA_INTERFACE_CLK_SEL, 0xf0, adc_edge);
|
||||||
|
qca8084_phy_reset(phy_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipq_qca8084_phy_hw_init(struct phy_ops **ops, u32 phy_addr)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
u16 phy_data;
|
||||||
|
#endif
|
||||||
|
struct phy_ops *qca8084_ops;
|
||||||
|
|
||||||
|
qca8084_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
|
||||||
|
if (!qca8084_ops) {
|
||||||
|
pr_debug("Error allocating memory for phy ops\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that qca8084 PHY is based on qca8081 PHY and so the following
|
||||||
|
* ops functions required would be re-used from qca8081 */
|
||||||
|
|
||||||
|
qca8084_ops->phy_get_link_status = qca8081_phy_get_link_status;
|
||||||
|
qca8084_ops->phy_get_speed = qca8081_phy_get_speed;
|
||||||
|
qca8084_ops->phy_get_duplex = qca8081_phy_get_duplex;
|
||||||
|
*ops = qca8084_ops;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, QCA8081_PHY_ID1);
|
||||||
|
printf("PHY ID1: 0x%x\n", phy_data);
|
||||||
|
phy_data = qca8084_phy_reg_read(phy_addr, QCA8081_PHY_ID2);
|
||||||
|
printf("PHY ID2: 0x%x\n", phy_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* adjust CDT threshold */
|
||||||
|
qca8084_cdt_thresh_init(phy_addr);
|
||||||
|
|
||||||
|
/* invert ADC clock edge as falling edge to fix link issue */
|
||||||
|
qca8084_phy_adc_edge_set(phy_addr, ADC_FALLING);
|
||||||
|
}
|
||||||
80
drivers/net/ipq_common/ipq_qca8084.h
Normal file
80
drivers/net/ipq_common/ipq_qca8084.h
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, The Linux Foundation. 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 _QCA8084_PHY_H_
|
||||||
|
#define _QCA8084_PHY_H_
|
||||||
|
|
||||||
|
/*MII register*/
|
||||||
|
#define QCA8084_PHY_FIFO_CONTROL 0x19
|
||||||
|
|
||||||
|
/*MII register field*/
|
||||||
|
#define QCA8084_PHY_FIFO_RESET 0x3
|
||||||
|
|
||||||
|
/*MMD1 register*/
|
||||||
|
#define QCA8084_PHY_MMD1_NUM 0x1
|
||||||
|
|
||||||
|
/*MMD3 register*/
|
||||||
|
#define QCA8084_PHY_MMD3_NUM 0x3
|
||||||
|
#define QCA8084_PHY_MMD3_ADDR_8023AZ_EEE_2500M_CAPABILITY 0x15
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL3 0x8074
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL4 0x8075
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL5 0x8076
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL6 0x8077
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL7 0x8078
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL9 0x807a
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL13 0x807e
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL14 0x807f
|
||||||
|
|
||||||
|
/*MMD3 register field*/
|
||||||
|
#define QCA8084_PHY_EEE_CAPABILITY_2500M 0x1
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL3_VAL 0xc040
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL4_VAL 0xa060
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL5_VAL 0xc040
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL6_VAL 0xa060
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL7_VAL 0xc050
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL9_VAL 0xc060
|
||||||
|
#define QCA8084_PHY_MMD3_CDT_THRESH_CTRL13_VAL 0xb060
|
||||||
|
#define QCA8084_PHY_MMD3_NEAR_ECHO_THRESH_VAL 0x1eb0
|
||||||
|
|
||||||
|
/*MMD7 register*/
|
||||||
|
#define QCA8084_PHY_MMD7_NUM 0x7
|
||||||
|
#define QCA8084_PHY_MMD7_ADDR_8023AZ_EEE_2500M_CTRL 0x3e
|
||||||
|
#define QCA8084_PHY_MMD7_ADDR_8023AZ_EEE_2500M_PARTNER 0x3f
|
||||||
|
#define QCA8084_PHY_MMD7_IPG_10_11_ENABLE 0x901d
|
||||||
|
|
||||||
|
/*MMD7 register field*/
|
||||||
|
#define QCA8084_PHY_8023AZ_EEE_2500BT 0x1
|
||||||
|
#define QCA8084_PHY_MMD7_IPG_10_EN 0
|
||||||
|
#define QCA8084_PHY_MMD7_IPG_11_EN 0x1
|
||||||
|
|
||||||
|
/*DEBUG port analog register*/
|
||||||
|
#define QCA8084_PHY_DEBUG_ANA_INTERFACE_CLK_SEL 0x8b80
|
||||||
|
#define QCA8084_DEBUG_PORT_ADDRESS 29
|
||||||
|
#define QCA8084_DEBUG_PORT_DATA 30
|
||||||
|
|
||||||
|
#define QCA8084_PHY_CONTROL 0
|
||||||
|
#define QCA8084_CTRL_SOFTWARE_RESET 0x8000
|
||||||
|
|
||||||
|
#define PHY_INVALID_DATA 0xffff
|
||||||
|
|
||||||
|
#define QCA8084_MII_ADDR_C45 (1<<30)
|
||||||
|
#define QCA8084_REG_C45_ADDRESS(dev_type, reg_num) (QCA8084_MII_ADDR_C45 | \
|
||||||
|
((dev_type & 0x1f) << 16) | (reg_num & 0xffff))
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ADC_RISING = 0,
|
||||||
|
ADC_FALLING = 0xf0,
|
||||||
|
}
|
||||||
|
qca8084_adc_edge_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
1210
drivers/net/ipq_common/ipq_qca8084_clk.c
Normal file
1210
drivers/net/ipq_common/ipq_qca8084_clk.c
Normal file
File diff suppressed because it is too large
Load diff
183
drivers/net/ipq_common/ipq_qca8084_clk.h
Normal file
183
drivers/net/ipq_common/ipq_qca8084_clk.h
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, The Linux Foundation. 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 _QCA8084_CLK_H_
|
||||||
|
#define _QCA8084_CLK_H_
|
||||||
|
|
||||||
|
#define QCA8084_SWITCH_CORE_CLK "qca8084_gcc_switch_core_clk"
|
||||||
|
#define QCA8084_APB_BRIDGE_CLK "qca8084_gcc_apb_bridge_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC0_TX_CLK "qca8084_gcc_mac0_tx_clk"
|
||||||
|
#define QCA8084_MAC0_TX_UNIPHY1_CLK "qca8084_gcc_mac0_tx_srds1_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC0_RX_CLK "qca8084_gcc_mac0_rx_clk"
|
||||||
|
#define QCA8084_MAC0_RX_UNIPHY1_CLK "qca8084_gcc_mac0_rx_srds1_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC1_TX_CLK "qca8084_gcc_mac1_tx_clk"
|
||||||
|
#define QCA8084_MAC1_GEPHY0_TX_CLK "qca8084_gcc_mac1_gephy0_tx_clk"
|
||||||
|
#define QCA8084_MAC1_UNIPHY1_CH0_RX_CLK "qca8084_gcc_mac1_srds1_ch0_rx_clk"
|
||||||
|
#define QCA8084_MAC1_UNIPHY1_CH0_XGMII_RX_CLK "qca8084_gcc_mac1_srds1_ch0_xgmii_rx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC1_RX_CLK "qca8084_gcc_mac1_rx_clk"
|
||||||
|
#define QCA8084_MAC1_GEPHY0_RX_CLK "qca8084_gcc_mac1_gephy0_rx_clk"
|
||||||
|
#define QCA8084_MAC1_UNIPHY1_CH0_TX_CLK "qca8084_gcc_mac1_srds1_ch0_tx_clk"
|
||||||
|
#define QCA8084_MAC1_UNIPHY1_CH0_XGMII_TX_CLK "qca8084_gcc_mac1_srds1_ch0_xgmii_tx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC2_TX_CLK "qca8084_gcc_mac2_tx_clk"
|
||||||
|
#define QCA8084_MAC2_GEPHY1_TX_CLK "qca8084_gcc_mac2_gephy1_tx_clk"
|
||||||
|
#define QCA8084_MAC2_UNIPHY1_CH1_RX_CLK "qca8084_gcc_mac2_srds1_ch1_rx_clk"
|
||||||
|
#define QCA8084_MAC2_UNIPHY1_CH1_XGMII_RX_CLK "qca8084_gcc_mac2_srds1_ch1_xgmii_rx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC2_RX_CLK "qca8084_gcc_mac2_rx_clk"
|
||||||
|
#define QCA8084_MAC2_GEPHY1_RX_CLK "qca8084_gcc_mac2_gephy1_rx_clk"
|
||||||
|
#define QCA8084_MAC2_UNIPHY1_CH1_TX_CLK "qca8084_gcc_mac2_srds1_ch1_tx_clk"
|
||||||
|
#define QCA8084_MAC2_UNIPHY1_CH1_XGMII_TX_CLK "qca8084_gcc_mac2_srds1_ch1_xgmii_tx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC3_TX_CLK "qca8084_gcc_mac3_tx_clk"
|
||||||
|
#define QCA8084_MAC3_GEPHY2_TX_CLK "qca8084_gcc_mac3_gephy2_tx_clk"
|
||||||
|
#define QCA8084_MAC3_UNIPHY1_CH2_RX_CLK "qca8084_gcc_mac3_srds1_ch2_rx_clk"
|
||||||
|
#define QCA8084_MAC3_UNIPHY1_CH2_XGMII_RX_CLK "qca8084_gcc_mac3_srds1_ch2_xgmii_rx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC3_RX_CLK "qca8084_gcc_mac3_rx_clk"
|
||||||
|
#define QCA8084_MAC3_GEPHY2_RX_CLK "qca8084_gcc_mac3_gephy2_rx_clk"
|
||||||
|
#define QCA8084_MAC3_UNIPHY1_CH2_TX_CLK "qca8084_gcc_mac3_srds1_ch2_tx_clk"
|
||||||
|
#define QCA8084_MAC3_UNIPHY1_CH2_XGMII_TX_CLK "qca8084_gcc_mac3_srds1_ch2_xgmii_tx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC4_TX_CLK "qca8084_gcc_mac4_tx_clk"
|
||||||
|
#define QCA8084_MAC4_GEPHY3_TX_CLK "qca8084_gcc_mac4_gephy3_tx_clk"
|
||||||
|
#define QCA8084_MAC4_UNIPHY1_CH3_RX_CLK "qca8084_gcc_mac4_srds1_ch3_rx_clk"
|
||||||
|
#define QCA8084_MAC4_UNIPHY1_CH3_XGMII_RX_CLK "qca8084_gcc_mac4_srds1_ch3_xgmii_rx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC4_RX_CLK "qca8084_gcc_mac4_rx_clk"
|
||||||
|
#define QCA8084_MAC4_GEPHY3_RX_CLK "qca8084_gcc_mac4_gephy3_rx_clk"
|
||||||
|
#define QCA8084_MAC4_UNIPHY1_CH3_TX_CLK "qca8084_gcc_mac4_srds1_ch3_tx_clk"
|
||||||
|
#define QCA8084_MAC4_UNIPHY1_CH3_XGMII_TX_CLK "qca8084_gcc_mac4_srds1_ch3_xgmii_tx_clk"
|
||||||
|
|
||||||
|
#define QCA8084_MAC5_TX_CLK "qca8084_gcc_mac5_tx_clk"
|
||||||
|
#define QCA8084_MAC5_TX_UNIPHY0_CLK "qca8084_gcc_mac5_tx_srds0_clk"
|
||||||
|
#define QCA8084_MAC5_TX_SRDS0_CLK_SRC "qca8084_gcc_mac5_tx_srds0_clk_src"
|
||||||
|
|
||||||
|
#define QCA8084_MAC5_RX_CLK "qca8084_gcc_mac5_rx_clk"
|
||||||
|
#define QCA8084_MAC5_RX_UNIPHY0_CLK "qca8084_gcc_mac5_rx_srds0_clk"
|
||||||
|
#define QCA8084_MAC5_RX_SRDS0_CLK_SRC "qca8084_gcc_mac5_rx_srds0_clk_src"
|
||||||
|
|
||||||
|
#define QCA8084_SEC_CTRL_CLK "qca8084_gcc_sec_ctrl_clk"
|
||||||
|
#define QCA8084_SEC_CTRL_SENSE_CLK "qca8084_gcc_sec_ctrl_sense_clk"
|
||||||
|
|
||||||
|
#define QCA8084_SRDS0_SYS_CLK "qca8084_gcc_srds0_sys_clk"
|
||||||
|
#define QCA8084_SRDS1_SYS_CLK "qca8084_gcc_srds1_sys_clk"
|
||||||
|
#define QCA8084_GEPHY0_SYS_CLK "qca8084_gcc_gephy0_sys_clk"
|
||||||
|
#define QCA8084_GEPHY1_SYS_CLK "qca8084_gcc_gephy1_sys_clk"
|
||||||
|
#define QCA8084_GEPHY2_SYS_CLK "qca8084_gcc_gephy2_sys_clk"
|
||||||
|
#define QCA8084_GEPHY3_SYS_CLK "qca8084_gcc_gephy3_sys_clk"
|
||||||
|
|
||||||
|
#define QCA8084_AHB_CLK "qca8084_gcc_ahb_clk"
|
||||||
|
#define QCA8084_SEC_CTRL_AHB_CLK "qca8084_gcc_sec_ctrl_ahb_clk"
|
||||||
|
#define QCA8084_TLMM_CLK "qca8084_gcc_tlmm_clk"
|
||||||
|
#define QCA8084_TLMM_AHB_CLK "qca8084_gcc_tlmm_ahb_clk"
|
||||||
|
#define QCA8084_CNOC_AHB_CLK "qca8084_gcc_cnoc_ahb_clk"
|
||||||
|
#define QCA8084_MDIO_AHB_CLK "qca8084_gcc_mdio_ahb_clk"
|
||||||
|
#define QCA8084_MDIO_MASTER_AHB_CLK "qca8084_gcc_mdio_master_ahb_clk"
|
||||||
|
|
||||||
|
#define QCA8084_GLOBAL_RST "qca8084_gcc_global_rst"
|
||||||
|
#define QCA8084_UNIPHY_XPCS_RST "qca8084_uniphy_xpcs_rst"
|
||||||
|
#define QCA8084_GEPHY_DSP_HW_RST "qca8084_gephy_dsp_hw_rst"
|
||||||
|
#define QCA8084_GEPHY_P3_MDC_SW_RST "qca8084_gephy_p3_mdc_sw_rst"
|
||||||
|
#define QCA8084_GEPHY_P2_MDC_SW_RST "qca8084_gephy_p2_mdc_sw_rst"
|
||||||
|
#define QCA8084_GEPHY_P1_MDC_SW_RST "qca8084_gephy_p1_mdc_sw_rst"
|
||||||
|
#define QCA8084_GEPHY_P0_MDC_SW_RST "qca8084_gephy_p0_mdc_sw_rst"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QCA8084_P_XO,
|
||||||
|
QCA8084_P_UNIPHY0_RX,
|
||||||
|
QCA8084_P_UNIPHY0_TX,
|
||||||
|
QCA8084_P_UNIPHY1_RX,
|
||||||
|
QCA8084_P_UNIPHY1_TX,
|
||||||
|
QCA8084_P_UNIPHY1_RX312P5M,
|
||||||
|
QCA8084_P_UNIPHY1_TX312P5M,
|
||||||
|
QCA8084_P_MAX,
|
||||||
|
} qca8084_clk_parent_t;
|
||||||
|
|
||||||
|
struct qca8084_clk_data {
|
||||||
|
unsigned long rate;
|
||||||
|
unsigned int rcg_val;
|
||||||
|
unsigned int cdiv_val;
|
||||||
|
unsigned int cbc_val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qca8084_parent_data {
|
||||||
|
unsigned long prate; /* RCG input clock rate */
|
||||||
|
qca8084_clk_parent_t parent; /* RCG parent clock id */
|
||||||
|
int cfg; /* RCG clock src value */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk_lookup {
|
||||||
|
unsigned int rcg;
|
||||||
|
unsigned int cdiv;
|
||||||
|
unsigned int cbc;
|
||||||
|
unsigned int rst_bit;
|
||||||
|
const char *clk_name;
|
||||||
|
const unsigned long *support_rate;
|
||||||
|
unsigned int num_rate;
|
||||||
|
const struct qca8084_parent_data *pdata;
|
||||||
|
unsigned int num_parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CLK_LOOKUP(_rcg, _cdiv, _cbc, _rst_bit, _clk_name, \
|
||||||
|
_rate, _num_rate, _pdata, _num_parent) \
|
||||||
|
{ \
|
||||||
|
.rcg = _rcg, \
|
||||||
|
.cdiv = _cdiv, \
|
||||||
|
.cbc = _cbc, \
|
||||||
|
.rst_bit = _rst_bit, \
|
||||||
|
.clk_name = _clk_name, \
|
||||||
|
.support_rate = _rate, \
|
||||||
|
.num_rate = _num_rate, \
|
||||||
|
.pdata = _pdata, \
|
||||||
|
.num_parent = _num_parent, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define QCA8084_CLK_TYPE_EPHY BIT(0)
|
||||||
|
#define QCA8084_CLK_TYPE_UNIPHY BIT(1)
|
||||||
|
#define QCA8084_CLK_TYPE_MAC BIT(2)
|
||||||
|
|
||||||
|
#define UQXGMII_SPEED_2500M_CLK 312500000
|
||||||
|
#define UQXGMII_SPEED_1000M_CLK 125000000
|
||||||
|
#define UQXGMII_SPEED_100M_CLK 25000000
|
||||||
|
#define UQXGMII_SPEED_10M_CLK 2500000
|
||||||
|
#define UQXGMII_XPCS_SPEED_2500M_CLK 78125000
|
||||||
|
#define QCA8084_AHB_CLK_RATE_104P17M 104160000
|
||||||
|
#define QCA8084_SYS_CLK_RATE_25M 25000000
|
||||||
|
#define QCA8084_XO_CLK_RATE_50M 50000000
|
||||||
|
|
||||||
|
#define QCA8084_CLK_BASE_REG 0x0c800000
|
||||||
|
#define QCA8084_CLK_MUX_SEL 0x300
|
||||||
|
#define QCA8084_UNIPHY0_MUX_SEL_MASK BITS_MASK(0, 2)
|
||||||
|
#define QCA8084_UNIPHY0_SEL_MAC5 0x3
|
||||||
|
#define QCA8084_UNIPHY0_SEL_MAC4 0
|
||||||
|
|
||||||
|
#define RCGR_CMD_ROOT_OFF BIT(31)
|
||||||
|
#define RCGR_CMD_UPDATE BIT(0)
|
||||||
|
#define RCGR_SRC_SEL BITS_MASK(8, 3)
|
||||||
|
#define RCGR_SRC_SEL_SHIFT 8
|
||||||
|
#define RCGR_HDIV BITS_MASK(0, 5)
|
||||||
|
#define RCGR_HDIV_SHIFT 0
|
||||||
|
#define RCGR_DIV_BYPASS 0
|
||||||
|
#define RCGR_DIV_MAX 0x1f
|
||||||
|
#define CDIVR_DIVIDER_10 9 /* CDIVR divided by N + 1 */
|
||||||
|
#define CDIVR_DIVIDER BITS_MASK(0, 4)
|
||||||
|
#define CDIVR_DIVIDER_SHIFT 0
|
||||||
|
#define CBCR_CLK_OFF BIT(31)
|
||||||
|
#define CBCR_CLK_RESET BIT(2)
|
||||||
|
#define CBCR_CLK_ENABLE BIT(0)
|
||||||
|
|
||||||
|
#endif /* _QCA8084_CLK_H_ */
|
||||||
504
drivers/net/ipq_common/ipq_qca8084_interface_ctrl.c
Normal file
504
drivers/net/ipq_common/ipq_qca8084_interface_ctrl.c
Normal file
|
|
@ -0,0 +1,504 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, The Linux Foundation. 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 "ipq_phy.h"
|
||||||
|
#include "ipq_qca8084.h"
|
||||||
|
#include "ipq_qca8084_clk.h"
|
||||||
|
#include "ipq_qca8084_interface_ctrl.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define pr_debug(fmt, args...) printf(fmt, ##args);
|
||||||
|
#else
|
||||||
|
#define pr_debug(fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void qca8084_phy_reset(u32 phy_id);
|
||||||
|
extern u16 qca8084_phy_reg_read(u32 phy_id, u32 reg_id);
|
||||||
|
extern u16 qca8084_phy_reg_write(u32 phy_id, u32 reg_id, u16 value);
|
||||||
|
extern u16 qca8084_phy_mmd_read(u32 phy_id, u16 mmd_num, u16 reg_id);
|
||||||
|
extern u16 qca8084_phy_mmd_write(u32 phy_id, u16 mmd_num, u16 reg_id,
|
||||||
|
u16 value);
|
||||||
|
extern void qca8084_phy_modify_mmd(uint32_t phy_addr, uint32_t mmd_num,
|
||||||
|
uint32_t mmd_reg, uint32_t mask, uint32_t value);
|
||||||
|
extern void qca8084_phy_modify_mii(uint32_t phy_addr, uint32_t mii_reg,
|
||||||
|
uint32_t mask, uint32_t value);
|
||||||
|
extern uint32_t ipq_mii_read(uint32_t reg);
|
||||||
|
extern void ipq_mii_write(uint32_t reg, uint32_t val);
|
||||||
|
extern void ipq_mii_update(uint32_t reg, uint32_t mask, uint32_t val);
|
||||||
|
extern void qca8084_port_clk_rate_set(uint32_t qca8084_port_id, uint32_t rate);
|
||||||
|
extern void qca8084_port_clk_en_set(uint32_t qca8084_port_id, uint8_t mask,
|
||||||
|
uint8_t enable);
|
||||||
|
extern void qca8084_clk_assert(const char *clock_id);
|
||||||
|
extern void qca8084_clk_deassert(const char *clock_id);
|
||||||
|
extern void qca8084_port_clk_reset(uint32_t qca8084_port_id, uint8_t mask);
|
||||||
|
|
||||||
|
void qca8084_serdes_addr_get(uint32_t serdes_id, uint32_t *address)
|
||||||
|
{
|
||||||
|
uint32_t data = 0;
|
||||||
|
|
||||||
|
data = ipq_mii_read(SERDES_CFG_OFFSET);
|
||||||
|
switch(serdes_id)
|
||||||
|
{
|
||||||
|
case QCA8084_UNIPHY_SGMII_0:
|
||||||
|
*address = (data >> SERDES_CFG_S0_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
case QCA8084_UNIPHY_SGMII_1:
|
||||||
|
*address = (data >> SERDES_CFG_S1_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
case QCA8084_UNIPHY_XPCS:
|
||||||
|
*address = (data >> SERDES_CFG_S1_XPCS_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_debug("Serdes id not matching\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_ephy_addr_get(uint32_t qca8084_port_id, uint32_t *phy_addr)
|
||||||
|
{
|
||||||
|
uint32_t data = 0;
|
||||||
|
|
||||||
|
data = ipq_mii_read(EPHY_CFG_OFFSET);
|
||||||
|
switch(qca8084_port_id)
|
||||||
|
{
|
||||||
|
case PORT1:
|
||||||
|
*phy_addr = (data >> EPHY_CFG_EPHY0_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
case PORT2:
|
||||||
|
*phy_addr = (data >> EPHY_CFG_EPHY1_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
case PORT3:
|
||||||
|
*phy_addr = (data >> EPHY_CFG_EPHY2_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
case PORT4:
|
||||||
|
*phy_addr = (data >> EPHY_CFG_EPHY3_ADDR_BOFFSET) & 0x1f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_debug("qca8084_port_id not matching\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t qca8084_uniphy_xpcs_mmd_read(uint16_t mmd_num, uint16_t mmd_reg)
|
||||||
|
{
|
||||||
|
uint32_t uniphy_xpcs_addr = 0;
|
||||||
|
|
||||||
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_XPCS, &uniphy_xpcs_addr);
|
||||||
|
|
||||||
|
return qca8084_phy_mmd_read(uniphy_xpcs_addr, mmd_num, mmd_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_xpcs_mmd_write(uint16_t mmd_num, uint16_t mmd_reg,
|
||||||
|
uint16_t reg_val)
|
||||||
|
{
|
||||||
|
uint32_t uniphy_xpcs_addr = 0;
|
||||||
|
#ifdef DEBUG
|
||||||
|
uint16_t phy_data = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_XPCS, &uniphy_xpcs_addr);
|
||||||
|
|
||||||
|
qca8084_phy_mmd_write(uniphy_xpcs_addr, mmd_num, mmd_reg, reg_val);
|
||||||
|
/*check the mmd register value*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
phy_data =
|
||||||
|
#endif
|
||||||
|
qca8084_uniphy_xpcs_mmd_read(mmd_num, mmd_reg);
|
||||||
|
|
||||||
|
pr_debug("phy_addr:0x%x, mmd_num:0x%x, mmd_reg:0x%x, phy_data:0x%x\n",
|
||||||
|
uniphy_xpcs_addr, mmd_num, mmd_reg, phy_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_xpcs_modify_mmd(uint32_t mmd_num, uint32_t mmd_reg,
|
||||||
|
uint32_t mask, uint32_t value)
|
||||||
|
{
|
||||||
|
uint16_t phy_data = 0, new_phy_data = 0;
|
||||||
|
|
||||||
|
phy_data = qca8084_uniphy_xpcs_mmd_read(mmd_num, mmd_reg);
|
||||||
|
new_phy_data = (phy_data & ~mask) | value;
|
||||||
|
qca8084_uniphy_xpcs_mmd_write(mmd_num, mmd_reg, new_phy_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t qca8084_uniphy_mode_check(uint32_t uniphy_index,
|
||||||
|
qca8084_uniphy_mode_t uniphy_mode)
|
||||||
|
{
|
||||||
|
uint32_t uniphy_addr = 0;
|
||||||
|
uint16_t uniphy_mode_ctrl_data = 0;
|
||||||
|
|
||||||
|
qca8084_serdes_addr_get(uniphy_index, &uniphy_addr);
|
||||||
|
|
||||||
|
uniphy_mode_ctrl_data = qca8084_phy_mmd_read(uniphy_addr,
|
||||||
|
QCA8084_UNIPHY_MMD1, QCA8084_UNIPHY_MMD1_MODE_CTRL);
|
||||||
|
if(uniphy_mode_ctrl_data == PHY_INVALID_DATA)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!(uniphy_mode & uniphy_mode_ctrl_data))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t qca8084_uniphy_xpcs_port_to_mmd(uint32_t qca8084_port_id)
|
||||||
|
{
|
||||||
|
uint32_t mmd_id = 0;
|
||||||
|
|
||||||
|
switch(qca8084_port_id)
|
||||||
|
{
|
||||||
|
case PORT1:
|
||||||
|
mmd_id = QCA8084_UNIPHY_MMD31;
|
||||||
|
break;
|
||||||
|
case PORT2:
|
||||||
|
mmd_id = QCA8084_UNIPHY_MMD26;
|
||||||
|
break;
|
||||||
|
case PORT3:
|
||||||
|
mmd_id = QCA8084_UNIPHY_MMD27;
|
||||||
|
break;
|
||||||
|
case PORT4:
|
||||||
|
mmd_id = QCA8084_UNIPHY_MMD28;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_debug("Port not matching qca8084 ports\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return mmd_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_xpcs_modify_port_mmd(uint32_t qca8084_port_id,
|
||||||
|
uint32_t mmd_reg, uint32_t mask,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t mmd_id = 0;
|
||||||
|
|
||||||
|
mmd_id = qca8084_uniphy_xpcs_port_to_mmd(qca8084_port_id);
|
||||||
|
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(mmd_id, mmd_reg, mask, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_port_speed_clock_set(uint32_t qca8084_port_id,
|
||||||
|
fal_port_speed_t speed)
|
||||||
|
{
|
||||||
|
uint32_t clk_rate = 0;
|
||||||
|
|
||||||
|
switch(speed)
|
||||||
|
{
|
||||||
|
case FAL_SPEED_2500:
|
||||||
|
clk_rate = UQXGMII_SPEED_2500M_CLK;
|
||||||
|
break;
|
||||||
|
case FAL_SPEED_1000:
|
||||||
|
clk_rate = UQXGMII_SPEED_1000M_CLK;
|
||||||
|
break;
|
||||||
|
case FAL_SPEED_100:
|
||||||
|
clk_rate = UQXGMII_SPEED_100M_CLK;
|
||||||
|
break;
|
||||||
|
case FAL_SPEED_10:
|
||||||
|
clk_rate = UQXGMII_SPEED_10M_CLK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_debug("Unknown speed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qca8084_port_clk_rate_set(qca8084_port_id, clk_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_xpcs_8023az_enable(void)
|
||||||
|
{
|
||||||
|
uint16_t uniphy_data = 0;
|
||||||
|
|
||||||
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_AN_LP_BASE_ABL2);
|
||||||
|
if(!(uniphy_data & QCA8084_UNIPHY_MMD3_XPCS_EEE_CAP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*Configure the EEE related timer*/
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL,
|
||||||
|
0x0f40, QCA8084_UNIPHY_MMD3_EEE_RES_REGS |
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_SIGN_BIT_REGS);
|
||||||
|
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_TX_TIMER,
|
||||||
|
0x1fff, QCA8084_UNIPHY_MMD3_EEE_TSL_REGS|
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_TLU_REGS |
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_TWL_REGS);
|
||||||
|
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_RX_TIMER,
|
||||||
|
0x1fff, QCA8084_UNIPHY_MMD3_EEE_100US_REG_REGS|
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_RWR_REG_REGS);
|
||||||
|
|
||||||
|
/*enable TRN_LPI*/
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL1,
|
||||||
|
0x101, QCA8084_UNIPHY_MMD3_EEE_TRANS_LPI_MODE|
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_TRANS_RX_LPI_MODE);
|
||||||
|
|
||||||
|
/*enable TX/RX LPI pattern*/
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL,
|
||||||
|
0x3, QCA8084_UNIPHY_MMD3_EEE_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_calibration(uint32_t uniphy_addr)
|
||||||
|
{
|
||||||
|
uint16_t uniphy_data = 0;
|
||||||
|
uint32_t retries = 100, calibration_done = 0;
|
||||||
|
|
||||||
|
/* wait calibration done to uniphy*/
|
||||||
|
while (calibration_done != QCA8084_UNIPHY_MMD1_CALIBRATION_DONE) {
|
||||||
|
mdelay(1);
|
||||||
|
if (retries-- == 0)
|
||||||
|
pr_debug("uniphy callibration time out!\n");
|
||||||
|
uniphy_data = qca8084_phy_mmd_read(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_CALIBRATION4);
|
||||||
|
|
||||||
|
calibration_done = (uniphy_data & QCA8084_UNIPHY_MMD1_CALIBRATION_DONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_xpcs_10g_r_linkup(void)
|
||||||
|
{
|
||||||
|
uint16_t uniphy_data = 0;
|
||||||
|
uint32_t retries = 100, linkup = 0;
|
||||||
|
|
||||||
|
/* wait 10G_R link up */
|
||||||
|
while (linkup != QCA8084_UNIPHY_MMD3_10GBASE_R_UP) {
|
||||||
|
mdelay(1);
|
||||||
|
if (retries-- == 0)
|
||||||
|
pr_debug("10g_r link up timeout\n");
|
||||||
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_10GBASE_R_PCS_STATUS1);
|
||||||
|
|
||||||
|
linkup = (uniphy_data & QCA8084_UNIPHY_MMD3_10GBASE_R_UP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qca8084_uniphy_xpcs_soft_reset(void)
|
||||||
|
{
|
||||||
|
uint16_t uniphy_data = 0;
|
||||||
|
uint32_t retries = 100, reset_done = QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET;
|
||||||
|
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_DIG_CTRL1, 0x8000,
|
||||||
|
QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET);
|
||||||
|
|
||||||
|
while (reset_done) {
|
||||||
|
mdelay(1);
|
||||||
|
if (retries-- == 0)
|
||||||
|
pr_debug("xpcs soft reset timeout\n");
|
||||||
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_DIG_CTRL1);
|
||||||
|
|
||||||
|
reset_done = (uniphy_data & QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_uniphy_xpcs_speed_set(uint32_t qca8084_port_id,
|
||||||
|
fal_port_speed_t speed)
|
||||||
|
{
|
||||||
|
uint32_t xpcs_speed = 0;
|
||||||
|
|
||||||
|
switch(speed)
|
||||||
|
{
|
||||||
|
case FAL_SPEED_2500:
|
||||||
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_2500;
|
||||||
|
break;
|
||||||
|
case FAL_SPEED_1000:
|
||||||
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_1000;
|
||||||
|
break;
|
||||||
|
case FAL_SPEED_100:
|
||||||
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_100;
|
||||||
|
break;
|
||||||
|
case FAL_SPEED_10:
|
||||||
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_10;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_debug("Unknown speed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_CTRL,
|
||||||
|
QCA8084_UNIPHY_MMD_XPC_SPEED_MASK,
|
||||||
|
xpcs_speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_uniphy_uqxgmii_function_reset(uint32_t qca8084_port_id)
|
||||||
|
{
|
||||||
|
uint32_t uniphy_addr = 0;
|
||||||
|
|
||||||
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_SGMII_1, &uniphy_addr);
|
||||||
|
|
||||||
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_USXGMII_RESET, BIT(qca8084_port_id-1), 0);
|
||||||
|
mdelay(1);
|
||||||
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_USXGMII_RESET, BIT(qca8084_port_id-1),
|
||||||
|
BIT(qca8084_port_id-1));
|
||||||
|
if(qca8084_port_id == PORT1)
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_DIG_CTRL,
|
||||||
|
0x400, QCA8084_UNIPHY_MMD3_USXG_FIFO_RESET);
|
||||||
|
else
|
||||||
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_DIG_CTRL,
|
||||||
|
0x20, QCA8084_UNIPHY_MMD_USXG_FIFO_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_uniphy_xpcs_autoneg_restart(uint32_t qca8084_port_id)
|
||||||
|
{
|
||||||
|
uint32_t retries = 500, uniphy_data = 0, mmd_id = 0;
|
||||||
|
|
||||||
|
mmd_id = qca8084_uniphy_xpcs_port_to_mmd(qca8084_port_id);
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(mmd_id, QCA8084_UNIPHY_MMD_MII_CTRL,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_AN_RESTART, QCA8084_UNIPHY_MMD_MII_AN_RESTART);
|
||||||
|
mdelay(1);
|
||||||
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(mmd_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_ERR_SEL);
|
||||||
|
while(!(uniphy_data & QCA8084_UNIPHY_MMD_MII_AN_COMPLETE_INT))
|
||||||
|
{
|
||||||
|
mdelay(1);
|
||||||
|
if (retries-- == 0)
|
||||||
|
{
|
||||||
|
pr_debug("xpcs uniphy autoneg restart timeout\n");
|
||||||
|
}
|
||||||
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(mmd_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_ERR_SEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _qca8084_interface_uqxgmii_mode_set(uint32_t uniphy_addr)
|
||||||
|
{
|
||||||
|
uint32_t qca8084_port_id = 0, phy_addr = 0;
|
||||||
|
|
||||||
|
/*reset xpcs*/
|
||||||
|
pr_debug("reset xpcs\n");
|
||||||
|
qca8084_clk_assert(QCA8084_UNIPHY_XPCS_RST);
|
||||||
|
/*select xpcs mode*/
|
||||||
|
pr_debug("select xpcs mode\n");
|
||||||
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_MODE_CTRL, 0x1f00, QCA8084_UNIPHY_MMD1_XPCS_MODE);
|
||||||
|
/*config dapa pass as usxgmii*/
|
||||||
|
pr_debug("config dapa pass as usxgmii\n");
|
||||||
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_GMII_DATAPASS_SEL, QCA8084_UNIPHY_MMD1_DATAPASS_MASK,
|
||||||
|
QCA8084_UNIPHY_MMD1_DATAPASS_USXGMII);
|
||||||
|
/*reset and release uniphy GMII/XGMII and ethphy GMII*/
|
||||||
|
pr_debug("reset and release uniphy GMII/XGMII and ethphy GMII\n");
|
||||||
|
for(qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
||||||
|
qca8084_port_id++)
|
||||||
|
{
|
||||||
|
qca8084_port_clk_reset(qca8084_port_id,
|
||||||
|
QCA8084_CLK_TYPE_UNIPHY|QCA8084_CLK_TYPE_EPHY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ana sw reset and release*/
|
||||||
|
pr_debug("ana sw reset and release\n");
|
||||||
|
qca8084_phy_modify_mii(uniphy_addr,
|
||||||
|
QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET, 0x40, QCA8084_UNIPHY_ANA_SOFT_RESET);
|
||||||
|
mdelay(10);
|
||||||
|
qca8084_phy_modify_mii(uniphy_addr,
|
||||||
|
QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET, 0x40, QCA8084_UNIPHY_ANA_SOFT_RELEASE);
|
||||||
|
|
||||||
|
/*Wait calibration done*/
|
||||||
|
pr_debug("Wait calibration done\n");
|
||||||
|
qca8084_uniphy_calibration(uniphy_addr);
|
||||||
|
/*Enable SSCG(Spread Spectrum Clock Generator)*/
|
||||||
|
pr_debug("enable uniphy sscg\n");
|
||||||
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_CDA_CONTROL1, 0x8, QCA8084_UNIPHY_MMD1_SSCG_ENABLE);
|
||||||
|
/*release XPCS*/
|
||||||
|
pr_debug("release XPCS\n");
|
||||||
|
qca8084_clk_deassert(QCA8084_UNIPHY_XPCS_RST);
|
||||||
|
/*ethphy software reset*/
|
||||||
|
pr_debug("ethphy software reset\n");
|
||||||
|
for(qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
||||||
|
qca8084_port_id++)
|
||||||
|
{
|
||||||
|
qca8084_ephy_addr_get(qca8084_port_id, &phy_addr);
|
||||||
|
qca8084_phy_reset(phy_addr);
|
||||||
|
}
|
||||||
|
/*Set BaseR mode*/
|
||||||
|
pr_debug("Set BaseR mode\n");
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_PCS_CTRL2, 0xf, QCA8084_UNIPHY_MMD3_PCS_TYPE_10GBASE_R);
|
||||||
|
/*wait 10G base_r link up*/
|
||||||
|
pr_debug("wait 10G base_r link up\n");
|
||||||
|
qca8084_uniphy_xpcs_10g_r_linkup();
|
||||||
|
/*enable UQXGMII mode*/
|
||||||
|
pr_debug("enable UQSXGMII mode\n");
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_DIG_CTRL1, 0x200, QCA8084_UNIPHY_MMD3_USXGMII_EN);
|
||||||
|
/*set UQXGMII mode*/
|
||||||
|
pr_debug("set QXGMII mode\n");
|
||||||
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_VR_RPCS_TPC, 0x1c00, QCA8084_UNIPHY_MMD3_QXGMII_EN);
|
||||||
|
/*set AM interval*/
|
||||||
|
pr_debug("set AM interval\n");
|
||||||
|
qca8084_uniphy_xpcs_mmd_write(QCA8084_UNIPHY_MMD3,
|
||||||
|
QCA8084_UNIPHY_MMD3_MII_AM_INTERVAL, QCA8084_UNIPHY_MMD3_MII_AM_INTERVAL_VAL);
|
||||||
|
/*xpcs software reset*/
|
||||||
|
pr_debug("xpcs software reset\n");
|
||||||
|
qca8084_uniphy_xpcs_soft_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void qca8084_interface_uqxgmii_mode_set(void)
|
||||||
|
{
|
||||||
|
uint32_t uniphy_addr = 0, qca8084_port_id = 0;
|
||||||
|
|
||||||
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_SGMII_1, &uniphy_addr);
|
||||||
|
|
||||||
|
/*disable IPG_tuning bypass*/
|
||||||
|
pr_debug("disable IPG_tuning bypass\n");
|
||||||
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
||||||
|
QCA8084_UNIPHY_MMD1_BYPASS_TUNING_IPG,
|
||||||
|
QCA8084_UNIPHY_MMD1_BYPASS_TUNING_IPG_EN, 0);
|
||||||
|
/*disable uniphy GMII/XGMII clock and disable ethphy GMII clock*/
|
||||||
|
pr_debug("disable uniphy GMII/XGMII clock and ethphy GMII clock\n");
|
||||||
|
for(qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
||||||
|
qca8084_port_id++)
|
||||||
|
{
|
||||||
|
qca8084_port_clk_en_set(qca8084_port_id,
|
||||||
|
QCA8084_CLK_TYPE_UNIPHY|QCA8084_CLK_TYPE_EPHY, 0);
|
||||||
|
}
|
||||||
|
/*configure uqxgmii mode*/
|
||||||
|
pr_debug("configure uqxgmii mode\n");
|
||||||
|
_qca8084_interface_uqxgmii_mode_set(uniphy_addr);
|
||||||
|
/*enable auto-neg complete interrupt,Mii using mii-4bits,
|
||||||
|
configure as PHY mode, enable autoneg ability*/
|
||||||
|
pr_debug("enable auto-neg complete interrupt, Mii using mii-4bits,"
|
||||||
|
" configure as PHY mode, enable autoneg ability, disable TICD\n");
|
||||||
|
for (qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
||||||
|
qca8084_port_id++)
|
||||||
|
{
|
||||||
|
/*enable auto-neg complete interrupt,Mii using mii-4bits,configure as PHY mode*/
|
||||||
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_AN_INT_MSK, 0x109,
|
||||||
|
QCA8084_UNIPHY_MMD_AN_COMPLETE_INT |
|
||||||
|
QCA8084_UNIPHY_MMD_MII_4BITS_CTRL |
|
||||||
|
QCA8084_UNIPHY_MMD_TX_CONFIG_CTRL);
|
||||||
|
|
||||||
|
/*enable autoneg ability*/
|
||||||
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_CTRL, 0x3060, QCA8084_UNIPHY_MMD_MII_AN_ENABLE |
|
||||||
|
QCA8084_UNIPHY_MMD_XPC_SPEED_1000);
|
||||||
|
|
||||||
|
/*disable TICD*/
|
||||||
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
||||||
|
QCA8084_UNIPHY_MMD_MII_XAUI_MODE_CTRL, 0x1,
|
||||||
|
QCA8084_UNIPHY_MMD_TX_IPG_CHECK_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*enable EEE for xpcs*/
|
||||||
|
pr_debug("enable EEE for xpcs\n");
|
||||||
|
qca8084_uniphy_xpcs_8023az_enable();
|
||||||
|
}
|
||||||
140
drivers/net/ipq_common/ipq_qca8084_interface_ctrl.h
Normal file
140
drivers/net/ipq_common/ipq_qca8084_interface_ctrl.h
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, The Linux Foundation. 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 __QCA8084_IF_CTRL_H_
|
||||||
|
#define __QCA8084_IF_CTRL_H_
|
||||||
|
|
||||||
|
#define EPHY_CFG_OFFSET 0xC90F018
|
||||||
|
#define EPHY_CFG_EPHY0_ADDR_BOFFSET 0
|
||||||
|
#define EPHY_CFG_EPHY1_ADDR_BOFFSET 5
|
||||||
|
#define EPHY_CFG_EPHY2_ADDR_BOFFSET 10
|
||||||
|
#define EPHY_CFG_EPHY3_ADDR_BOFFSET 15
|
||||||
|
|
||||||
|
#define SERDES_CFG_OFFSET 0xC90F014
|
||||||
|
#define SERDES_CFG_S0_ADDR_BOFFSET 0
|
||||||
|
#define SERDES_CFG_S1_ADDR_BOFFSET 5
|
||||||
|
#define SERDES_CFG_S1_XPCS_ADDR_BOFFSET 10
|
||||||
|
|
||||||
|
#define QCA8084_UNIPHY_SGMII_0 0
|
||||||
|
#define QCA8084_UNIPHY_SGMII_1 1
|
||||||
|
#define QCA8084_UNIPHY_XPCS 2
|
||||||
|
|
||||||
|
/*UNIPHY MII registers*/
|
||||||
|
#define QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET 0
|
||||||
|
|
||||||
|
/*UNIPHY MII register field*/
|
||||||
|
#define QCA8084_UNIPHY_ANA_SOFT_RESET 0
|
||||||
|
#define QCA8084_UNIPHY_ANA_SOFT_RELEASE 0x40
|
||||||
|
|
||||||
|
/*UNIPHY MMD*/
|
||||||
|
#define QCA8084_UNIPHY_MMD1 0x1
|
||||||
|
#define QCA8084_UNIPHY_MMD3 0x3
|
||||||
|
#define QCA8084_UNIPHY_MMD26 0x1a
|
||||||
|
#define QCA8084_UNIPHY_MMD27 0x1b
|
||||||
|
#define QCA8084_UNIPHY_MMD28 0x1c
|
||||||
|
#define QCA8084_UNIPHY_MMD31 0x1f
|
||||||
|
|
||||||
|
/*UNIPHY MMD1 registers*/
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CDA_CONTROL1 0x20
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CALIBRATION4 0x78
|
||||||
|
#define QCA8084_UNIPHY_MMD1_BYPASS_TUNING_IPG 0x189
|
||||||
|
#define QCA8084_UNIPHY_MMD1_MODE_CTRL 0x11b
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CHANNEL0_CFG 0x120
|
||||||
|
#define QCA8084_UNIPHY_MMD1_GMII_DATAPASS_SEL 0x180
|
||||||
|
#define QCA8084_UNIPHY_MMD1_USXGMII_RESET 0x18c
|
||||||
|
|
||||||
|
/*UNIPHY MMD1 register field*/
|
||||||
|
#define QCA8084_UNIPHY_MMD1_BYPASS_TUNING_IPG_EN 0x0fff
|
||||||
|
#define QCA8084_UNIPHY_MMD1_XPCS_MODE 0x1000
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_MODE 0x400
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_PLUS_MODE 0x800
|
||||||
|
#define QCA8084_UNIPHY_MMD1_1000BASE_X 0x0
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_PHY_MODE 0x10
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_MAC_MODE 0x20
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_MODE_CTRL_MASK 0x1f70
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_MASK 0xe
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CH0_AUTONEG_ENABLE 0x0
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CH0_FORCE_ENABLE 0x8
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_1G 0x4
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_100M 0x2
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_10M 0x0
|
||||||
|
#define QCA8084_UNIPHY_MMD1_DATAPASS_MASK 0x1
|
||||||
|
#define QCA8084_UNIPHY_MMD1_DATAPASS_USXGMII 0x1
|
||||||
|
#define QCA8084_UNIPHY_MMD1_DATAPASS_SGMII 0x0
|
||||||
|
#define QCA8084_UNIPHY_MMD1_CALIBRATION_DONE 0x80
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_FUNC_RESET 0x10
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SGMII_ADPT_RESET 0x800
|
||||||
|
#define QCA8084_UNIPHY_MMD1_SSCG_ENABLE 0x8
|
||||||
|
|
||||||
|
/*UNIPHY MMD3 registers*/
|
||||||
|
#define QCA8084_UNIPHY_MMD3_PCS_CTRL2 0x7
|
||||||
|
#define QCA8084_UNIPHY_MMD3_AN_LP_BASE_ABL2 0x14
|
||||||
|
#define QCA8084_UNIPHY_MMD3_10GBASE_R_PCS_STATUS1 0x20
|
||||||
|
#define QCA8084_UNIPHY_MMD3_DIG_CTRL1 0x8000
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL 0x8006
|
||||||
|
#define QCA8084_UNIPHY_MMD3_VR_RPCS_TPC 0x8007
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_TX_TIMER 0x8008
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_RX_TIMER 0x8009
|
||||||
|
#define QCA8084_UNIPHY_MMD3_MII_AM_INTERVAL 0x800a
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL1 0x800b
|
||||||
|
|
||||||
|
/*UNIPHY MMD3 register field*/
|
||||||
|
#define QCA8084_UNIPHY_MMD3_PCS_TYPE_10GBASE_R 0
|
||||||
|
#define QCA8084_UNIPHY_MMD3_10GBASE_R_UP 0x1000
|
||||||
|
#define QCA8084_UNIPHY_MMD3_USXGMII_EN 0x200
|
||||||
|
#define QCA8084_UNIPHY_MMD3_QXGMII_EN 0x1400
|
||||||
|
#define QCA8084_UNIPHY_MMD3_MII_AM_INTERVAL_VAL 0x6018
|
||||||
|
#define QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET 0x8000
|
||||||
|
#define QCA8084_UNIPHY_MMD3_XPCS_EEE_CAP 0x40
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_RES_REGS 0x100
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_SIGN_BIT_REGS 0x40
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_EN 0x3
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_TSL_REGS 0xa
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_TLU_REGS 0xc0
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_TWL_REGS 0x1600
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_100US_REG_REGS 0xc8
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_RWR_REG_REGS 0x1c00
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_TRANS_LPI_MODE 0x1
|
||||||
|
#define QCA8084_UNIPHY_MMD3_EEE_TRANS_RX_LPI_MODE 0x100
|
||||||
|
#define QCA8084_UNIPHY_MMD3_USXG_FIFO_RESET 0x400
|
||||||
|
|
||||||
|
/*UNIPHY MMD26 27 28 31 registers*/
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_CTRL 0
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_DIG_CTRL 0x8000
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_AN_INT_MSK 0x8001
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_ERR_SEL 0x8002
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_XAUI_MODE_CTRL 0x8004
|
||||||
|
|
||||||
|
/*UNIPHY MMD26 27 28 31 register field*/
|
||||||
|
#define QCA8084_UNIPHY_MMD_AN_COMPLETE_INT 0x1
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_4BITS_CTRL 0x0
|
||||||
|
#define QCA8084_UNIPHY_MMD_TX_CONFIG_CTRL 0x8
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_AN_ENABLE 0x1000
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_AN_RESTART 0x200
|
||||||
|
#define QCA8084_UNIPHY_MMD_MII_AN_COMPLETE_INT 0x1
|
||||||
|
#define QCA8084_UNIPHY_MMD_USXG_FIFO_RESET 0x20
|
||||||
|
#define QCA8084_UNIPHY_MMD_XPC_SPEED_MASK 0x2060
|
||||||
|
#define QCA8084_UNIPHY_MMD_XPC_SPEED_2500 0x20
|
||||||
|
#define QCA8084_UNIPHY_MMD_XPC_SPEED_1000 0x40
|
||||||
|
#define QCA8084_UNIPHY_MMD_XPC_SPEED_100 0x2000
|
||||||
|
#define QCA8084_UNIPHY_MMD_XPC_SPEED_10 0
|
||||||
|
#define QCA8084_UNIPHY_MMD_TX_IPG_CHECK_DISABLE 0x1
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QCA8084_UNIPHY_MAC = QCA8084_UNIPHY_MMD1_SGMII_MAC_MODE,
|
||||||
|
QCA8084_UNIPHY_PHY = QCA8084_UNIPHY_MMD1_SGMII_PHY_MODE,
|
||||||
|
QCA8084_UNIPHY_SGMII = QCA8084_UNIPHY_MMD1_SGMII_MODE,
|
||||||
|
QCA8084_UNIPHY_SGMII_PLUS = QCA8084_UNIPHY_MMD1_SGMII_PLUS_MODE,
|
||||||
|
QCA8084_UNIPHY_UQXGMII = QCA8084_UNIPHY_MMD1_XPCS_MODE,
|
||||||
|
} qca8084_uniphy_mode_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
#define PORT_WRAPPER_RGMII 18
|
#define PORT_WRAPPER_RGMII 18
|
||||||
#define PORT_WRAPPER_PSGMII_FIBER 19
|
#define PORT_WRAPPER_PSGMII_FIBER 19
|
||||||
#define PORT_WRAPPER_SGMII_FIBER 20
|
#define PORT_WRAPPER_SGMII_FIBER 20
|
||||||
|
#define PORT_WRAPPER_UQXGMII 21
|
||||||
|
#define PORT_WRAPPER_UQXGMII_3CHANNELS 22
|
||||||
#define PORT_WRAPPER_MAX 0xFF
|
#define PORT_WRAPPER_MAX 0xFF
|
||||||
|
|
||||||
/* ETH PHY Types */
|
/* ETH PHY Types */
|
||||||
|
|
@ -44,4 +46,6 @@
|
||||||
#define AQ_PHY_TYPE 0x3
|
#define AQ_PHY_TYPE 0x3
|
||||||
#define QCA8033_PHY_TYPE 0x4
|
#define QCA8033_PHY_TYPE 0x4
|
||||||
#define SFP_PHY_TYPE 0x5
|
#define SFP_PHY_TYPE 0x5
|
||||||
|
#define QCA8084_PHY_TYPE 0x6
|
||||||
|
#define UNUSED_PHY_TYPE 0xFF
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#define BIT(nr) (1UL << (nr))
|
#define BIT(nr) (1UL << (nr))
|
||||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||||
|
#define BITS_MASK(_s, _n) (((1UL << (_n)) - 1) << _s)
|
||||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -122,6 +123,17 @@ static inline unsigned int generic_hweight8(unsigned int w)
|
||||||
|
|
||||||
#include <asm/bitops.h>
|
#include <asm/bitops.h>
|
||||||
|
|
||||||
|
#define for_each_clear_bit(bit, addr, size) \
|
||||||
|
for ((bit) = find_first_zero_bit((addr), (size)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
/* same as for_each_clear_bit() but use bit as value to start with */
|
||||||
|
#define for_each_clear_bit_from(bit, addr, size) \
|
||||||
|
for ((bit) = find_next_zero_bit((addr), (size), (bit)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
/* linux/include/asm-generic/bitops/non-atomic.h */
|
/* linux/include/asm-generic/bitops/non-atomic.h */
|
||||||
|
|
||||||
#ifndef PLATFORM__SET_BIT
|
#ifndef PLATFORM__SET_BIT
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,14 @@
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
|
#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
|
||||||
|
|
||||||
|
#define PORT0 0
|
||||||
|
#define PORT1 1
|
||||||
|
#define PORT2 2
|
||||||
|
#define PORT3 3
|
||||||
|
#define PORT4 4
|
||||||
|
#define PORT5 5
|
||||||
|
#define PORT6 6
|
||||||
|
|
||||||
#define DEBUG_LL_STATE 0 /* Link local state machine changes */
|
#define DEBUG_LL_STATE 0 /* Link local state machine changes */
|
||||||
#define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */
|
#define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */
|
||||||
#define DEBUG_NET_PKT 0 /* Packets on info on the network at large */
|
#define DEBUG_NET_PKT 0 /* Packets on info on the network at large */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue