// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/at803x.c
*
* Driver for Qualcomm Atheros AR803x PHY
*
* Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
*/
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool_netlink.h>
#include <linux/of_gpio.h>
#include <linux/bitfield.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/consumer.h>
#include <dt-bindings/net/qca-ar803x.h>
#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
#define AT803X_SFC_ASSERT_CRS BIT(11)
#define AT803X_SFC_FORCE_LINK BIT(10)
#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5)
#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3
#define AT803X_SFC_MANUAL_MDIX 0x1
#define AT803X_SFC_MANUAL_MDI 0x0
#define AT803X_SFC_SQE_TEST BIT(2)
#define AT803X_SFC_POLARITY_REVERSAL BIT(1)
#define AT803X_SFC_DISABLE_JABBER BIT(0)
#define AT803X_SPECIFIC_STATUS 0x11
#define AT803X_SS_SPEED_MASK (3 << 14)
#define AT803X_SS_SPEED_1000 (2 << 14)
#define AT803X_SS_SPEED_100 (1 << 14)
#define AT803X_SS_SPEED_10 (0 << 14)
#define AT803X_SS_DUPLEX BIT(13)
#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
#define AT803X_SS_MDIX BIT(6)
#define AT803X_INTR_ENABLE 0x12
#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13)
#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12)
#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11)
#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10)
#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5)
#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1)
#define AT803X_INTR_ENABLE_WOL BIT(0)
#define AT803X_INTR_STATUS 0x13
#define AT803X_SMART_SPEED 0x14
#define AT803X_SMART_SPEED_ENABLE BIT(5)
#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2)
#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1)
#define AT803X_CDT 0x16
#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8)
#define AT803X_CDT_ENABLE_TEST BIT(0)
#define AT803X_CDT_STATUS 0x1c
#define AT803X_CDT_STATUS_STAT_NORMAL 0
#define AT803X_CDT_STATUS_STAT_SHORT 1
#define AT803X_CDT_STATUS_STAT_OPEN 2
#define AT803X_CDT_STATUS_STAT_FAIL 3
#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8)
#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0)
#define AT803X_LED_CONTROL 0x18
#define AT803X_DEVICE_ADDR 0x03
#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
#define AT803X_REG_CHIP_CONFIG 0x1f
#define AT803X_BT_BX_REG_SEL 0x8000
#define AT803X_DEBUG_ADDR 0x1D
#define AT803X_DEBUG_DATA 0x1E
#define AT803X_MODE_CFG_MASK 0x0F
#define AT803X_MODE_CFG_SGMII 0x01
#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/
#define AT803X_PSSR_MR_AN_COMPLETE 0x0200
#define AT803X_DEBUG_REG_0 0x00
#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15)
#define AT803X_DEBUG_REG_5 0x05
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
#define AT803X_DEBUG_REG_1F 0x1F
#define AT803X_DEBUG_PLL_ON BIT(2)
#define AT803X_DEBUG_RGMII_1V8 BIT(3)
/* AT803x supports either the XTAL input pad, an internal PLL or the
* DSP as clock reference for the clock output pad. The XTAL reference
* is only used for 25 MHz output, all other frequencies need the PLL.
* The DSP as a clock reference is used in synchronous ethernet
* applications.
*
* By default the PLL is only enabled if there is a link. Otherwise
* the PHY will go into low power state and disabled the PLL. You can
* set the PLL_ON bit (see debug register 0x1f) to keep the PLL always
* enabled.
*/
#define AT803X_MMD7_CLK25M 0x8016
#define AT803X_CLK_OUT_MASK GENMASK(4, 2)
#define AT803X_CLK_OUT_25MHZ_XTAL 0
#define AT803X_CLK_OUT_25MHZ_DSP 1
#define AT803X_CLK_OUT_50MHZ_PLL 2
#define AT803X_CLK_OUT_50MHZ_DSP 3
#define AT803X_CLK_OUT_62_5MHZ_PLL 4
#define AT803X_CLK_OUT_62_5MHZ_DSP 5
#define AT803X_CLK_OUT_125MHZ_PLL 6
#define AT803X_CLK_OUT_125MHZ_DSP 7
/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask
* but doesn't support choosing between XTAL/PLL and DSP.
*/
#define AT8035_CLK_OUT_MASK GENMASK(4, 3)
#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7)
#define AT803X_CLK_OUT_STRENGTH_FULL 0
#define AT803X_CLK_OUT_STRENGTH_HALF 1
#define AT803X_CLK_OUT_STRENGTH_QUARTER 2
#define AT803X_DEFAULT_DOWNSHIFT 5
#define AT803X_MIN_DOWNSHIFT 2
#define AT803X_MAX_DOWNSHIFT 9
#define ATH9331_PHY_ID 0x004dd041
#define ATH8030_PHY_ID 0x004dd076
#define ATH8031_PHY_ID 0x004dd074
#define ATH8032_PHY_ID 0x004dd023
#define ATH8035_PHY_ID 0x004dd072
#define AT8030_PHY_ID_MASK 0xffffffef
MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
struct at803x_priv {
int flags;
#define AT803X_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */
u16 clk_25m_reg;
u16 clk_25m_mask;
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
struct regulator *vddio;
};
struct at803x_context {
u16 bmcr;
u16 advertise;
u16 control1000;
u16 int_enable;
u16 smart_speed;
u16 led_control;
};
static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
{
int ret;
ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
if (ret < 0)
return ret;
return phy_read(phydev, AT803X_DEBUG_DATA);
}
static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
u16 clear, u16 set)
{
u16 val;
int ret;
ret = at803x_debug_reg_read(phydev, reg);
if (ret < 0)
return ret;
val = ret & 0xffff;
val &= ~clear;
val |= set;
return phy_write(phydev, AT803X_DEBUG_DATA, val);
}
static int at803x_enable_rx_delay(struct phy_d