en8811h:use 1.2.5 version
This commit is contained in:
parent
5116de248b
commit
575201b5dc
@ -242,7 +242,6 @@
|
||||
pinctrl-0 = <&en8811_pwr_a>;
|
||||
|
||||
airoha,polarity = <3>;
|
||||
airoha,surge = <0>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -262,7 +261,6 @@
|
||||
pinctrl-0 = <&en8811_pwr_b>;
|
||||
|
||||
airoha,polarity = <3>;
|
||||
airoha,surge = <0>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -147,31 +147,41 @@
|
||||
#size-cells = <0>;
|
||||
|
||||
phy14: phy@14 {
|
||||
/* EN8811H PHY ID */
|
||||
compatible = "ethernet-phy-id03a2.a411";
|
||||
/* PHY Address */
|
||||
reg = <14>;
|
||||
reset-gpios = <&pio 49 1>; /* GPIO49 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&en8811_pwr_a>;
|
||||
|
||||
airoha,polarity = <3>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpios = <&pio 49 1>;
|
||||
reset-assert-us = <10000>;
|
||||
reset-deassert-us = <20000>;
|
||||
|
||||
phy-mode = "2500base-x";
|
||||
full-duplex;
|
||||
pause;
|
||||
airoha,polarity = <3>;
|
||||
};
|
||||
|
||||
phy15: phy@15 {
|
||||
/* EN8811H PHY ID */
|
||||
compatible = "ethernet-phy-id03a2.a411";
|
||||
/* PHY Address */
|
||||
reg = <15>;
|
||||
reset-gpios = <&pio 47 1>; /* GPIO47 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&en8811_pwr_b>;
|
||||
|
||||
airoha,polarity = <3>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpios = <&pio 47 1>;
|
||||
reset-assert-us = <10000>;
|
||||
reset-deassert-us = <20000>;
|
||||
|
||||
phy-mode = "2500base-x";
|
||||
full-duplex;
|
||||
pause;
|
||||
airoha,polarity = <3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -186,30 +186,40 @@
|
||||
#size-cells = <0>;
|
||||
|
||||
phy14: phy@14 {
|
||||
/* EN8811H PHY ID */
|
||||
compatible = "ethernet-phy-id03a2.a411";
|
||||
/* PHY Address */
|
||||
reg = <14>;
|
||||
reset-gpios = <&pio 49 1>; /* GPIO49 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&en8811_pwr_a>;
|
||||
|
||||
airoha,polarity = <3>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpios = <&pio 49 1>;
|
||||
reset-assert-us = <10000>;
|
||||
reset-deassert-us = <20000>;
|
||||
|
||||
phy-mode = "2500base-x";
|
||||
full-duplex;
|
||||
airoha,polarity = <3>;
|
||||
pause;
|
||||
};
|
||||
|
||||
phy15: phy@15 {
|
||||
/* EN8811H PHY ID */
|
||||
compatible = "ethernet-phy-id03a2.a411";
|
||||
/* PHY Address */
|
||||
reg = <15>;
|
||||
reset-gpios = <&pio 47 1>; /* GPIO47 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&en8811_pwr_b>;
|
||||
|
||||
airoha,polarity = <3>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpios = <&pio 47 1>;
|
||||
reset-assert-us = <10000>;
|
||||
reset-deassert-us = <20000>;
|
||||
|
||||
phy-mode = "2500base-x";
|
||||
full-duplex;
|
||||
airoha,polarity = <3>;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
@ -10,15 +10,10 @@
|
||||
#ifndef __EN8811H_H
|
||||
#define __EN8811H_H
|
||||
|
||||
#define EN8811H_MD32_DM "EthMD32.dm.bin"
|
||||
#define EN8811H_MD32_DSP "EthMD32.DSP.bin"
|
||||
#define EN8811H_IVY "ivypram.bin"
|
||||
|
||||
#define EN8811H_PHY_ID1 0x03a2
|
||||
#define EN8811H_PHY_ID2 0xa411
|
||||
#define EN8811H_PHY_ID ((EN8811H_PHY_ID1 << 16) | EN8811H_PHY_ID2)
|
||||
#define EN8811H_PHY_READY 0x02
|
||||
#define EN8811H_PHY_IVY_READY 0xABC
|
||||
#define MAX_RETRY 25
|
||||
|
||||
#define EN8811H_TX_POL_NORMAL 0x1
|
||||
@ -48,7 +43,7 @@
|
||||
#define MII_MMD_ADDR_DATA_REG 0x0e
|
||||
#define MMD_OP_MODE_DATA BIT(14)
|
||||
|
||||
#define EN8811H_DRIVER_VERSION "v1.3.0"
|
||||
#define EN8811H_DRIVER_VERSION "v1.2.5"
|
||||
|
||||
#define LED_ON_CTRL(i) (0x024 + ((i)*2))
|
||||
#define LED_ON_EN (1 << 15)
|
||||
@ -88,64 +83,20 @@
|
||||
#define LED_BLK_DUR (0x023)
|
||||
#define LED_BLK_DUR_MASK (0xffff)
|
||||
|
||||
#define UNIT_LED_BLINK_DURATION 780
|
||||
#define UNIT_LED_BLINK_DURATION 1024
|
||||
|
||||
#define GET_BIT(val, bit) ((val & BIT(bit)) >> bit)
|
||||
|
||||
#define INVALID_DATA 0xffff
|
||||
#define PBUS_INVALID_DATA 0xffffffff
|
||||
|
||||
/* MII Registers */
|
||||
#define AIR_AUX_CTRL_STATUS 0x1d
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2)
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_100 0x4
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8
|
||||
#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc
|
||||
|
||||
/* Registers on BUCKPBUS */
|
||||
#define EN8811H_2P5G_LPA 0x3b30
|
||||
#define EN8811H_2P5G_LPA_2P5G BIT(0)
|
||||
|
||||
#define EN8811H_FW_CTRL_1 0x0f0018
|
||||
#define EN8811H_FW_CTRL_1_START 0x0
|
||||
#define EN8811H_FW_CTRL_1_FINISH 0x1
|
||||
#define EN8811H_FW_CTRL_2 0x800000
|
||||
#define EN8811H_FW_CTRL_2_LOADING BIT(11)
|
||||
#define EN8811H_LOOP 0x800
|
||||
|
||||
#define NUM_ASI_REGS 5
|
||||
struct air_cable_test_rsl {
|
||||
int status[4];
|
||||
unsigned int length[4];
|
||||
};
|
||||
|
||||
struct en8811h_priv {
|
||||
struct dentry *debugfs_root;
|
||||
unsigned int dm_crc32;
|
||||
unsigned int dsp_crc32;
|
||||
unsigned int ivy_crc32;
|
||||
char buf[512];
|
||||
int pol;
|
||||
int surge;
|
||||
int cko;
|
||||
struct kobject *cable_kobj;
|
||||
int running_status;
|
||||
int pair[4];
|
||||
int an;
|
||||
int link;
|
||||
int speed;
|
||||
int duplex;
|
||||
int pause;
|
||||
int asym_pause;
|
||||
u16 on_crtl[3];
|
||||
u16 blk_crtl[3];
|
||||
u32 firmware_version;
|
||||
bool mcu_needs_restart;
|
||||
bool mcu_load;
|
||||
int debug;
|
||||
int phy_handle;
|
||||
int init_stage;
|
||||
int need_an;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct air_base_t_led_cfg {
|
||||
@ -155,18 +106,6 @@ struct air_base_t_led_cfg {
|
||||
u16 on_cfg;
|
||||
u16 blk_cfg;
|
||||
};
|
||||
|
||||
enum air_init_stage {
|
||||
AIR_INIT_START,
|
||||
AIR_INIT_CONFIG,
|
||||
AIR_INIT_FW_LOADING,
|
||||
AIR_INIT_FW_READY,
|
||||
AIR_INIT_SUCESS,
|
||||
AIR_INIT_FW_FAIL,
|
||||
AIR_INIT_FAIL,
|
||||
AIR_INIT_LAST
|
||||
};
|
||||
|
||||
enum air_led_gpio {
|
||||
AIR_LED2_GPIO3 = 3,
|
||||
AIR_LED1_GPIO4,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,12 +15,10 @@
|
||||
#define phydev_mdio_bus(_dev) (_dev->bus)
|
||||
#define phydev_addr(_dev) (_dev->addr)
|
||||
#define phydev_dev(_dev) (&_dev->dev)
|
||||
#define phydev_kobj(_dev) (&_dev->dev.kobj)
|
||||
#else
|
||||
#define phydev_mdio_bus(_dev) (_dev->mdio.bus)
|
||||
#define phydev_addr(_dev) (_dev->mdio.addr)
|
||||
#define phydev_dev(_dev) (&_dev->mdio.dev)
|
||||
#define phydev_kobj(_dev) (&_dev->mdio.dev.kobj)
|
||||
#endif
|
||||
|
||||
#define DEBUGFS_COUNTER "counter"
|
||||
@ -33,42 +31,8 @@
|
||||
#define DEBUGFS_DBG_REG_SHOW "dbg_regs_show"
|
||||
#define DEBUGFS_TEMPERATURE "temp"
|
||||
#define DEBUGFS_LP_SPEED "lp_speed"
|
||||
#define DEBUGFS_MII_CL22_OP "cl22_op"
|
||||
#define DEBUGFS_MII_CL45_OP "cl45_op"
|
||||
#define DEBUGFS_CABLE_DIAG "cable_diag"
|
||||
#define DEBUGFS_LED_MODE "led_mode"
|
||||
#define DEBUGFS_TX_COMP "tx_comp"
|
||||
|
||||
#define CMD_MAX_LENGTH 128
|
||||
|
||||
/* bits range: for example AIR_BITS_RANGE(16, 4) = 0x0F0000 */
|
||||
#ifndef AIR_BITS_RANGE
|
||||
#define AIR_BITS_RANGE(offset, range) GENMASK((offset) + (range) - 1U, (offset))
|
||||
#endif /* End of AIR_BITS_RANGE */
|
||||
|
||||
/* bits offset right: for example AIR_BITS_OFF_R(0x1234, 8, 4) = 0x2 */
|
||||
#ifndef AIR_BITS_OFF_R
|
||||
#define AIR_BITS_OFF_R(val, offset, range) (((val) >> (offset)) & GENMASK((range) - 1U, 0))
|
||||
#endif /* End of AIR_BITS_OFF_R */
|
||||
|
||||
/* bits offset left: for example AIR_BITS_OFF_L(0x1234, 8, 4) = 0x400 */
|
||||
#ifndef AIR_BITS_OFF_L
|
||||
#define AIR_BITS_OFF_L(val, offset, range) (((val) & GENMASK((range) - 1U, 0)) << (offset))
|
||||
#endif /* End of AIR_BITS_OFF_L */
|
||||
|
||||
#define AIR_EN8811H_SET_VALUE(__out__, __val__, __offset__, __length__) \
|
||||
{ \
|
||||
(__out__) &= ~AIR_BITS_RANGE((__offset__), (__length__)); \
|
||||
(__out__) |= AIR_BITS_OFF_L((__val__), (__offset__), (__length__)); \
|
||||
}
|
||||
|
||||
#define CTL1000_PORT_TYPE (0x0400)
|
||||
#define CTL1000_TEST_NORMAL (0x0000)
|
||||
#define CTL1000_TEST_TM1 (0x2000)
|
||||
#define CTL1000_TEST_TM2 (0x4000)
|
||||
#define CTL1000_TEST_TM3 (0x6000)
|
||||
#define CTL1000_TEST_TM4 (0x8000)
|
||||
#define MMD_DEV_VSPEC1 (0x1e)
|
||||
#define DEBUGFS_MII_CL22_OP "cl22_op"
|
||||
#define DEBUGFS_MII_CL45_OP "cl45_op"
|
||||
|
||||
enum air_port_mode {
|
||||
AIR_PORT_MODE_FORCE_100,
|
||||
@ -100,104 +64,6 @@ enum air_link_mode_bit {
|
||||
AIR_LINK_MODE_2500baseT_Full_BIT = 5,
|
||||
};
|
||||
|
||||
enum air_led_force {
|
||||
AIR_LED_NORMAL = 0,
|
||||
AIR_LED_FORCE_OFF,
|
||||
AIR_LED_FORCE_ON,
|
||||
AIR_LED_FORCE_LAST = 0xff,
|
||||
};
|
||||
|
||||
enum air_para {
|
||||
AIR_PARA_PRIV,
|
||||
AIR_PARA_PHYDEV,
|
||||
AIR_PARA_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_port_cable_status {
|
||||
AIR_PORT_CABLE_STATUS_ERROR,
|
||||
AIR_PORT_CABLE_STATUS_OPEN,
|
||||
AIR_PORT_CABLE_STATUS_SHORT,
|
||||
AIR_PORT_CABLE_STATUS_NORMAL,
|
||||
AIR_PORT_CABLE_STATUS_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_surge {
|
||||
AIR_SURGE_0R,
|
||||
AIR_SURGE_5R,
|
||||
AIR_SURGE_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_port_cable_test_pair {
|
||||
AIR_PORT_CABLE_TEST_PAIR_A,
|
||||
AIR_PORT_CABLE_TEST_PAIR_B,
|
||||
AIR_PORT_CABLE_TEST_PAIR_C,
|
||||
AIR_PORT_CABLE_TEST_PAIR_D,
|
||||
AIR_PORT_CABLE_TEST_PAIR_ALL,
|
||||
AIR_PORT_CABLE_TEST_PAIR_LAST
|
||||
};
|
||||
|
||||
enum air_cko {
|
||||
AIR_CKO_DIS,
|
||||
AIR_CKO_EN,
|
||||
AIR_CKO_LAST = 0xff
|
||||
};
|
||||
|
||||
enum air_tx_comp_mode {
|
||||
AIR_TX_COMP_MODE_100M_PAIR_A,
|
||||
AIR_TX_COMP_MODE_100M_PAIR_B,
|
||||
AIR_TX_COMP_MODE_100M_PAIR_A_DISCRETE,
|
||||
AIR_TX_COMP_MODE_100M_PAIR_B_DISCRETE,
|
||||
AIR_TX_COMP_MODE_1000M_TM1,
|
||||
AIR_TX_COMP_MODE_1000M_TM2,
|
||||
AIR_TX_COMP_MODE_1000M_TM3,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_TD,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_A,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_B,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_C,
|
||||
AIR_TX_COMP_MODE_1000M_TM4_CM_PAIR_D,
|
||||
AIR_TX_COMP_MODE_2500M_TM1,
|
||||
AIR_TX_COMP_MODE_2500M_TM2,
|
||||
AIR_TX_COMP_MODE_2500M_TM3,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_1,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_2,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_3,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_4,
|
||||
AIR_TX_COMP_MODE_2500M_TM4_TONE_5,
|
||||
AIR_TX_COMP_MODE_2500M_TM5,
|
||||
AIR_TX_COMP_MODE_2500M_TM6,
|
||||
AIR_TX_COMP_MODE_LAST = 0xFF,
|
||||
};
|
||||
|
||||
struct trrg_param_s {
|
||||
unsigned int TrRG_LSB :5;
|
||||
unsigned int Reserved_21 :3;
|
||||
unsigned int TrRG_MSB :5;
|
||||
unsigned int Reserved_29 :3;
|
||||
unsigned int Reserved_0 :1;
|
||||
unsigned int DATA_ADDR :6;
|
||||
unsigned int NODE_ADDR :4;
|
||||
unsigned int CH_ADDR :2;
|
||||
unsigned int WR_RD_CTRL :1;
|
||||
unsigned int Reserved_14 :1;
|
||||
unsigned int PKT_XMT_STA :1;
|
||||
};
|
||||
|
||||
union trrgdesc_s {
|
||||
struct trrg_param_s param;
|
||||
unsigned short Raw[2];
|
||||
unsigned int DescVal;
|
||||
};
|
||||
|
||||
struct trrg_s {
|
||||
union trrgdesc_s TrRGDesc;
|
||||
unsigned int RgMask;
|
||||
};
|
||||
|
||||
struct hal_tr_data_s {
|
||||
unsigned short data_lo;
|
||||
unsigned char data_hi;
|
||||
};
|
||||
|
||||
#ifndef unlikely
|
||||
# define unlikely(x) (x)
|
||||
#endif
|
||||
@ -218,10 +84,7 @@ unsigned int air_buckpbus_reg_read(struct phy_device *phydev,
|
||||
int air_buckpbus_reg_write(struct phy_device *phydev,
|
||||
unsigned int pbus_address, unsigned int pbus_data);
|
||||
int en8811h_of_init(struct phy_device *phydev);
|
||||
int air_surge_protect_cfg(struct phy_device *phydev);
|
||||
int air_ref_clk_speed(struct phy_device *phydev, int para);
|
||||
int air_cko_cfg(struct phy_device *phydev);
|
||||
int airoha_control_flag(struct phy_device *phydev, int mask, int val);
|
||||
int air_surge_5ohm_config(struct phy_device *phydev);
|
||||
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
|
||||
int airphy_debugfs_init(struct phy_device *phydev);
|
||||
void airphy_debugfs_remove(struct phy_device *phydev);
|
||||
|
9225
target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_fw.h
Normal file
9225
target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_fw.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,10 +19,9 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include "air_en8811h_api.h"
|
||||
#include "air_en8811h_fw.h"
|
||||
#include "air_en8811h.h"
|
||||
|
||||
MODULE_DESCRIPTION("Airoha EN8811H PHY Drivers");
|
||||
@ -35,11 +34,6 @@ MODULE_LICENSE("GPL");
|
||||
* GPIO3 <-> BASE_T_LED2,
|
||||
**************************/
|
||||
/* User-defined.B */
|
||||
/* #define AIR_MD32_FW_CHECK */
|
||||
/* #define AIR_IVY_LOAD */
|
||||
#ifdef AIR_IVY_LOAD
|
||||
/* #define AIR_IVY_CHECK */
|
||||
#endif
|
||||
#define AIR_LED_SUPPORT
|
||||
#ifdef AIR_LED_SUPPORT
|
||||
static const struct air_base_t_led_cfg led_cfg[3] = {
|
||||
@ -57,49 +51,8 @@ static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
|
||||
/***********************************************************
|
||||
* F U N C T I O N S
|
||||
***********************************************************/
|
||||
#ifdef AIR_MD32_FW_CHECK
|
||||
static void air_mdio_read_buf(struct phy_device *phydev, unsigned long address,
|
||||
const struct firmware *fw, unsigned int *crc32)
|
||||
{
|
||||
unsigned int offset;
|
||||
int ret = 0;
|
||||
unsigned int pbus_data_low, pbus_data_high;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct mii_bus *mbus = phydev_mdio_bus(phydev);
|
||||
int addr = phydev_addr(phydev);
|
||||
char *buf = kmalloc(fw->size, GFP_KERNEL);
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
memset(buf, '\0', fw->size);
|
||||
/* page 4 */
|
||||
ret |= air_mii_cl22_write(mbus, addr, 0x1F, 4);
|
||||
/* address increment*/
|
||||
ret |= air_mii_cl22_write(mbus, addr, 0x10, 0x8000);
|
||||
ret |= air_mii_cl22_write(mbus, addr,
|
||||
0x15, (unsigned int)((address >> 16) & 0xffff));
|
||||
ret |= air_mii_cl22_write(mbus, addr,
|
||||
0x16, (unsigned int)(address & 0xffff));
|
||||
for (offset = 0; offset < fw->size; offset += 4) {
|
||||
pbus_data_high = air_mii_cl22_read(mbus, addr, 0x17);
|
||||
pbus_data_low = air_mii_cl22_read(mbus, addr, 0x18);
|
||||
buf[offset + 0] = pbus_data_low & 0xff;
|
||||
buf[offset + 1] = (pbus_data_low & 0xff00) >> 8;
|
||||
buf[offset + 2] = pbus_data_high & 0xff;
|
||||
buf[offset + 3] = (pbus_data_high & 0xff00) >> 8;
|
||||
}
|
||||
msleep(100);
|
||||
*crc32 = ~crc32(~0, buf, fw->size);
|
||||
ret |= air_mii_cl22_write(mbus, addr, 0x1F, 0);
|
||||
kfree(buf);
|
||||
if (ret) {
|
||||
dev_info(dev, "%s 0x%lx FAIL(ret:%d)\n",
|
||||
__func__, address, ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
static int air_mdio_write_buf(struct phy_device *phydev,
|
||||
unsigned long address, const struct firmware *fw)
|
||||
static int air_mdio_write_buf(struct phy_device *phydev, unsigned long address,
|
||||
unsigned long array_size, const unsigned char *buffer)
|
||||
{
|
||||
unsigned int write_data, offset;
|
||||
int ret = 0;
|
||||
@ -130,14 +83,14 @@ static int air_mdio_write_buf(struct phy_device *phydev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < fw->size; offset += 4) {
|
||||
write_data = (fw->data[offset + 3] << 8) | fw->data[offset + 2];
|
||||
for (offset = 0; offset < array_size; offset += 4) {
|
||||
write_data = (buffer[offset + 3] << 8) | buffer[offset + 2];
|
||||
ret = air_mii_cl22_write(mbus, addr, 0x13, write_data);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "air_mii_cl22_write, ret: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
write_data = (fw->data[offset + 1] << 8) | fw->data[offset];
|
||||
write_data = (buffer[offset + 1] << 8) | buffer[offset];
|
||||
ret = air_mii_cl22_write(mbus, addr, 0x14, write_data);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "air_mii_cl22_write, ret: %d\n", ret);
|
||||
@ -151,147 +104,14 @@ static int air_mdio_write_buf(struct phy_device *phydev,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef AIR_IVY_LOAD
|
||||
static int modify_reg_bits(struct phy_device *phydev,
|
||||
unsigned int reg, unsigned int mask, unsigned int set)
|
||||
{
|
||||
unsigned int write_data;
|
||||
int ret;
|
||||
|
||||
write_data = air_buckpbus_reg_read(phydev, reg);
|
||||
write_data &= ~mask;
|
||||
write_data |= set;
|
||||
ret = air_buckpbus_reg_write(phydev, reg, write_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int air_mdio_load_ivy(struct phy_device *phydev,
|
||||
unsigned long address, const struct firmware *fw)
|
||||
{
|
||||
unsigned int write_data = 0, offset, read_data;
|
||||
int ret = 0, retry;
|
||||
#ifdef AIR_IVY_CHECK
|
||||
int error = 0;
|
||||
#endif
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0xcf924, 0x12);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xcfa28);
|
||||
write_data |= BIT(0);
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0xcfa28, write_data);
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xcfa28);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(100);
|
||||
for (offset = 0; offset < fw->size; offset += 4) {
|
||||
write_data = (fw->data[offset + 3] << 24) | (fw->data[offset + 2] << 16);
|
||||
write_data |= ((fw->data[offset + 1] << 8) | fw->data[offset]);
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
address, write_data);
|
||||
#ifdef AIR_IVY_CHECK
|
||||
read_data = air_buckpbus_reg_read(phydev, address);
|
||||
if (write_data != read_data) {
|
||||
dev_info(dev, "%x: write_data(0x%x) != read_data(0x%x)\n",
|
||||
address, write_data, read_data);
|
||||
error++;
|
||||
}
|
||||
#endif
|
||||
address += 1;
|
||||
}
|
||||
#ifdef AIR_IVY_CHECK
|
||||
if (error)
|
||||
dev_err(dev, "Check ivy Fail(%d)\n", error);
|
||||
else
|
||||
dev_err(dev, "Check ivy Pass\n");
|
||||
#endif
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, BIT(0), 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, 0, BIT(16));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret |= air_buckpbus_reg_write(phydev,
|
||||
0xDC065, 0x80);
|
||||
ret |= air_buckpbus_reg_write(phydev,
|
||||
0xDC064, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
retry = 5;
|
||||
do {
|
||||
msleep(300);
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0xDC064, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xDC065);
|
||||
if (write_data == 0x80)
|
||||
break;
|
||||
if (!retry)
|
||||
dev_err(dev, "0xDC065 is not ready.(0x%x)\n", write_data);
|
||||
} while (retry--);
|
||||
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, BIT(16), 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = modify_reg_bits(phydev, 0xCFA28, 0, BIT(24));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
retry = 10;
|
||||
do {
|
||||
msleep(300);
|
||||
write_data = air_buckpbus_reg_read(phydev, 0xCFA38);
|
||||
if (write_data == EN8811H_PHY_IVY_READY) {
|
||||
dev_info(dev, "IVY ready!\n");
|
||||
break;
|
||||
}
|
||||
if (!retry)
|
||||
dev_err(dev, "IVY is not ready.(0x%x)\n", write_data);
|
||||
} while (retry--);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static int en8811h_load_firmware(struct phy_device *phydev)
|
||||
{
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
const struct firmware *fw;
|
||||
const char *firmware;
|
||||
int ret = 0;
|
||||
u32 pbus_value = 0;
|
||||
#ifdef AIR_MD32_FW_CHECK
|
||||
unsigned int d_crc32 = 0, crc32 = 0;
|
||||
int retry = 0;
|
||||
#endif
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
priv->init_stage = AIR_INIT_FW_LOADING;
|
||||
#ifdef AIR_IVY_LOAD
|
||||
firmware = EN8811H_IVY;
|
||||
ret = request_firmware_direct(&fw, firmware, dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"failed to load firmware %s, ret: %d\n", firmware, ret);
|
||||
return ret;
|
||||
}
|
||||
priv->ivy_crc32 = ~crc32(~0, fw->data, fw->size);
|
||||
dev_info(dev, "%s: crc32=0x%x\n",
|
||||
firmware, ~crc32(~0, fw->data, fw->size));
|
||||
/* Download ivy */
|
||||
ret = air_mdio_load_ivy(phydev, 0xd4000, fw);
|
||||
release_firmware(fw);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_mdio_write_buf 0xd4000 fail, ret: %d\n", ret);
|
||||
goto release;
|
||||
}
|
||||
#endif
|
||||
ret = air_buckpbus_reg_write(phydev,
|
||||
0x0f0018, 0x0);
|
||||
if (ret < 0)
|
||||
@ -302,120 +122,29 @@ static int en8811h_load_firmware(struct phy_device *phydev)
|
||||
0x800000, pbus_value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
firmware = EN8811H_MD32_DM;
|
||||
ret = request_firmware_direct(&fw, firmware, dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"failed to load firmware %s, ret: %d\n", firmware, ret);
|
||||
return ret;
|
||||
}
|
||||
priv->dm_crc32 = ~crc32(~0, fw->data, fw->size);
|
||||
dev_info(dev, "%s: crc32=0x%x\n",
|
||||
firmware, ~crc32(~0, fw->data, fw->size));
|
||||
/* Download DM */
|
||||
ret = air_mdio_write_buf(phydev, 0x00000000, fw);
|
||||
release_firmware(fw);
|
||||
ret = air_mdio_write_buf(phydev, 0x00000000, EthMD32_dm_size, EthMD32_dm);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_mdio_write_buf 0x00000000 fail, ret: %d\n", ret);
|
||||
goto release;
|
||||
}
|
||||
|
||||
firmware = EN8811H_MD32_DSP;
|
||||
ret = request_firmware_direct(&fw, firmware, dev);
|
||||
if (ret < 0) {
|
||||
dev_info(dev,
|
||||
"failed to load firmware %s, ret: %d\n", firmware, ret);
|
||||
return ret;
|
||||
}
|
||||
priv->dsp_crc32 = ~crc32(~0, fw->data, fw->size);
|
||||
dev_info(dev, "%s: crc32=0x%x\n",
|
||||
firmware, ~crc32(~0, fw->data, fw->size));
|
||||
|
||||
/* Download PM */
|
||||
ret = air_mdio_write_buf(phydev, 0x00100000, fw);
|
||||
ret = air_mdio_write_buf(phydev, 0x00100000, EthMD32_pm_size, EthMD32_pm);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_mdio_write_buf 0x00100000 fail , ret: %d\n", ret);
|
||||
goto release;
|
||||
return ret;
|
||||
}
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
|
||||
pbus_value &= ~BIT(11);
|
||||
ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
|
||||
if (ret < 0)
|
||||
goto release;
|
||||
#ifdef AIR_MD32_FW_CHECK
|
||||
crc32 = ~crc32(~0, fw->data, fw->size);
|
||||
/* Check PM */
|
||||
air_mdio_read_buf(phydev, 0x100000, fw, &d_crc32);
|
||||
if (d_crc32 == crc32)
|
||||
dev_info(dev, "0x00100000 Check Sum Pass.\n");
|
||||
else {
|
||||
dev_info(dev, "0x00100000 Check Sum Fail.\n");
|
||||
dev_info(dev, "CRC32 0x%x != Caculated CRC32 0x%x\n",
|
||||
crc32, d_crc32);
|
||||
}
|
||||
release_firmware(fw);
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(100);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x0f0018);
|
||||
retry--;
|
||||
if (retry == 0) {
|
||||
dev_err(dev,
|
||||
"Release Software Reset fail , ret: %d\n",
|
||||
pbus_value);
|
||||
goto release;
|
||||
}
|
||||
} while (pbus_value != 0x1);
|
||||
dev_info(dev,
|
||||
"Release Software Reset successful.\n");
|
||||
#else
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif
|
||||
return 0;
|
||||
release:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int en8811h_init_up(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0, retry, reg_value;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
unsigned int pbus_value;
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
dev_info(dev, "%s start\n", __func__);
|
||||
ret = en8811h_load_firmware(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "EN8811H load firmware fail.\n");
|
||||
return ret;
|
||||
}
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
mdelay(300);
|
||||
reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
|
||||
if (reg_value == EN8811H_PHY_READY) {
|
||||
dev_info(dev, "EN8811H PHY ready!\n");
|
||||
priv->init_stage = AIR_INIT_FW_READY;
|
||||
break;
|
||||
}
|
||||
if (retry == 0) {
|
||||
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_err(dev,
|
||||
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
|
||||
dev_err(dev,
|
||||
"%s fail!\n", __func__);
|
||||
priv->init_stage = AIR_INIT_FW_FAIL;
|
||||
}
|
||||
} while (retry--);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -491,7 +220,6 @@ static int en8811h_led_init(struct phy_device *phydev)
|
||||
u16 cl45_data = led_dur;
|
||||
int ret = 0, id;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
ret = air_mii_cl45_write(phydev, 0x1f, LED_BLK_DUR, cl45_data);
|
||||
if (ret < 0)
|
||||
@ -527,10 +255,6 @@ static int en8811h_led_init(struct phy_device *phydev)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
priv->on_crtl[id] = air_mii_cl45_read(phydev, 0x1f,
|
||||
LED_ON_CTRL(id));
|
||||
priv->blk_crtl[id] = air_mii_cl45_read(phydev, 0x1f,
|
||||
LED_BLK_CTRL(id));
|
||||
}
|
||||
reg_value = air_buckpbus_reg_read(phydev, 0xcf8b8) | led_gpio;
|
||||
ret = air_buckpbus_reg_write(phydev, 0xcf8b8, reg_value);
|
||||
@ -540,7 +264,6 @@ static int en8811h_led_init(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
#endif /* AIR_LED_SUPPORT */
|
||||
|
||||
#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE)
|
||||
static int en8811h_get_features(struct phy_device *phydev)
|
||||
{
|
||||
@ -561,13 +284,11 @@ static int en8811h_get_features(struct phy_device *phydev)
|
||||
phydev->supported);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
||||
phydev->supported);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||
phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
|
||||
phydev->supported);
|
||||
return 0;
|
||||
}
|
||||
@ -576,11 +297,12 @@ static int en8811h_get_features(struct phy_device *phydev)
|
||||
static int en8811h_probe(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0;
|
||||
int pid1 = 0, pid2 = 0;
|
||||
u32 pbus_value = 0;
|
||||
int reg_value, pid1 = 0, pid2 = 0;
|
||||
u32 retry, pbus_value = 0;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct mii_bus *mbus = phydev_mdio_bus(phydev);
|
||||
int addr = phydev_addr(phydev);
|
||||
|
||||
struct en8811h_priv *priv;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
@ -590,30 +312,23 @@ static int en8811h_probe(struct phy_device *phydev)
|
||||
ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pid1 = air_mii_cl22_read(mbus, addr, MII_PHYSID1);
|
||||
pid2 = air_mii_cl22_read(mbus, addr, MII_PHYSID2);
|
||||
dev_info(dev, "PHY = %x - %x\n", pid1, pid2);
|
||||
if ((pid1 != EN8811H_PHY_ID1) || (pid2 != EN8811H_PHY_ID2)) {
|
||||
dev_err(dev, "EN8811H dose not exist!!\n");
|
||||
goto priv_free;
|
||||
kfree(priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv->init_stage = AIR_INIT_START;
|
||||
ret = air_buckpbus_reg_write(phydev, 0x1e00d0, 0xf);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1e0228, 0xf0);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
priv->mcu_needs_restart = false;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xcf914);
|
||||
dev_info(dev, "Bootmode: %s\n",
|
||||
(GET_BIT(pbus_value, 24) ? "Flash" : "Download Code"));
|
||||
ret = en8811h_of_init(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
ret = en8811h_load_firmware(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "EN8811H load firmware fail.\n");
|
||||
goto priv_free;
|
||||
}
|
||||
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
|
||||
ret = airphy_debugfs_init(phydev);
|
||||
if (ret < 0) {
|
||||
@ -622,68 +337,69 @@ static int en8811h_probe(struct phy_device *phydev)
|
||||
goto priv_free;
|
||||
}
|
||||
#endif /* CONFIG_AIROHA_EN8811H_PHY_DEBUGFS */
|
||||
|
||||
if (priv->phy_handle) {
|
||||
dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
} else {
|
||||
ret = en8811h_init_up(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
priv->init_stage = AIR_INIT_CONFIG;
|
||||
ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
pbus_value &= ~0x3;
|
||||
#if defined(CONFIG_OF)
|
||||
pbus_value |= priv->pol;
|
||||
#else
|
||||
pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
|
||||
#endif
|
||||
ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
|
||||
priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
|
||||
ret = air_surge_protect_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_surge_protect_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
mdelay(300);
|
||||
reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
|
||||
if (reg_value == EN8811H_PHY_READY) {
|
||||
dev_info(dev, "EN8811H PHY ready!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = air_cko_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_cko_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
#if defined(AIR_LED_SUPPORT)
|
||||
ret = en8811h_led_init(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->init_stage = AIR_INIT_SUCESS;
|
||||
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
retry--;
|
||||
} while (retry);
|
||||
if (retry == 0) {
|
||||
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_err(dev,
|
||||
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
|
||||
dev_err(dev,
|
||||
"EN8811H initialize fail!\n");
|
||||
goto priv_free;
|
||||
}
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
/* Serdes polarity */
|
||||
ret = en8811h_of_init(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
pbus_value &= ~0x3;
|
||||
#if defined(CONFIG_OF)
|
||||
pbus_value |= priv->pol;
|
||||
#else
|
||||
pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
|
||||
#endif
|
||||
ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_info(dev, "MD32 FW Version : %08x\n", pbus_value);
|
||||
if (priv->surge) {
|
||||
ret = air_surge_5ohm_config(phydev);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"air_surge_5ohm_config fail. (ret=%d)\n", ret);
|
||||
} else
|
||||
dev_info(dev, "Surge Protection Mode - 0R\n");
|
||||
#if defined(AIR_LED_SUPPORT)
|
||||
ret = en8811h_led_init(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
#endif
|
||||
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
return 0;
|
||||
priv_free:
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void en8811h_remove(struct phy_device *phydev)
|
||||
{
|
||||
|
||||
@ -700,229 +416,6 @@ void en8811h_remove(struct phy_device *phydev)
|
||||
}
|
||||
}
|
||||
|
||||
static int en8811h_restart_up(struct phy_device *phydev)
|
||||
{
|
||||
int ret, retry, reg_value;
|
||||
u32 pbus_value;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
dev_info(dev, "%s start\n", __func__);
|
||||
ret = air_mii_cl45_write(phydev, 0x1e, 0x8009, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
|
||||
EN8811H_FW_CTRL_1_START);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
|
||||
EN8811H_FW_CTRL_1_FINISH);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
retry = MAX_RETRY;
|
||||
do {
|
||||
mdelay(300);
|
||||
reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
|
||||
if (reg_value == EN8811H_PHY_READY) {
|
||||
priv->init_stage = AIR_INIT_FW_READY;
|
||||
dev_info(dev, "EN8811H PHY ready!\n");
|
||||
break;
|
||||
}
|
||||
if (retry == 0) {
|
||||
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_err(dev,
|
||||
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
|
||||
dev_err(dev,
|
||||
"%s fail!\n", __func__);
|
||||
priv->init_stage = AIR_INIT_FW_FAIL;
|
||||
}
|
||||
} while (retry--);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int en8811h_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 pbus_value = 0;
|
||||
struct device *dev = phydev_dev(phydev);
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev, 0x1e00d0, 0xf);
|
||||
ret |= air_buckpbus_reg_write(phydev, 0x1e0228, 0xf0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* If restart happened in .probe(), no need to restart now */
|
||||
if (priv->mcu_needs_restart) {
|
||||
ret = en8811h_restart_up(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
} else {
|
||||
ret = en8811h_init_up(phydev);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
/* Next calls to .config_init() mcu needs to restart */
|
||||
priv->mcu_needs_restart = true;
|
||||
}
|
||||
|
||||
priv->init_stage = AIR_INIT_CONFIG;
|
||||
ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
|
||||
ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
/* Serdes polarity */
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
pbus_value &= ~0x3;
|
||||
#if defined(CONFIG_OF)
|
||||
pbus_value |= priv->pol;
|
||||
#else
|
||||
pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
|
||||
#endif
|
||||
|
||||
ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
|
||||
if (ret < 0)
|
||||
goto priv_free;
|
||||
|
||||
pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
|
||||
dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
|
||||
priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
|
||||
dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
|
||||
|
||||
ret = air_surge_protect_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_surge_protect_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
ret = air_cko_cfg(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"air_cko_cfg fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
|
||||
#if defined(AIR_LED_SUPPORT)
|
||||
ret = en8811h_led_init(phydev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
|
||||
goto priv_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->init_stage = AIR_INIT_SUCESS;
|
||||
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
|
||||
return 0;
|
||||
|
||||
priv_free:
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
static int en8811h_get_rate_matching(struct phy_device *phydev,
|
||||
phy_interface_t iface)
|
||||
{
|
||||
return RATE_MATCH_PAUSE;
|
||||
}
|
||||
|
||||
static int en8811h_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
bool changed = false;
|
||||
int err, val;
|
||||
|
||||
val = 0;
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->advertising))
|
||||
val |= MDIO_AN_10GBT_CTRL_ADV2_5G;
|
||||
err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
|
||||
MDIO_AN_10GBT_CTRL_ADV2_5G, val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0)
|
||||
changed = true;
|
||||
|
||||
return __genphy_config_aneg(phydev, changed);
|
||||
}
|
||||
|
||||
static int en8811h_update_link(struct phy_device *phydev)
|
||||
{
|
||||
int status = 0, bmcr;
|
||||
struct mii_bus *mbus = phydev_mdio_bus(phydev);
|
||||
int addr = phydev_addr(phydev);
|
||||
|
||||
bmcr = air_mii_cl22_read(mbus, addr, MII_BMCR);
|
||||
if (bmcr < 0)
|
||||
return bmcr;
|
||||
/* Autoneg is being started, therefore disregard BMSR value and
|
||||
* report link as down.
|
||||
*/
|
||||
if (bmcr & BMCR_ANRESTART)
|
||||
goto done;
|
||||
status = air_mii_cl22_read(mbus, addr, MII_BMSR);
|
||||
if (status < 0)
|
||||
return status;
|
||||
done:
|
||||
phydev->link = status & BMSR_LSTATUS ? 1 : 0;
|
||||
phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int en8811h_read_status(struct phy_device *phydev)
|
||||
{
|
||||
struct en8811h_priv *priv = phydev->priv;
|
||||
u32 pbus_value;
|
||||
int old_link = phydev->link, ret;
|
||||
|
||||
ret = en8811h_update_link(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* why bother the PHY if nothing can have changed */
|
||||
if (old_link && phydev->link)
|
||||
return 0;
|
||||
phydev->speed = SPEED_UNKNOWN;
|
||||
phydev->duplex = DUPLEX_UNKNOWN;
|
||||
phydev->pause = 0;
|
||||
phydev->asym_pause = 0;
|
||||
phydev->rate_matching = RATE_MATCH_PAUSE;
|
||||
|
||||
ret = genphy_read_lpa(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Get link partner 2.5GBASE-T ability from vendor register */
|
||||
pbus_value = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->lp_advertising,
|
||||
pbus_value & EN8811H_2P5G_LPA_2P5G);
|
||||
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
if (phydev->autoneg_complete)
|
||||
phy_resolve_aneg_pause(phydev);
|
||||
|
||||
if (!phydev->link)
|
||||
return 0;
|
||||
|
||||
ret = air_ref_clk_speed(phydev, AIR_PARA_PHYDEV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Firmware before version 24011202 has no vendor register 2P5G_LPA.
|
||||
* Assume link partner advertised it if connected at 2500Mbps.
|
||||
*/
|
||||
if (priv->firmware_version < 0x24011202) {
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
phydev->lp_advertising,
|
||||
phydev->speed == SPEED_2500);
|
||||
}
|
||||
if (phydev->speed <= SPEED_1000)
|
||||
phydev->pause = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_driver en8811h_driver[] = {
|
||||
{
|
||||
.phy_id = EN8811H_PHY_ID,
|
||||
@ -935,12 +428,6 @@ static struct phy_driver en8811h_driver[] = {
|
||||
.read_mmd = __air_mii_cl45_read,
|
||||
.write_mmd = __air_mii_cl45_write,
|
||||
#endif
|
||||
.config_init = en8811h_config_init,
|
||||
.read_status = en8811h_read_status,
|
||||
.get_rate_matching = en8811h_get_rate_matching,
|
||||
.config_aneg = en8811h_config_aneg,
|
||||
.resume = genphy_resume,
|
||||
.suspend = genphy_suspend,
|
||||
} };
|
||||
|
||||
int __init en8811h_phy_driver_register(void)
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user