diff --git a/drivers/net/ipq40xx/ipq40xx_qca8075.c b/drivers/net/ipq40xx/ipq40xx_qca8075.c new file mode 100644 index 0000000000..452902cf51 --- /dev/null +++ b/drivers/net/ipq40xx/ipq40xx_qca8075.c @@ -0,0 +1,772 @@ +/* + * Copyright (c) 2015-2016, 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 +#include +#include +#include +#include +#include +#include "ipq40xx_edma_eth.h" +#include "ipq40xx_qca8075.h" + +extern int ipq40xx_mdio_write(int mii_id, + int regnum, u16 value); +extern int ipq40xx_mdio_read(int mii_id, + int regnum, ushort *data); + +static u32 qca8075_id; +static u16 qca8075_phy_reg_write(u32 dev_id, u32 phy_id, + u32 reg_id, u16 reg_val) +{ + ipq40xx_mdio_write(phy_id, reg_id, reg_val); + return 0; +} + +u16 qca8075_phy_reg_read(u32 dev_id, u32 phy_id, u32 reg_id) +{ + return ipq40xx_mdio_read(phy_id, reg_id, NULL); +} + +/* + * phy4 prfer medium + * get phy4 prefer medum, fiber or copper; + */ +static qca8075_phy_medium_t __phy_prefer_medium_get(u32 dev_id, + u32 phy_id) +{ + u16 phy_medium; + phy_medium = + qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_PHY_CHIP_CONFIG); + + return ((phy_medium & QCA8075_PHY4_PREFER_FIBER) ? + QCA8075_PHY_MEDIUM_FIBER : QCA8075_PHY_MEDIUM_COPPER); +} + +/* + * phy4 activer medium + * get phy4 current active medium, fiber or copper; + */ +static qca8075_phy_medium_t __phy_active_medium_get(u32 dev_id, + u32 phy_id) +{ + u16 phy_data = 0; + u32 phy_mode; + + phy_mode = qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_PHY_CHIP_CONFIG); + phy_mode &= 0x000f; + + if (phy_mode == QCA8075_PHY_PSGMII_AMDET) { + phy_data = qca8075_phy_reg_read(dev_id, + phy_id, QCA8075_PHY_SGMII_STATUS); + + if ((phy_data & QCA8075_PHY4_AUTO_COPPER_SELECT)) { + return QCA8075_PHY_MEDIUM_COPPER; + } else if ((phy_data & QCA8075_PHY4_AUTO_BX1000_SELECT)) { + /* PHY_MEDIUM_FIBER_BX1000 */ + return QCA8075_PHY_MEDIUM_FIBER; + } else if ((phy_data & QCA8075_PHY4_AUTO_FX100_SELECT)) { + /* PHY_MEDIUM_FIBER_FX100 */ + return QCA8075_PHY_MEDIUM_FIBER; + } + /* link down */ + return __phy_prefer_medium_get(dev_id, phy_id); + } else if ((phy_mode == QCA8075_PHY_PSGMII_BASET) || + (phy_mode == QCA8075_PHY_SGMII_BASET)) { + return QCA8075_PHY_MEDIUM_COPPER; + } else if ((phy_mode == QCA8075_PHY_PSGMII_BX1000) || + (phy_mode == QCA8075_PHY_PSGMII_FX100)) { + return QCA8075_PHY_MEDIUM_FIBER; + } else { + return QCA8075_PHY_MEDIUM_COPPER; + } +} + +/* + * phy4 copper page or fiber page select + * set phy4 copper or fiber page + */ + +static u8 __phy_reg_pages_sel(u32 dev_id, u32 phy_id, + qca8075_phy_reg_pages_t phy_reg_pages) +{ + u16 reg_pages; + reg_pages = qca8075_phy_reg_read(dev_id, + phy_id, QCA8075_PHY_CHIP_CONFIG); + + if (phy_reg_pages == QCA8075_PHY_COPPER_PAGES) { + reg_pages |= 0x8000; + } else if (phy_reg_pages == QCA8075_PHY_SGBX_PAGES) { + reg_pages &= ~0x8000; + } else + return -EINVAL; + + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_PHY_CHIP_CONFIG, reg_pages); + return 0; +} + +/* + * phy4 reg pages selection by active medium + * phy4 reg pages selection + */ +static u32 __phy_reg_pages_sel_by_active_medium(u32 dev_id, + u32 phy_id) +{ + qca8075_phy_medium_t phy_medium; + qca8075_phy_reg_pages_t reg_pages; + + phy_medium = __phy_active_medium_get(dev_id, phy_id); + if (phy_medium == QCA8075_PHY_MEDIUM_FIBER) { + reg_pages = QCA8075_PHY_SGBX_PAGES; + } else if (phy_medium == QCA8075_PHY_MEDIUM_COPPER) { + reg_pages = QCA8075_PHY_COPPER_PAGES; + } else { + return -1; + } + + return __phy_reg_pages_sel(dev_id, phy_id, reg_pages); +} + +u8 qca8075_phy_get_link_status(u32 dev_id, u32 phy_id) +{ + u16 phy_data; + if (phy_id == COMBO_PHY_ID) + __phy_reg_pages_sel_by_active_medium(dev_id, phy_id); + phy_data = qca8075_phy_reg_read(dev_id, + phy_id, QCA8075_PHY_SPEC_STATUS); + if (phy_data & QCA8075_STATUS_LINK_PASS) + return 0; + + return 1; +} + +u32 qca8075_phy_get_duplex(u32 dev_id, u32 phy_id, + fal_port_duplex_t * duplex) +{ + u16 phy_data; + + if (phy_id == COMBO_PHY_ID) { + __phy_reg_pages_sel_by_active_medium(dev_id, phy_id); + } + + phy_data = qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_PHY_SPEC_STATUS); + + /* + * Read duplex + */ + if (phy_data & QCA8075_STATUS_FULL_DUPLEX) + *duplex = FAL_FULL_DUPLEX; + else + *duplex = FAL_HALF_DUPLEX; + + return 0; +} + +u32 qca8075_phy_get_speed(u32 dev_id, u32 phy_id, + fal_port_speed_t * speed) +{ + u16 phy_data; + + if (phy_id == COMBO_PHY_ID) { + __phy_reg_pages_sel_by_active_medium(dev_id, phy_id); + } + phy_data = qca8075_phy_reg_read(dev_id, + phy_id, QCA8075_PHY_SPEC_STATUS); + + switch (phy_data & QCA8075_STATUS_SPEED_MASK) { + case QCA8075_STATUS_SPEED_1000MBS: + *speed = FAL_SPEED_1000; + break; + case QCA8075_STATUS_SPEED_100MBS: + *speed = FAL_SPEED_100; + break; + case QCA8075_STATUS_SPEED_10MBS: + *speed = FAL_SPEED_10; + break; + default: + return -EINVAL; + } + return 0; +} + +static u32 qca8075_phy_mmd_write(u32 dev_id, u32 phy_id, + u16 mmd_num, u16 reg_id, u16 reg_val) +{ + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_CTRL_REG, mmd_num); + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_DATA_REG, reg_id); + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_CTRL_REG, + 0x4000 | mmd_num); + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_DATA_REG, reg_val); + + return 0; +} + +static u16 qca8075_phy_mmd_read(u32 dev_id, u32 phy_id, + u16 mmd_num, u16 reg_id) +{ + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_CTRL_REG, mmd_num); + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_DATA_REG, reg_id); + qca8075_phy_reg_write(dev_id, phy_id, + QCA8075_MMD_CTRL_REG, + 0x4000 | mmd_num); + return qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_MMD_DATA_REG); +} + +/* + * get phy4 medium is 100fx + */ +static u8 __medium_is_fiber_100fx(u32 dev_id, u32 phy_id) +{ + u16 phy_data; + phy_data = qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_PHY_SGMII_STATUS); + + if (phy_data & QCA8075_PHY4_AUTO_FX100_SELECT) { + return 1; + } + /* Link down */ + if ((!(phy_data & QCA8075_PHY4_AUTO_COPPER_SELECT)) && + (!(phy_data & QCA8075_PHY4_AUTO_BX1000_SELECT)) && + (!(phy_data & QCA8075_PHY4_AUTO_SGMII_SELECT))) { + + phy_data = qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_PHY_CHIP_CONFIG); + if ((phy_data & QCA8075_PHY4_PREFER_FIBER) + && (!(phy_data & QCA8075_PHY4_FIBER_MODE_1000BX))) { + return 1; + } + } + return 0; +} + +/* + * qca8075_phy_set_hibernate - set hibernate status + * set hibernate status + */ +static u32 qca8075_phy_set_hibernate(u32 dev_id, u32 phy_id, u8 enable) +{ + u16 phy_data; + + qca8075_phy_reg_write(dev_id, phy_id, QCA8075_DEBUG_PORT_ADDRESS, + QCA8075_DEBUG_PHY_HIBERNATION_CTRL); + + phy_data = qca8075_phy_reg_read(dev_id, phy_id, + QCA8075_DEBUG_PORT_DATA); + + if (enable) { + phy_data |= 0x8000; + } else { + phy_data &= ~0x8000; + } + + qca8075_phy_reg_write(dev_id, phy_id, QCA8075_DEBUG_PORT_DATA, phy_data); + return 0; +} + +/* + * qca8075_restart_autoneg - restart the phy autoneg + */ +static u32 qca8075_phy_restart_autoneg(u32 dev_id, u32 phy_id) +{ + u16 phy_data; + + if (phy_id == COMBO_PHY_ID) { + if (__medium_is_fiber_100fx(dev_id, phy_id)) + return -1; + __phy_reg_pages_sel_by_active_medium(dev_id, phy_id); + } + phy_data = qca8075_phy_reg_read(dev_id, phy_id, QCA8075_PHY_CONTROL); + phy_data |= QCA8075_CTRL_AUTONEGOTIATION_ENABLE; + qca8075_phy_reg_write(dev_id, phy_id, QCA8075_PHY_CONTROL, + phy_data | QCA8075_CTRL_RESTART_AUTONEGOTIATION); + + return 0; +} + +/* + * qca8075_phy_get_8023az status + * get 8023az status + */ +static u32 qca8075_phy_get_8023az(u32 dev_id, u32 phy_id, u8 *enable) +{ + u16 phy_data; + if (phy_id == COMBO_PHY_ID) { + if (QCA8075_PHY_MEDIUM_COPPER != + __phy_active_medium_get(dev_id, phy_id)) + return -1; + } + *enable = 0; + + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, QCA8075_PHY_MMD7_NUM, + QCA8075_PHY_MMD7_ADDR_8023AZ_EEE_CTRL); + + if ((phy_data & 0x0004) && (phy_data & 0x0002)) + *enable = 1; + + return 0; +} + +/* + * qca8075_phy_set_powersave - set power saving status + */ +static u32 qca8075_phy_set_powersave(u32 dev_id, u32 phy_id, u8 enable) +{ + u16 phy_data; + u8 status = 0; + + if (phy_id == COMBO_PHY_ID) { + if (QCA8075_PHY_MEDIUM_COPPER != + __phy_active_medium_get(dev_id, phy_id)) + return -1; + } + + if (enable) { + qca8075_phy_get_8023az(dev_id, phy_id, &status); + if (!status) { + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL); + phy_data &= ~(1 << 14); + qca8075_phy_mmd_write(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL, + phy_data); + } + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL5); + phy_data &= ~(1 << 14); + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL5, + phy_data); + + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL3); + phy_data &= ~(1 << 15); + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL3, phy_data); + + } else { + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL); + phy_data |= (1 << 14); + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL, + phy_data); + + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL5); + phy_data |= (1 << 14); + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL5, phy_data); + + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL3); + phy_data |= (1 << 15); + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_CLD_CTRL3, phy_data); + + } + qca8075_phy_reg_write(dev_id, phy_id, QCA8075_PHY_CONTROL, 0x9040); + return 0; +} + +/* + * qca8075_phy_set_802.3az + */ + static u32 qca8075_phy_set_8023az(u32 dev_id, u32 phy_id, u8 enable) +{ + u16 phy_data; + + if (phy_id == COMBO_PHY_ID) { + if (QCA8075_PHY_MEDIUM_COPPER != + __phy_active_medium_get(dev_id, phy_id)) + return -1; + } + phy_data = qca8075_phy_mmd_read(dev_id, phy_id, QCA8075_PHY_MMD7_NUM, + QCA8075_PHY_MMD7_ADDR_8023AZ_EEE_CTRL); + if (enable) { + phy_data |= 0x0006; + + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD7_NUM, + QCA8075_PHY_MMD7_ADDR_8023AZ_EEE_CTRL, phy_data); + if (qca8075_id == QCA8075_PHY_V1_0_5P) { + /* + * Workaround to avoid packet loss and < 10m cable + * 1000M link not stable under az enable + */ + qca8075_phy_mmd_write(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL, + AZ_TIMER_CTRL_ADJUST_VALUE); + + qca8075_phy_mmd_write(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_CLD_CTRL, + AZ_CLD_CTRL_ADJUST_VALUE); + } + } else { + phy_data &= ~0x0006; + qca8075_phy_mmd_write(dev_id, phy_id, QCA8075_PHY_MMD7_NUM, + QCA8075_PHY_MMD7_ADDR_8023AZ_EEE_CTRL, phy_data); + if (qca8075_id == QCA8075_PHY_V1_0_5P) { + qca8075_phy_mmd_write(dev_id, phy_id, + QCA8075_PHY_MMD3_NUM, + QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL, + AZ_TIMER_CTRL_DEFAULT_VALUE); + } + } + qca8075_phy_restart_autoneg(dev_id, phy_id); + return 0; +} + +void ess_reset(void) +{ + writel(0x1, 0x1812008); + mdelay(10); + writel(0x0, 0x1812008); + mdelay(100); +} + +void qca8075_ess_reset(void) +{ + int i; + u32 status; + /* + * Fix phy psgmii RX 20bit + */ + qca8075_phy_reg_write(0, 5, 0x0, 0x005b); + /* + * Reset phy psgmii + */ + qca8075_phy_reg_write(0, 5, 0x0, 0x001b); + /* + * Release reset phy psgmii + */ + qca8075_phy_reg_write(0, 5, 0x0, 0x005b); + for (i = 0; i < QCA8075_MAX_TRIES; i++) { + status = qca8075_phy_mmd_read(0, 5, 1, 0x28); + if(status & 0x1) + break; + mdelay(10); + } + if (i >= QCA8075_MAX_TRIES) + printf("qca8075 PSGMII PLL_VCO_CALIB Not Ready\n"); + mdelay(50); + /* + * Check qca8075 psgmii calibration done end. + * Freeze phy psgmii RX CDR + */ + qca8075_phy_reg_write(0, 5, 0x1a, 0x2230); + + ess_reset(); + /* + * Check ipq40xx psgmii calibration done start + */ + for (i = 0; i < QCA8075_MAX_TRIES; i++) { + status = readl(0x000980A0); + if (status & 0x1) + break; + mdelay(10); + } + if (i >= QCA8075_MAX_TRIES) + printf("PSGMII PLL_VCO_CALIB Not Ready\n"); + mdelay(50); + /* + * Check ipq40xx psgmii calibration done end. + * Relesae phy psgmii RX CDR + */ + qca8075_phy_reg_write(0, 5, 0x1a, 0x3230); + /* + * Release phy psgmii RX 20bit + */ + qca8075_phy_reg_write(0, 5, 0x0, 0x005f); + mdelay(200); +} + +void psgmii_self_test(void) +{ + int i, phy, j; + u32 value; + u32 phy_t_status; + u16 status; + u32 tx_counter_ok, tx_counter_error; + u32 rx_counter_ok, rx_counter_error; + u32 tx_counter_ok_high16; + u32 rx_counter_ok_high16; + u32 tx_ok, rx_ok; + + /* + * Switch to access MII reg for copper + */ + qca8075_phy_reg_write(0, 4, 0x1f, 0x8500); + for (phy = 0; phy < 5; phy++) { + /* + * Enable phy mdio broadcast write + */ + qca8075_phy_mmd_write(0, phy, 7, 0x8028, 0x801f); + } + /* + * Force no link by power down + */ + qca8075_phy_reg_write(0, 0x1f, 0x0, 0x1840); + /* + * Packet number + */ + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8021, 0x3000); + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8062, 0x05e0); + /* + * Fix mdi status + */ + qca8075_phy_reg_write(0, 0x1f, 0x10, 0x6800); + + for (i = 0; i < 100; i++) { + phy_t_status = 0; + for (phy = 0; phy < 5; phy++) { + value = readl(0xc00066c + (phy * 0xc)); + /* + * Enable mac loop back + */ + writel((value | (1 << 21)), (0xc00066c + (phy * 0xc))); + } + /* + * Phy single test + */ + for (phy = 0; phy < 5; phy++) { + /* + * Enable loopback + */ + qca8075_phy_reg_write(0, phy, 0x0, 0x9000); + qca8075_phy_reg_write(0, phy, 0x0, 0x4140); + /* + * Check link + */ + j = 0; + while (j < 100) { + status = qca8075_phy_reg_read(0, phy, 0x11); + if (status & (1 << 10)) + break; + mdelay(10); + j++; + } + /* + * Enable check + */ + qca8075_phy_mmd_write(0, phy, 7, 0x8029, 0x0000); + qca8075_phy_mmd_write(0, phy, 7, 0x8029, 0x0003); + /* + * Start traffic + */ + qca8075_phy_mmd_write(0, phy, 7, 0x8020, 0xa000); + mdelay(200); + /* + * check counter + */ + tx_counter_ok = qca8075_phy_mmd_read(0, phy, 7, 0x802e); + tx_counter_ok_high16 = qca8075_phy_mmd_read(0, phy, 7, 0x802d); + tx_counter_error = qca8075_phy_mmd_read(0, phy, 7, 0x802f); + rx_counter_ok = qca8075_phy_mmd_read(0, phy, 7, 0x802b); + rx_counter_ok_high16 = qca8075_phy_mmd_read(0, phy, 7, 0x802a); + rx_counter_error = qca8075_phy_mmd_read(0, phy, 7, 0x802c); + tx_ok = tx_counter_ok + (tx_counter_ok_high16 << 16); + rx_ok = rx_counter_ok + (rx_counter_ok_high16 << 16); + /* + * Success + */ + if((tx_ok == 0x3000) && (tx_counter_error == 0)) { + phy_t_status &= (~(1 << phy)); + } else { + phy_t_status |= (1 << phy); + } + /* + * Power down + */ + qca8075_phy_reg_write(0, phy, 0x0, 0x1840); + } + /* + * Reset 5-phy + */ + qca8075_phy_reg_write(0, 0x1f, 0x0, 0x9000); + /* + * Enable 5-phy loopback + */ + qca8075_phy_reg_write(0, 0x1f, 0x0, 0x4140); + /* + * check link + */ + j = 0; + while (j < 100) { + for (phy = 0; phy < 5; phy++) { + status = qca8075_phy_reg_read(0, phy, 0x11); + if (!(status & (1 << 10))) + break; + } + if (phy >= 5) + break; + mdelay(10); + j++; + } + /* + * Enable check + */ + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8029, 0x0000); + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8029, 0x0003); + /* + * Start traffic + */ + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8020, 0xa000); + mdelay(200); + for (phy = 0; phy < 5; phy++) { + /* + * Check counter + */ + tx_counter_ok = qca8075_phy_mmd_read(0, phy, 7, 0x802e); + tx_counter_ok_high16 = qca8075_phy_mmd_read(0, phy, 7, 0x802d); + tx_counter_error = qca8075_phy_mmd_read(0, phy, 7, 0x802f); + rx_counter_ok = qca8075_phy_mmd_read(0, phy, 7, 0x802b); + rx_counter_ok_high16 = qca8075_phy_mmd_read(0, phy, 7, 0x802a); + rx_counter_error = qca8075_phy_mmd_read(0, phy, 7, 0x802c); + tx_ok = tx_counter_ok + (tx_counter_ok_high16 << 16); + rx_ok = rx_counter_ok + (rx_counter_ok_high16 << 16); + debug("rx_ok: %d, tx_ok: %d", rx_ok, tx_ok); + debug("rx_counter_error: %d, tx_counter_error: %d", + rx_counter_error, tx_counter_error); + /* + * Success + */ + if ((tx_ok == 0x3000) && (tx_counter_error == 0)) { + phy_t_status &= (~(1 << (phy + 8))); + } else { + phy_t_status |= (1 << (phy + 8)); + } + } + if (phy_t_status) { + qca8075_ess_reset(); + } else { + break; + } + } + /* + * Configuration recover + */ + /* + * Packet number + */ + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8021, 0x0); + /* + * Disable check + */ + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8029, 0x0); + /* + * Disable traffic + */ + qca8075_phy_mmd_write(0, 0x1f, 7, 0x8020, 0x0); +} + +void clear_self_test_config(void) +{ + int phy = 0; + u32 value = 0; + + /* + * Disable phy internal loopback + */ + qca8075_phy_reg_write(0, 0x1f, 0x10, 0x6860); + qca8075_phy_reg_write(0, 0x1f, 0x0, 0x9040); + + for (phy = 0; phy < 5; phy++) { + value = readl(0xc00066c + (phy * 0xc)); + /* + * Disable mac loop back + */ + writel((value&(~(1 << 21))), (0xc00066c + (phy * 0xc))); + /* + * Disable phy mdio broadcast writei + */ + qca8075_phy_mmd_write(0, phy, 7, 0x8028, 0x001f); + } + +} + +int ipq40xx_qca8075_phy_init(struct ipq40xx_eth_dev *info) +{ + u16 phy_data; + u32 phy_id = 0; + struct phy_ops *qca8075_ops; + + qca8075_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops)); + if (!qca8075_ops) + return -ENOMEM; + + qca8075_ops->phy_get_link_status = qca8075_phy_get_link_status; + qca8075_ops->phy_get_speed = qca8075_phy_get_speed; + qca8075_ops->phy_get_duplex = qca8075_phy_get_duplex; + info->ops = qca8075_ops; + + qca8075_id = phy_data = qca8075_phy_reg_read(0x0, 0x0, QCA8075_PHY_ID1); + printf ("PHY ID1: 0x%x\n", phy_data); + phy_data = qca8075_phy_reg_read(0x0, 0x0, QCA8075_PHY_ID2); + printf ("PHY ID2: 0x%x\n", phy_data); + qca8075_id = (qca8075_id << 16) | phy_data; + + if (qca8075_id == QCA8075_PHY_V1_0_5P) { + phy_data = qca8075_phy_mmd_read(0, PSGMII_ID, + QCA8075_PHY_MMD1_NUM, QCA8075_PSGMII_FIFI_CTRL); + phy_data &= 0xbfff; + qca8075_phy_mmd_write(0, PSGMII_ID, QCA8075_PHY_MMD1_NUM, + QCA8075_PSGMII_FIFI_CTRL, phy_data); + } + + /* + * Enable AZ transmitting ability + */ + qca8075_phy_mmd_write(0, PSGMII_ID, QCA8075_PHY_MMD1_NUM, + QCA8075_PSGMII_MODE_CTRL, + QCA8075_PHY_PSGMII_MODE_CTRL_ADJUST_VALUE); + + /* + * Enable phy power saving function by default + */ + if (qca8075_id == QCA8075_PHY_V1_1_2P) + phy_id = 3; + + if ((qca8075_id == QCA8075_PHY_V1_0_5P) || + (qca8075_id == QCA8075_PHY_V1_1_5P) || + (qca8075_id == QCA8075_PHY_V1_1_2P)) { + for (; phy_id < 5; phy_id++) { + qca8075_phy_set_8023az(0x0, phy_id, 0x1); + qca8075_phy_set_powersave(0x0, phy_id, 0x1); + qca8075_phy_set_hibernate(0x0, phy_id, 0x1); + } + } + + phy_data = qca8075_phy_mmd_read(0, 4, QCA8075_PHY_MMD3_NUM, 0x805a); + phy_data &= (~(1 << 1)); + qca8075_phy_mmd_write(0, 4, QCA8075_PHY_MMD3_NUM, 0x805a, phy_data); + + return 0; +} diff --git a/drivers/net/ipq40xx/ipq40xx_qca8075.h b/drivers/net/ipq40xx/ipq40xx_qca8075.h new file mode 100644 index 0000000000..2d69336da1 --- /dev/null +++ b/drivers/net/ipq40xx/ipq40xx_qca8075.h @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2015-2016, 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 _QCA8075_PHY_H_ +#define _QCA8075_PHY_H_ + +#define QCA8075_PHY_V1_0_5P 0x004DD0B0 +#define QCA8075_PHY_V1_1_5P 0x004DD0B1 +#define QCA8075_PHY_V1_1_2P 0x004DD0B2 + +#define QCA8075_PHY_CONTROL 0 +#define QCA8075_PHY_STATUS 1 +#define QCA8075_PHY_ID1 2 +#define QCA8075_PHY_ID2 3 +#define QCA8075_AUTONEG_ADVERT 4 +#define QCA8075_LINK_PARTNER_ABILITY 5 +#define QCA8075_AUTONEG_EXPANSION 6 +#define QCA8075_NEXT_PAGE_TRANSMIT 7 +#define QCA8075_LINK_PARTNER_NEXT_PAGE 8 +#define QCA8075_1000BASET_CONTROL 9 +#define QCA8075_1000BASET_STATUS 10 +#define QCA8075_MMD_CTRL_REG 13 +#define QCA8075_MMD_DATA_REG 14 +#define QCA8075_EXTENDED_STATUS 15 +#define QCA8075_PHY_SPEC_CONTROL 16 +#define QCA8075_PHY_SPEC_STATUS 17 +#define QCA8075_PHY_INTR_MASK 18 +#define QCA8075_PHY_INTR_STATUS 19 +#define QCA8075_PHY_CDT_CONTROL 22 +#define QCA8075_PHY_CDT_STATUS 28 +#define QCA8075_DEBUG_PORT_ADDRESS 29 +#define QCA8075_DEBUG_PORT_DATA 30 +#define COMBO_PHY_ID 4 +#define PSGMII_ID 5 + +#define QCA8075_DEBUG_PHY_HIBERNATION_CTRL 0xb +#define QCA8075_DEBUG_PHY_POWER_SAVING_CTRL 0x29 +#define QCA8075_PHY_MMD7_ADDR_8023AZ_EEE_CTRL 0x3c +#define QCA8075_PHY_MMD3_ADDR_REMOTE_LOOPBACK_CTRL 0x805a +#define QCA8075_PHY_MMD3_WOL_MAGIC_MAC_CTRL1 0x804a +#define QCA8075_PHY_MMD3_WOL_MAGIC_MAC_CTRL2 0x804b +#define QCA8075_PHY_MMD3_WOL_MAGIC_MAC_CTRL3 0x804c +#define QCA8075_PHY_MMD3_WOL_CTRL 0x8012 + +#define QCA8075_PSGMII_FIFI_CTRL 0x6e +#define QCA8075_PSGMII_CALIB_CTRL 0x27 +#define QCA8075_PSGMII_MODE_CTRL 0x6d +#define QCA8075_PHY_PSGMII_MODE_CTRL_ADJUST_VALUE 0x220c + +#define QCA8075_PHY_MMD7_NUM 7 +#define QCA8075_PHY_MMD3_NUM 3 +#define QCA8075_PHY_MMD1_NUM 1 + +#define QCA8075_PHY_SGMII_STATUS 0x1a /* sgmii_status Register */ +#define QCA8075_PHY4_AUTO_SGMII_SELECT 0x40 +#define QCA8075_PHY4_AUTO_COPPER_SELECT 0x20 +#define QCA8075_PHY4_AUTO_BX1000_SELECT 0x10 +#define QCA8075_PHY4_AUTO_FX100_SELECT 0x8 + +#define QCA8075_PHY_CHIP_CONFIG 0x1f /* Chip Configuration Register */ +#define BT_BX_SG_REG_SELECT BIT_15 +#define BT_BX_SG_REG_SELECT_OFFSET 15 +#define BT_BX_SG_REG_SELECT_LEN 1 +#define QCA8075_SG_BX_PAGES 0x0 +#define QCA8075_SG_COPPER_PAGES 0x1 + +#define QCA8075_PHY_PSGMII_BASET 0x0 +#define QCA8075_PHY_PSGMII_BX1000 0x1 +#define QCA8075_PHY_PSGMII_FX100 0x2 +#define QCA8075_PHY_PSGMII_AMDET 0x3 +#define QCA8075_PHY_SGMII_BASET 0x4 + +#define QCA8075_PHY4_PREFER_FIBER 0x400 +#define PHY4_PREFER_COPPER 0x0 +#define PHY4_PREFER_FIBER 0x1 + +#define QCA8075_PHY4_FIBER_MODE_1000BX 0x100 +#define AUTO_100FX_FIBER 0x0 +#define AUTO_1000BX_FIBER 0x1 + +#define QCA8075_PHY_MDIX 0x0020 +#define QCA8075_PHY_MDIX_AUTO 0x0060 +#define QCA8075_PHY_MDIX_STATUS 0x0040 + +#define MODE_CFG_QUAL BIT_4 +#define MODE_CFG_QUAL_OFFSET 4 +#define MODE_CFG_QUAL_LEN 4 + +#define MODE_CFG BIT_0 +#define MODE_CFG_OFFSET 0 +#define MODE_CFG_LEN 4 + +#define QCA8075_PHY_MMD3_ADDR_8023AZ_CLD_CTRL 0x8007 +#define QCA8075_PHY_MMD3_ADDR_8023AZ_TIMER_CTRL 0x804e +#define QCA8075_PHY_MMD3_ADDR_CLD_CTRL5 0x8005 +#define QCA8075_PHY_MMD3_ADDR_CLD_CTRL3 0x8003 + +#define AZ_TIMER_CTRL_DEFAULT_VALUE 0x3062 +#define AZ_CLD_CTRL_DEFAULT_VALUE 0x83f6 +#define AZ_TIMER_CTRL_ADJUST_VALUE 0x7062 +#define AZ_CLD_CTRL_ADJUST_VALUE 0x8396 + + /*debug port */ +#define QCA8075_DEBUG_PORT_RGMII_MODE 18 +#define QCA8075_DEBUG_PORT_RGMII_MODE_EN 0x0008 + +#define QCA8075_DEBUG_PORT_RX_DELAY 0 +#define QCA8075_DEBUG_PORT_RX_DELAY_EN 0x8000 + +#define QCA8075_DEBUG_PORT_TX_DELAY 5 +#define QCA8075_DEBUG_PORT_TX_DELAY_EN 0x0100 + + /* PHY Registers Field */ + + /* Control Register fields offset:0 */ + /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define QCA8075_CTRL_SPEED_MSB 0x0040 + + /* Collision test enable */ +#define QCA8075_CTRL_COLL_TEST_ENABLE 0x0080 + + /* FDX =1, half duplex =0 */ +#define QCA8075_CTRL_FULL_DUPLEX 0x0100 + + /* Restart auto negotiation */ +#define QCA8075_CTRL_RESTART_AUTONEGOTIATION 0x0200 + + /* Isolate PHY from MII */ +#define QCA8075_CTRL_ISOLATE 0x0400 + + /* Power down */ +#define QCA8075_CTRL_POWER_DOWN 0x0800 + + /* Auto Neg Enable */ +#define QCA8075_CTRL_AUTONEGOTIATION_ENABLE 0x1000 + + /* Local Loopback Enable */ +#define QCA8075_LOCAL_LOOPBACK_ENABLE 0x4000 + + /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define QCA8075_CTRL_SPEED_LSB 0x2000 + + /* 0 = normal, 1 = loopback */ +#define QCA8075_CTRL_LOOPBACK 0x4000 +#define QCA8075_CTRL_SOFTWARE_RESET 0x8000 + +#define QCA8075_CTRL_SPEED_MASK 0x2040 +#define QCA8075_CTRL_SPEED_1000 0x0040 +#define QCA8075_CTRL_SPEED_100 0x2000 +#define QCA8075_CTRL_SPEED_10 0x0000 + +#define QCA8075_RESET_DONE(phy_control) \ + (((phy_control) & (QCA8075_CTRL_SOFTWARE_RESET)) == 0) + + /* Status Register fields offset:1 */ + /* Extended register capabilities */ +#define QCA8075_STATUS_EXTENDED_CAPS 0x0001 + + /* Jabber Detected */ +#define QCA8075_STATUS_JABBER_DETECT 0x0002 + + /* Link Status 1 = link */ +#define QCA8075_STATUS_LINK_STATUS_UP 0x0004 + + /* Auto Neg Capable */ +#define QCA8075_STATUS_AUTONEG_CAPS 0x0008 + + /* Remote Fault Detect */ +#define QCA8075_STATUS_REMOTE_FAULT 0x0010 + + /* Auto Neg Complete */ +#define QCA8075_STATUS_AUTO_NEG_DONE 0x0020 + + /* Preamble may be suppressed */ +#define QCA8075_STATUS_PREAMBLE_SUPPRESS 0x0040 + + /* Ext. status info in Reg 0x0F */ +#define QCA8075_STATUS_EXTENDED_STATUS 0x0100 + + /* 100T2 Half Duplex Capable */ +#define QCA8075_STATUS_100T2_HD_CAPS 0x0200 + + /* 100T2 Full Duplex Capable */ +#define QCA8075_STATUS_100T2_FD_CAPS 0x0400 + + /* 10T Half Duplex Capable */ +#define QCA8075_STATUS_10T_HD_CAPS 0x0800 + + /* 10T Full Duplex Capable */ +#define QCA8075_STATUS_10T_FD_CAPS 0x1000 + + /* 100X Half Duplex Capable */ +#define QCA8075_STATUS_100X_HD_CAPS 0x2000 + + /* 100X Full Duplex Capable */ +#define QCA8075_STATUS_100X_FD_CAPS 0x4000 + + /* 100T4 Capable */ +#define QCA8075_STATUS_100T4_CAPS 0x8000 + + /* extended status register capabilities */ + +#define QCA8075_STATUS_1000T_HD_CAPS 0x1000 + +#define QCA8075_STATUS_1000T_FD_CAPS 0x2000 + +#define QCA8075_STATUS_1000X_HD_CAPS 0x4000 + +#define QCA8075_STATUS_1000X_FD_CAPS 0x8000 + +#define QCA8075_AUTONEG_DONE(ip_phy_status) \ + (((ip_phy_status) & (QCA8075_STATUS_AUTO_NEG_DONE)) == \ + (QCA8075_STATUS_AUTO_NEG_DONE)) + + /* PHY identifier1 offset:2 */ +//Organizationally Unique Identifier bits 3:18 + + /* PHY identifier2 offset:3 */ +//Organizationally Unique Identifier bits 19:24 + + /* Auto-Negotiation Advertisement register. offset:4 */ + /* indicates IEEE 802.3 CSMA/CD */ +#define QCA8075_ADVERTISE_SELECTOR_FIELD 0x0001 + + /* 10T Half Duplex Capable */ +#define QCA8075_ADVERTISE_10HALF 0x0020 + + /* 10T Full Duplex Capable */ +#define QCA8075_ADVERTISE_10FULL 0x0040 + + /* 100TX Half Duplex Capable */ +#define QCA8075_ADVERTISE_100HALF 0x0080 + + /* 100TX Full Duplex Capable */ +#define QCA8075_ADVERTISE_100FULL 0x0100 + + /* 100T4 Capable */ +#define QCA8075_ADVERTISE_100T4 0x0200 + + /* Pause operation desired */ +#define QCA8075_ADVERTISE_PAUSE 0x0400 + + /* Asymmetric Pause Direction bit */ +#define QCA8075_ADVERTISE_ASYM_PAUSE 0x0800 + + /* Remote Fault detected */ +#define QCA8075_ADVERTISE_REMOTE_FAULT 0x2000 + + /* Next Page ability supported */ +#define QCA8075_ADVERTISE_NEXT_PAGE 0x8000 + + /* 100TX Half Duplex Capable */ +#define QCA8075_ADVERTISE_1000HALF 0x0100 + + /* 100TX Full Duplex Capable */ +#define QCA8075_ADVERTISE_1000FULL 0x0200 + +#define QCA8075_ADVERTISE_ALL \ + (QCA8075_ADVERTISE_10HALF | QCA8075_ADVERTISE_10FULL | \ + QCA8075_ADVERTISE_100HALF | QCA8075_ADVERTISE_100FULL | \ + QCA8075_ADVERTISE_1000FULL) + +#define QCA8075_ADVERTISE_MEGA_ALL \ + (QCA8075_ADVERTISE_10HALF | QCA8075_ADVERTISE_10FULL | \ + QCA8075_ADVERTISE_100HALF | QCA8075_ADVERTISE_100FULL) + +#define QCA8075_BX_ADVERTISE_1000FULL 0x0020 +#define QCA8075_BX_ADVERTISE_1000HALF 0x0040 +#define QCA8075_BX_ADVERTISE_PAUSE 0x0080 +#define QCA8075_BX_ADVERTISE_ASYM_PAUSE 0x0100 + +#define QCA8075_BX_ADVERTISE_ALL \ + (QCA8075_BX_ADVERTISE_ASYM_PAUSE | QCA8075_BX_ADVERTISE_PAUSE | \ + QCA8075_BX_ADVERTISE_1000HALF | QCA8075_BX_ADVERTISE_1000FULL) + + /* Link Partner ability offset:5 */ + /* Same as advertise selector */ +#define QCA8075_LINK_SLCT 0x001f + + /* Can do 10mbps half-duplex */ +#define QCA8075_LINK_10BASETX_HALF_DUPLEX 0x0020 + + /* Can do 10mbps full-duplex */ +#define QCA8075_LINK_10BASETX_FULL_DUPLEX 0x0040 + + /* Can do 100mbps half-duplex */ +#define QCA8075_LINK_100BASETX_HALF_DUPLEX 0x0080 + + /* Can do 100mbps full-duplex */ +#define QCA8075_LINK_100BASETX_FULL_DUPLEX 0x0100 + + /* Can do 1000mbps full-duplex */ +#define QCA8075_LINK_1000BASETX_FULL_DUPLEX 0x0800 + + /* Can do 1000mbps half-duplex */ +#define QCA8075_LINK_1000BASETX_HALF_DUPLEX 0x0400 + + /* 100BASE-T4 */ +#define QCA8075_LINK_100BASE4 0x0200 + + /* PAUSE */ +#define QCA8075_LINK_PAUSE 0x0400 + + /* Asymmetrical PAUSE */ +#define QCA8075_LINK_ASYPAUSE 0x0800 + + /* Link partner faulted */ +#define QCA8075_LINK_RFAULT 0x2000 + + /* Link partner acked us */ +#define QCA8075_LINK_LPACK 0x4000 + + /* Next page bit */ +#define QCA8075_LINK_NPAGE 0x8000 + + /* Auto-Negotiation Expansion Register offset:6 */ + + /* Next Page Transmit Register offset:7 */ + + /* Link partner Next Page Register offset:8 */ + + /* 1000BASE-T Control Register offset:9 */ + /* Advertise 1000T HD capability */ +#define QCA8075_CTL_1000T_HD_CAPS 0x0100 + + /* Advertise 1000T FD capability */ +#define QCA8075_CTL_1000T_FD_CAPS 0x0200 + + /* 1=Repeater/switch device port 0=DTE device */ +#define QCA8075_CTL_1000T_REPEATER_DTE 0x0400 + + /* 1=Configure PHY as Master 0=Configure PHY as Slave */ +#define QCA8075_CTL_1000T_MS_VALUE 0x0800 + + /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */ +#define QCA8075_CTL_1000T_MS_ENABLE 0x1000 + + /* Normal Operation */ +#define QCA8075_CTL_1000T_TEST_MODE_NORMAL 0x0000 + + /* Transmit Waveform test */ +#define QCA8075_CTL_1000T_TEST_MODE_1 0x2000 + + /* Master Transmit Jitter test */ +#define QCA8075_CTL_1000T_TEST_MODE_2 0x4000 + + /* Slave Transmit Jitter test */ +#define QCA8075_CTL_1000T_TEST_MODE_3 0x6000 + + /* Transmitter Distortion test */ +#define QCA8075_CTL_1000T_TEST_MODE_4 0x8000 +#define QCA8075_CTL_1000T_SPEED_MASK 0x0300 +#define QCA8075_CTL_1000T_DEFAULT_CAP_MASK 0x0300 + + /* 1000BASE-T Status Register offset:10 */ + /* LP is 1000T HD capable */ +#define QCA8075_STATUS_1000T_LP_HD_CAPS 0x0400 + + /* LP is 1000T FD capable */ +#define QCA8075_STATUS_1000T_LP_FD_CAPS 0x0800 + + /* Remote receiver OK */ +#define QCA8075_STATUS_1000T_REMOTE_RX_STATUS 0x1000 + + /* Local receiver OK */ +#define QCA8075_STATUS_1000T_LOCAL_RX_STATUS 0x2000 + + /* 1=Local TX is Master, 0=Slave */ +#define QCA8075_STATUS_1000T_MS_CONFIG_RES 0x4000 + +#define QCA8075_STATUS_1000T_MS_CONFIG_FAULT 0x8000 + + /* Master/Slave config fault */ +#define QCA8075_STATUS_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define QCA8075_STATUS_1000T_LOCAL_RX_STATUS_SHIFT 13 + + /* Phy Specific Control Register offset:16 */ + /* 1=Jabber Function disabled */ +#define QCA8075_CTL_JABBER_DISABLE 0x0001 + + /* 1=Polarity Reversal enabled */ +#define QCA8075_CTL_POLARITY_REVERSAL 0x0002 + + /* 1=SQE Test enabled */ +#define QCA8075_CTL_SQE_TEST 0x0004 +#define QCA8075_CTL_MAC_POWERDOWN 0x0008 + + /* 1=CLK125 low, 0=CLK125 toggling + #define QCA8075_CTL_CLK125_DISABLE 0x0010 + */ + /* MDI Crossover Mode bits 6:5 */ + /* Manual MDI configuration */ +#define QCA8075_CTL_MDI_MANUAL_MODE 0x0000 + + /* Manual MDIX configuration */ +#define QCA8075_CTL_MDIX_MANUAL_MODE 0x0020 + + /* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ +#define QCA8075_CTL_AUTO_X_1000T 0x0040 + + /* Auto crossover enabled all speeds */ +#define QCA8075_CTL_AUTO_X_MODE 0x0060 + + /* 1=Enable Extended 10BASE-T distance + * (Lower 10BASE-T RX Threshold) + * 0=Normal 10BASE-T RX Threshold */ +#define QCA8075_CTL_10BT_EXT_DIST_ENABLE 0x0080 + + /* 1=5-Bit interface in 100BASE-TX + * 0=MII interface in 100BASE-TX */ +#define QCA8075_CTL_MII_5BIT_ENABLE 0x0100 + + /* 1=Scrambler disable */ +#define QCA8075_CTL_SCRAMBLER_DISABLE 0x0200 + + /* 1=Force link good */ +#define QCA8075_CTL_FORCE_LINK_GOOD 0x0400 + + /* 1=Assert CRS on Transmit */ +#define QCA8075_CTL_ASSERT_CRS_ON_TX 0x0800 + +#define QCA8075_CTL_POLARITY_REVERSAL_SHIFT 1 +#define QCA8075_CTL_AUTO_X_MODE_SHIFT 5 +#define QCA8075_CTL_10BT_EXT_DIST_ENABLE_SHIFT 7 + + + /* Phy Specific status fields offset:17 */ + /* 1=Speed & Duplex resolved */ +#define QCA8075_STATUS_LINK_PASS 0x0400 +#define QCA8075_STATUS_RESOVLED 0x0800 + + /* 1=Duplex 0=Half Duplex */ +#define QCA8075_STATUS_FULL_DUPLEX 0x2000 + + /* Speed, bits 14:15 */ +#define QCA8075_STATUS_SPEED 0xC000 +#define QCA8075_STATUS_SPEED_MASK 0xC000 + + /* 00=10Mbs */ +#define QCA8075_STATUS_SPEED_10MBS 0x0000 + + /* 01=100Mbs */ +#define QCA8075_STATUS_SPEED_100MBS 0x4000 + + /* 10=1000Mbs */ +#define QCA8075_STATUS_SPEED_1000MBS 0x8000 +#define QCA8075_SPEED_DUPLEX_RESOVLED(phy_status) \ + (((phy_status) & \ + (QCA8075_STATUS_RESOVLED)) == \ + (QCA8075_STATUS_RESOVLED)) + + /*phy debug port1 register offset:29 */ + /*phy debug port2 register offset:30 */ + + /*QCA8075 interrupt flag */ +#define QCA8075_INTR_SPEED_CHANGE 0x4000 +#define QCA8075_INTR_DUPLEX_CHANGE 0x2000 +#define QCA8075_INTR_STATUS_UP_CHANGE 0x0400 +#define QCA8075_INTR_STATUS_DOWN_CHANGE 0x0800 +#define QCA8075_INTR_BX_FX_STATUS_DOWN_CHANGE 0x0100 +#define QCA8075_INTR_BX_FX_STATUS_UP_CHANGE 0x0080 +#define QCA8075_INTR_MEDIA_STATUS_CHANGE 0x1000 +#define QCA8075_INTR_WOL 0x0001 +#define QCA8075_INTR_POE 0x0002 + +#define RUN_CDT 0x8000 +#define CABLE_LENGTH_UNIT 0x0400 +#define QCA8075_MAX_TRIES 100 + +#endif /* _QCA8075_PHY_H_ */