Baseline update from LYNQ_SDK_ASR_T108_V05.03.01.00(kernel build error.)
Change-Id: I56fc72cd096e82c589920026553170e5cb9692eb
diff --git a/marvell/linux/drivers/net/phy/Kconfig b/marvell/linux/drivers/net/phy/Kconfig
old mode 100644
new mode 100755
index ec7d436..65042ca
--- a/marvell/linux/drivers/net/phy/Kconfig
+++ b/marvell/linux/drivers/net/phy/Kconfig
@@ -598,3 +598,5 @@
config MICREL_KS8995MA
tristate "Micrel KS8995MA 5-ports 10/100 managed Ethernet switch"
depends on SPI
+
+source "drivers/net/phy/jlsemi/Kconfig"
\ No newline at end of file
diff --git a/marvell/linux/drivers/net/phy/Makefile b/marvell/linux/drivers/net/phy/Makefile
old mode 100644
new mode 100755
index a0caa5a..45f573e
--- a/marvell/linux/drivers/net/phy/Makefile
+++ b/marvell/linux/drivers/net/phy/Makefile
@@ -114,3 +114,4 @@
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
+obj-$(CONFIG_JLSEMI_PHY) += jlsemi/
diff --git a/marvell/linux/drivers/net/phy/jlsemi/Kconfig b/marvell/linux/drivers/net/phy/jlsemi/Kconfig
new file mode 100755
index 0000000..35db0a1
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/Kconfig
@@ -0,0 +1,6 @@
+#
+# PHY/SWITCH device configuration
+#
+config JLSEMI_PHY
+ tristate "Drivers for JLSemi Auto PHYs"
+ help
diff --git a/marvell/linux/drivers/net/phy/jlsemi/Makefile b/marvell/linux/drivers/net/phy/jlsemi/Makefile
new file mode 100755
index 0000000..662b6fe
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/Makefile
@@ -0,0 +1,2 @@
+jl31xx-y := jl3xxx.o jlapi.o
+obj-$(CONFIG_JLSEMI_PHY) += jl31xx.o
diff --git a/marvell/linux/drivers/net/phy/jlsemi/jl.h b/marvell/linux/drivers/net/phy/jlsemi/jl.h
new file mode 100755
index 0000000..df86146
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/jl.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016-2022 JLSemi Limited
+ * All Rights Reserved
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of JLSemi Limited.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ *
+ * No part of this code may be reproduced, stored in a retrieval system,
+ * or transmitted, in any form or by any means, electronic, mechanical,
+ * photocopying, recording, or otherwise, without the prior written
+ * permission of JLSemi Limited.
+ */
+
+#ifndef _JL_HXX_
+#define _JL_HXX_
+
+#include <linux/phy.h>
+
+
+#define JL3XXX_ID 0x937c4018
+#define JL3XXX_MASK 0xfffffffe
+
+#define JL3113_ID 0x937c4010
+
+typedef enum {
+ jl_slave = 0,
+ jl_master = 1,
+} jl_role;
+
+void jl_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/);
+int jl_get_link(struct phy_device *phydev);
+
+int jl3113_get_link(struct phy_device *phydev);
+void jl3113_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/);
+
+
+
+/**************** utility ***********************/
+
+enum {
+ BIT0 = 0x1,
+ BIT2 = 0x1<<2,
+ BIT3 = 0x1<<3,
+ BIT4 = 0x1<<4,
+ BIT6 = 0x1<<6,
+ BIT9 = 0x1<<9,
+ BIT11 = 0x1<<11,
+ BIT12 = 0x1<<12,
+ BIT13 = 0x1<<13,
+ BIT14 = 0x1<<14,
+ BIT15 = 0x1<<15,
+};
+
+static inline int rd(struct phy_device *phydev, u16 mmd, u16 reg) {
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, mmd);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, reg);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | mmd);
+ return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, 0x0e);
+}
+
+static inline int wt(struct phy_device *phydev, u16 mmd, u16 reg, u16 val) {
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, mmd);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, reg);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | mmd);
+ return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, val);
+}
+
+static inline int md(struct phy_device *phydev, u16 mmd, u16 reg, u16 mask, u16 val) {
+ u16 ret = rd(phydev, mmd, reg);
+ ret &= ~mask;
+ return wt(phydev, mmd, reg, ret | val);
+}
+
+
+#endif /* _JL_HXX_ */
+
diff --git a/marvell/linux/drivers/net/phy/jlsemi/jl3xxx.c b/marvell/linux/drivers/net/phy/jlsemi/jl3xxx.c
new file mode 100755
index 0000000..8bc22ba
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/jl3xxx.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2016-2022 JLSemi Limited
+ * All Rights Reserved
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of JLSemi Limited.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ *
+ * No part of this code may be reproduced, stored in a retrieval system,
+ * or transmitted, in any form or by any means, electronic, mechanical,
+ * photocopying, recording, or otherwise, without the prior written
+ * permission of JLSemi Limited.
+ */
+
+#include <linux/phy.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <asm/ptrace.h>
+#include "jl.h"
+
+
+#define DBG(fmt, ...) printk("xxx: "fmt, ##__VA_ARGS__)
+
+/* Set and/or override some configuration registers based on the
+ * lynq,jl3103 property stored in the of_node for the phydev.
+ * lynq,jl3103 = <speed master>,...;
+ * speed: 1000Mbps or 100Mbps.
+ * master: 1-master, 0-slave.
+ */
+
+/* 1 = PHY as master, 0 = PHY as slave */
+#define JL3xxx_MASTER_SLAVE_CFG BIT(14)
+/* 0 = 100BASE-T1, 1 = 1000BASE-T1 */
+#define JL3xxx_LINK_TYPE BIT(0)
+
+static int ROLE = jl_slave;
+typedef enum
+{
+ eLINK_OFF = 0,
+ eLINK_ON,
+ eLINK_END
+} E_LINK_STATE;
+static E_LINK_STATE jlphy_port_state= 0;
+
+
+module_param(ROLE, int, 0644);
+
+static inline int rd_switch(struct phy_device *phydev, u16 mmd, u16 reg) {
+ mdiobus_write(phydev->mdio.bus, 8, 0x0d, mmd);
+ mdiobus_write(phydev->mdio.bus, 8, 0x0e, reg);
+ mdiobus_write(phydev->mdio.bus, 8, 0x0d, 0x4000 | mmd);
+ return mdiobus_read(phydev->mdio.bus, 8, 0x0e);
+}
+
+static inline int wt_switch(struct phy_device *phydev, u16 mmd, u16 reg, u16 val) {
+ mdiobus_write(phydev->mdio.bus, 8, 0x0d, mmd);
+ mdiobus_write(phydev->mdio.bus, 8, 0x0e, reg);
+ mdiobus_write(phydev->mdio.bus, 8, 0x0d, 0x4000 | mmd);
+ return mdiobus_write(phydev->mdio.bus, 8, 0x0e, val);
+}
+
+static int jlphy_loopback_test(struct phy_device *phydev)
+{
+ int tmp = 0;
+
+#if 0 //��ػ�
+ tmp = rd(phydev, 1, 0);
+ tmp |= 0x0002;
+ wt(phydev, 1, 0, tmp);
+ mdelay(2);
+ /*soft reset*/
+ tmp = rd(phydev, 1, 0);
+ tmp |= 0x8000;
+ wt(phydev, 1, 0, tmp);
+#endif
+
+#if 0 //�ڻػ�
+ tmp = rd(phydev, 3, 0x8800);
+ tmp |= 0x0004;
+ wt(phydev, 3, 0x8800, tmp);
+ mdelay(2);
+ /*soft reset*/
+ tmp = rd(phydev, 1, 0);
+ tmp |= 0x8000;
+ wt(phydev, 1, 0, tmp);
+#endif
+
+#if 0 //�����ػ�
+ tmp = rd_switch(phydev, 0, 0x42);
+ tmp |= 0x0010;
+ wt_switch(phydev, 0, 0x42, tmp);
+#endif
+ return 0;
+}
+
+/********************** Interface *************************************/
+
+static int jlphy_config_aneg(struct phy_device *phydev)
+{
+ DBG("%s()\n", __func__);
+ return 0;
+}
+
+static int jlphy_aneg_done(struct phy_device *phydev)
+{
+ DBG("%s()\n", __func__);
+ return BMSR_ANEGCOMPLETE;
+}
+
+static int jlphy_soft_reset(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int jlphy_config_init(struct phy_device *phydev)
+{
+ DBG("%s(), an:= %d, if:= %d\n", __func__, phydev->autoneg, phydev->interface);
+ printk("[%s] addr:%d\n", __func__, phydev->mdio.addr);
+
+ unsigned int tmp = 0;
+ int i = 0;
+
+ while(!jl_get_link(phydev)){
+ printk("[%s] link is down\n", __func__);
+ msleep(5);
+ }
+ printk("[%s] link is up\n", __func__);
+
+ wt(phydev, 0x1f, 0x9f, 0x000d); //cl45 1f.0x9f,0xD,phyaddr 0x1f
+
+ while (0xd != rd(phydev, 0x1f, 0x9f)) {
+ wt(phydev, 0x1f, 0x9f, 0x000d);
+ mdelay(2);
+ printk("[%s] cfg 4.1f.9f failed:0x%x\n", __func__, rd(phydev, 0x1f, 0x9f));
+ }
+ printk("[%s] cfg 4.1f.9f success:0x%x\n", __func__, rd(phydev, 0x1f, 0x9f));
+
+ wt_switch(phydev, 0, 0x100, 0x01e7);
+ mdelay(2);
+
+ wt_switch(phydev, 0, 0x0, 0x7c);
+ mdelay(2000);
+
+ wt_switch(phydev, 0, 0x6e, 0x5fff);
+ mdelay(2000);
+ tmp = rd_switch(phydev, 0, 0x6e);
+ printk("[%s] cfg 8.0.6e:0x%x\n", __func__, tmp);
+
+ wt_switch(phydev, 0, 0x100, 0x01e7);
+ mdelay(2000);
+
+ return 0;
+}
+
+static int jl_get_pkt_cnt(struct phy_device *phydev)
+{
+ int tmp = 0;
+ printk("[%s] RGMII RXI:%d\n",__func__, rd_switch(phydev, 0, 0x23));
+ printk("[%s] RGMII RXO:%d\n",__func__, rd_switch(phydev, 0, 0x24));
+ printk("[%s] RGMII TXI:%d\n",__func__, rd_switch(phydev, 0, 0x25));
+ printk("[%s] RGMII TXO:%d\n",__func__, rd_switch(phydev, 0, 0x26));
+ printk("[%s] RMII RXI:%d\n",__func__, rd_switch(phydev, 0, 0x45));
+ printk("[%s] RMII RXO:%d\n",__func__, rd_switch(phydev, 0, 0x46));
+ printk("[%s] RMII TXI:%d\n",__func__, rd_switch(phydev, 0, 0x47));
+ printk("[%s] RMII TXO:%d\n",__func__, rd_switch(phydev, 0, 0x48));
+ printk("[%s] TX_PKT_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x9E));
+ printk("[%s] TX_PKT_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xA0));
+ printk("[%s] TX_PKT_UC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xA2));
+ printk("[%s] TX_PKT_UC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xA4));
+ printk("[%s] TX_PKT_MC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xA6));
+ printk("[%s] TX_PKT_MC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xA8));
+ printk("[%s] TX_PKT_BC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xAA));
+ printk("[%s] TX_PKT_BC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xAC));
+ printk("[%s] TX_PKT_DRP_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xAE));
+ printk("[%s] TX_PKT_ERR_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xAF));
+ printk("[%s] RX_PKT_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xB0));
+ printk("[%s] RX_PKT_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xB2));
+ printk("[%s] RX_PKT_UC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xB4));
+ printk("[%s] RX_PKT_UC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xB6));
+ printk("[%s] RX_PKT_MC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xB8));
+ printk("[%s] RX_PKT_MC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xBA));
+ printk("[%s] RX_PKT_BC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xBC));
+ printk("[%s] RX_PKT_BC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xBE));
+ printk("[%s] RX_PKT_DRP_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xC0));
+ printk("[%s] RX_PKT_CRC_ERR_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xC1));
+ printk("[%s] RX_PKT_FRAG_ERR_CNT:%d\n",__func__, rd_switch(phydev, 0, 0xC2));
+ printk("[%s] TX_PKT_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x136));
+ printk("[%s] TX_PKT_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x138));
+ printk("[%s] TX_PKT_UC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x13A));
+ printk("[%s] TX_PKT_UC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x13C));
+ printk("[%s] TX_PKT_MC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x13E));
+ printk("[%s] TX_PKT_MC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x140));
+ printk("[%s] TX_PKT_BC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x142));
+ printk("[%s] TX_PKT_BC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x144));
+ printk("[%s] TX_PKT_DRP_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x146));
+ printk("[%s] TX_PKT_ERR_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x147));
+ printk("[%s] RX_PKT_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x148));
+ printk("[%s] RX_PKT_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x14A));
+ printk("[%s] RX_PKT_UC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x14C));
+ printk("[%s] RX_PKT_UC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x14E));
+ printk("[%s] RX_PKT_MC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x150));
+ printk("[%s] RX_PKT_MC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x152));
+ printk("[%s] RX_PKT_BC_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x154));
+ printk("[%s] RX_PKT_BC_BYTE_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x156));
+ printk("[%s] RX_PKT_DRP_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x158));
+ printk("[%s] RX_PKT_CRC_ERR_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x159));
+ printk("[%s] RX_PKT_FRAG_ERR_CNT:%d\n",__func__, rd_switch(phydev, 0, 0x15A));
+
+ return 0;
+}
+
+
+
+static int jlphy_read_status(struct phy_device *phydev)
+{
+ static int i = 0;
+ phydev->link = jl_get_link(phydev);
+ phydev->duplex = DUPLEX_FULL;
+ phydev->pause = 0;
+ phydev->asym_pause = 0;
+
+ if ((i % 5 == 0)) {
+ printk("[%s] link:%d\n", __func__, phydev->link);
+ printk("[%s] clk config:0x%x\n", __func__, rd_switch(phydev, 0, 0));
+ printk("[%s] 4 0x1f.9f:0x%x\n", __func__, rd(phydev, 0x1f, 0x9f));
+ printk("[%s] 8 0x0.6e:0x%x\n", __func__, rd_switch(phydev, 0, 0x6e));
+ printk("[%s] 8 0x0.100:0x%x\n", __func__, rd_switch(phydev, 0, 0x100));
+ printk("[%s] 8 0x0.0:0x%x\n", __func__, rd_switch(phydev, 0, 0x0));
+ printk("[%s] 8 0x0.42:0x%x\n", __func__, rd_switch(phydev, 0, 0x42));
+ printk("[%s] 8 0x0.0x184:0x%x\n", __func__, rd_switch(phydev, 0, 0x184));
+ printk("[%s] 8 0x0.0x185:0x%x\n", __func__, rd_switch(phydev, 0, 0x185));
+ printk("[%s] 8 0x0.0x186:0x%x\n", __func__, rd_switch(phydev, 0, 0x186));
+ printk("[%s] 8 0x0.0x187:0x%x\n", __func__, rd_switch(phydev, 0, 0x187));
+ }
+ i++;
+
+ return 0;
+}
+
+static int jlphy_private_proc(struct phy_device *phydev)
+{
+ int err = 0;
+ int islink = 0;
+ int org_phy_status = 0;
+ int new_phy_status = 0;
+
+ if(phydev->mdio.bus == NULL)
+ return 0;
+
+ org_phy_status = jlphy_port_state;
+ islink = rd(phydev, 0x1, 0x1);
+ islink = (islink&0x4)?1:0;
+
+ //rtl8306e_port_phyLinkStatus_get(i,&islink);
+ jlphy_port_state = islink;
+ if(islink == 1)
+ new_phy_status = 1;
+
+ if((org_phy_status == 0)&&(new_phy_status == 1)) {
+ wt(phydev, 0x1f, 0x9f, 0xd);//for jl3133
+ }
+
+ if((org_phy_status == 1)&&(new_phy_status == 0))
+ return err;
+
+ return 0;
+}
+
+
+static int jl3_aneg_done(struct phy_device *phydev)
+{
+ DBG("%s()\n", __func__);
+ return BMSR_ANEGCOMPLETE;
+}
+
+
+static int jl3_config_aneg(struct phy_device *phydev)
+{
+ DBG("%s()\n", __func__);
+ return 0;
+}
+
+
+static int jl3_soft_reset(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int jl3_read_status(struct phy_device *phydev)
+{
+ int i = 0;
+ phydev->link = jl3113_get_link(phydev);
+ phydev->duplex = DUPLEX_FULL;
+ phydev->pause = 0;
+ phydev->asym_pause = 0;
+
+ if ((i % 5 == 0)) {
+ printk("[%s] link:%d\n", __func__, phydev->link);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x3);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0x8000);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x3);
+ printk("[%s] rmii config:0x%x\n", __func__, mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, 0x0e));
+
+ }
+ i++;
+
+ return 0;
+}
+
+static int jl3_config_init(struct phy_device *phydev)
+{
+ const __be32 *paddr;
+ u32 speed;
+ u32 master;
+ int val = 0, len;
+
+ DBG("%s(), an:= %d, if:= %d\n", __func__, phydev->autoneg, phydev->interface);
+ printk("[%s] addr:%d\n", __func__, phydev->mdio.addr);
+// jl3113_config_init(phydev, ROLE, SPEED_1000);
+
+ paddr = of_get_property(phydev->mdio.dev.of_node,
+ "lynq,jl3103", &len);
+ if (!paddr)
+ return 0;
+
+ speed = be32_to_cpup(paddr);
+ master = be32_to_cpup(paddr + 1);
+ val = rd(phydev, 0x1, 0x834);
+ if (val < 0)
+ return val;
+ printk("[%s] speed = %u, master = %u, val = 0x%x", __func__, speed, master, val);
+ val &= ~(JL3xxx_MASTER_SLAVE_CFG | JL3xxx_LINK_TYPE);
+ if (speed == SPEED_1000)
+ val |= JL3xxx_LINK_TYPE;
+ if (master)
+ val |= JL3xxx_MASTER_SLAVE_CFG;
+ printk("[%s]: set val = 0x%x", __func__, val);
+ wt(phydev, 0x1, 0x834, val);//set slave/master, 100M/1000M
+
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x3);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0x8000);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x3);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0x40);
+ msleep(2);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0x0000);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0xA000);
+
+ if(phydev->autoneg != 0)
+ return 0;
+ //*
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x3);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0x8800);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x3);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0xcc30);
+ msleep(2);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0x0000);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 0xA000);
+ //*/
+ return 0;
+}
+
+static int jl3_private_proc(struct phy_device *phydev)
+{
+ int err = 0;
+ int islink = 0;
+ int org_phy_status = 0;
+ int new_phy_status = 0;
+
+ if(phydev->mdio.bus == NULL)
+ return 0;
+
+ org_phy_status = jlphy_port_state;
+ islink = rd(phydev, 0x1, 0x1);
+ islink = (islink&0x4)?1:0;
+
+ //rtl8306e_port_phyLinkStatus_get(i,&islink);
+ jlphy_port_state = islink;
+ if(islink == 1)
+ new_phy_status = 1;
+
+ if((org_phy_status == 0)&&(new_phy_status == 1)) {
+ wt(phydev, 0x3, 0x8000, 0x40);
+ wt(phydev, 0x1, 0x0000, 0xA000);
+ }
+
+
+ if((org_phy_status == 1)&&(new_phy_status == 0))
+ return err;
+
+ return 0;
+}
+
+
+static struct phy_driver s_phy_drvs[] = {
+ {/* jl3133 */
+ .phy_id = JL3XXX_ID,
+ .phy_id_mask = JL3XXX_MASK,
+ .name = "JlSemi 3113",
+
+// .features = SUPPORTED_Autoneg | SUPPORTED_TP,
+ .read_status = jlphy_read_status,
+
+ .soft_reset = jlphy_soft_reset,
+ .config_init = jlphy_config_init,
+
+ .config_aneg = jlphy_config_aneg,
+ .aneg_done = jlphy_aneg_done,
+ .private_proc = jlphy_private_proc,
+ },
+ {/* jl3103 */
+ .phy_id = JL3113_ID,
+ .phy_id_mask = JL3XXX_MASK,
+ .name = "Jl3103 Auto Ethernet",
+
+//#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE)
+// .features = SUPPORTED_Autoneg | SUPPORTED_TP,
+//#else
+// .features = PHY_GBIT_FEATURES,
+//#endif
+ .read_status = jl3_read_status,
+ .soft_reset = jl3_soft_reset,
+ .config_init = jl3_config_init,
+ .config_aneg = jl3_config_aneg,
+ .aneg_done = jl3_aneg_done,
+// .private_proc = jl3_private_proc,
+
+ },
+};
+
+module_phy_driver(s_phy_drvs);
+
+static struct mdio_device_id __maybe_unused s_phy_tbl[] = {
+ { JL3XXX_ID, JL3XXX_MASK },
+ { JL3113_ID, JL3XXX_MASK },
+ { },
+};
+
+MODULE_DEVICE_TABLE(mdio, s_phy_tbl);
+
+MODULE_DESCRIPTION("JLSemi Automotive PHY driver");
+MODULE_LICENSE("GPL");
+
diff --git a/marvell/linux/drivers/net/phy/jlsemi/jlapi.c b/marvell/linux/drivers/net/phy/jlsemi/jlapi.c
new file mode 100755
index 0000000..395b0ab
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/jlapi.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016-2022 JLSemi Limited
+ * All Rights Reserved
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of JLSemi Limited.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ *
+ * No part of this code may be reproduced, stored in a retrieval system,
+ * or transmitted, in any form or by any means, electronic, mechanical,
+ * photocopying, recording, or otherwise, without the prior written
+ * permission of JLSemi Limited.
+ */
+
+#include <linux/delay.h>
+#include "jl.h"
+
+
+typedef enum { SGMII, RGMII } pcs_mode;
+
+static inline pcs_mode get_mode(struct phy_device *phydev) {
+ /* return (0x6 == rd(phydev, 0x1f, 0x60e)) ? RGMII : SGMII; */
+ return (phydev->interface == PHY_INTERFACE_MODE_SGMII) ? SGMII : RGMII;
+}
+
+static bool set_master(struct phy_device *phydev, const jl_role role)
+{
+ int ret = rd(phydev, 1, 0x834);
+ const int old = ret;
+
+ if (role == jl_master)
+ ret |= BIT14;
+ else
+ ret &= ~BIT14;
+
+ if (old == ret)
+ return false;
+
+ wt(phydev, 1, 0x834, ret);
+ return true;
+}
+
+static bool set_speed(struct phy_device *phydev)
+{
+ int ret = rd(phydev, 1, 0);
+ const int old = ret;
+
+ ret &= ~(BIT13|BIT6);
+ if (phydev->speed == SPEED_1000)
+ ret |= BIT6;
+ else
+ ret |= BIT13;
+
+ if (old == ret)
+ return false;
+
+ wt(phydev, 1, 0, ret);
+ return true;
+}
+
+static void do_reset(struct phy_device *phydev)
+{
+ md(phydev, 1, 0, BIT15, BIT15);
+ while (rd(phydev, 1, 0) & BIT15)
+ msleep(1);
+
+ printk("[%s] success\n", __func__);
+}
+
+static bool set_pcs_rgmii(struct phy_device *phydev, pcs_mode mode)
+{
+ int ret, old;
+
+ if (mode != RGMII)
+ return false;
+
+ /* [11:10] 1.0/1.2/1.5/1.8ns */
+ ret = rd(phydev, 3, 0x8800);
+ old = ret;
+
+ ret &= ~(BIT14|BIT15);
+ switch(phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ret |= BIT14|BIT15;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ ret |= BIT14;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ret |= BIT15;
+ break;
+ default:
+ break;
+ }
+
+ if (old == ret)
+ return false;
+
+ wt(phydev, 3, 0x8800, ret);
+ return true;
+}
+
+static void set_pcs_sgmii(struct phy_device *phydev, pcs_mode mode)
+{
+ u16 ret;
+
+ if (mode != SGMII)
+ return;
+
+ ret = rd(phydev, 3, 0x8000);
+ if ((ret & 0xf) == 0x1)
+ return;
+
+ wt(phydev, 3, 0x8000, ret & 0xfff1);
+}
+
+
+/********************************** API *********************************************/
+
+int jl_get_link(struct phy_device *phydev)
+{
+// return !!(rd(phydev, 0x03, 0x901) & BIT2);
+ return !!(rd(phydev, 0x01, 0x1) & BIT2);
+}
+
+
+/*
+ * phy_device
+ * speed
+ * interface
+ */
+void jl_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/)
+{
+ bool changed = false;
+ const pcs_mode mode = get_mode(phydev);
+
+ /* fill speed first */
+ phydev->speed = speed;
+
+ changed |= set_master(phydev, role);
+ changed |= set_speed(phydev);
+ changed |= set_pcs_rgmii(phydev, mode);
+
+ if (changed)
+ do_reset(phydev);
+
+ set_pcs_sgmii(phydev, mode);
+}
+
+/********************************** jl3103 API *********************************************/
+int jl3113_get_link(struct phy_device *phydev)
+{
+ int tmp = 0;
+
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x1);
+ tmp = mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, 0x0e);
+ return !!(tmp & BIT2 );
+
+}
+
+void jl3113_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/)
+{
+#if 0
+ bool changed = false;
+ const pcs_mode mode = get_mode(phydev);
+
+ /* fill speed first */
+ phydev->speed = speed;
+
+ if (do_patch(phydev, mode))
+ do_reset(phydev);
+
+ changed |= set_master(phydev, role);
+ changed |= set_speed(phydev);
+ changed |= (mode == SGMII) ? set_sgmii(phydev) : set_rgmii(phydev);
+
+ if (changed)
+ do_reset(phydev);
+#endif
+}
+
+
diff --git a/marvell/linux/drivers/net/phy/jlsemi/jlsemi/Makefile b/marvell/linux/drivers/net/phy/jlsemi/jlsemi/Makefile
new file mode 100755
index 0000000..4af0aa3
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/jlsemi/Makefile
@@ -0,0 +1,2 @@
+jl31xx-y += jlapi.o
+#obj-$(CONFIG_JLSEMI_PHY) += jlapi.o
diff --git a/marvell/linux/drivers/net/phy/jlsemi/jlsemi/jl.h b/marvell/linux/drivers/net/phy/jlsemi/jlsemi/jl.h
new file mode 100755
index 0000000..df86146
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/jlsemi/jl.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016-2022 JLSemi Limited
+ * All Rights Reserved
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of JLSemi Limited.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ *
+ * No part of this code may be reproduced, stored in a retrieval system,
+ * or transmitted, in any form or by any means, electronic, mechanical,
+ * photocopying, recording, or otherwise, without the prior written
+ * permission of JLSemi Limited.
+ */
+
+#ifndef _JL_HXX_
+#define _JL_HXX_
+
+#include <linux/phy.h>
+
+
+#define JL3XXX_ID 0x937c4018
+#define JL3XXX_MASK 0xfffffffe
+
+#define JL3113_ID 0x937c4010
+
+typedef enum {
+ jl_slave = 0,
+ jl_master = 1,
+} jl_role;
+
+void jl_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/);
+int jl_get_link(struct phy_device *phydev);
+
+int jl3113_get_link(struct phy_device *phydev);
+void jl3113_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/);
+
+
+
+/**************** utility ***********************/
+
+enum {
+ BIT0 = 0x1,
+ BIT2 = 0x1<<2,
+ BIT3 = 0x1<<3,
+ BIT4 = 0x1<<4,
+ BIT6 = 0x1<<6,
+ BIT9 = 0x1<<9,
+ BIT11 = 0x1<<11,
+ BIT12 = 0x1<<12,
+ BIT13 = 0x1<<13,
+ BIT14 = 0x1<<14,
+ BIT15 = 0x1<<15,
+};
+
+static inline int rd(struct phy_device *phydev, u16 mmd, u16 reg) {
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, mmd);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, reg);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | mmd);
+ return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, 0x0e);
+}
+
+static inline int wt(struct phy_device *phydev, u16 mmd, u16 reg, u16 val) {
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, mmd);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, reg);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | mmd);
+ return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, val);
+}
+
+static inline int md(struct phy_device *phydev, u16 mmd, u16 reg, u16 mask, u16 val) {
+ u16 ret = rd(phydev, mmd, reg);
+ ret &= ~mask;
+ return wt(phydev, mmd, reg, ret | val);
+}
+
+
+#endif /* _JL_HXX_ */
+
diff --git a/marvell/linux/drivers/net/phy/jlsemi/jlsemi/jlapi.c b/marvell/linux/drivers/net/phy/jlsemi/jlsemi/jlapi.c
new file mode 100755
index 0000000..1da6846
--- /dev/null
+++ b/marvell/linux/drivers/net/phy/jlsemi/jlsemi/jlapi.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016-2022 JLSemi Limited
+ * All Rights Reserved
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of JLSemi Limited.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ *
+ * No part of this code may be reproduced, stored in a retrieval system,
+ * or transmitted, in any form or by any means, electronic, mechanical,
+ * photocopying, recording, or otherwise, without the prior written
+ * permission of JLSemi Limited.
+ */
+
+#include <linux/delay.h>
+#include "jl.h"
+
+
+typedef enum { SGMII, RGMII } pcs_mode;
+
+static inline pcs_mode get_mode(struct phy_device *phydev) {
+ /* return (0x6 == rd(phydev, 0x1f, 0x60e)) ? RGMII : SGMII; */
+ return (phydev->interface == PHY_INTERFACE_MODE_SGMII) ? SGMII : RGMII;
+}
+
+static bool set_master(struct phy_device *phydev, const jl_role role)
+{
+ int ret = rd(phydev, 1, 0x834);
+ const int old = ret;
+
+ if (role == jl_master)
+ ret |= BIT14;
+ else
+ ret &= ~BIT14;
+
+ if (old == ret)
+ return false;
+
+ wt(phydev, 1, 0x834, ret);
+ return true;
+}
+
+static bool set_speed(struct phy_device *phydev)
+{
+ int ret = rd(phydev, 1, 0);
+ const int old = ret;
+
+ ret &= ~(BIT13|BIT6);
+ if (phydev->speed == SPEED_1000)
+ ret |= BIT6;
+ else
+ ret |= BIT13;
+
+ if (old == ret)
+ return false;
+
+ wt(phydev, 1, 0, ret);
+ return true;
+}
+
+static void do_reset(struct phy_device *phydev)
+{
+ md(phydev, 1, 0, BIT15, BIT15);
+ while (rd(phydev, 1, 0) & BIT15)
+ msleep(1);
+
+ printk("[%s] success\n", __func__);
+}
+
+static bool set_pcs_rgmii(struct phy_device *phydev, pcs_mode mode)
+{
+ int ret, old;
+
+ if (mode != RGMII)
+ return false;
+
+ /* [11:10] 1.0/1.2/1.5/1.8ns */
+ ret = rd(phydev, 3, 0x8800);
+ old = ret;
+
+ ret &= ~(BIT14|BIT15);
+ switch(phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ret |= BIT14|BIT15;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ ret |= BIT14;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ret |= BIT15;
+ break;
+ default:
+ break;
+ }
+
+ if (old == ret)
+ return false;
+
+ wt(phydev, 3, 0x8800, ret);
+ return true;
+}
+
+static void set_pcs_sgmii(struct phy_device *phydev, pcs_mode mode)
+{
+ u16 ret;
+
+ if (mode != SGMII)
+ return;
+
+ ret = rd(phydev, 3, 0x8000);
+ if ((ret & 0xf) == 0x1)
+ return;
+
+ wt(phydev, 3, 0x8000, ret & 0xfff1);
+}
+
+
+/********************************** API *********************************************/
+
+int jl_get_link(struct phy_device *phydev)
+{
+// return !!(rd(phydev, 0x03, 0x901) & BIT2);
+ return !!(rd(phydev, 0x01, 0x1) & BIT2);
+}
+
+
+/*
+ * phy_device
+ * speed
+ * interface
+ */
+void jl_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/)
+{
+ bool changed = false;
+ const pcs_mode mode = get_mode(phydev);
+
+ /* fill speed first */
+ phydev->speed = speed;
+
+ changed |= set_master(phydev, role);
+ changed |= set_speed(phydev);
+ changed |= set_pcs_rgmii(phydev, mode);
+
+ if (changed)
+ do_reset(phydev);
+
+ set_pcs_sgmii(phydev, mode);
+}
+
+/********************************** jl3103 API *********************************************/
+int jl3113_get_link(struct phy_device *phydev)
+{
+ int tmp = 0;
+
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0e, 1);
+ mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 0x0d, 0x4000 | 0x1);
+ tmp = mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, 0x0e);
+ return !!(tmp & BIT2 );
+}
+
+void jl3113_config_init(struct phy_device *phydev, jl_role role, int speed/*SPEED_100*/)
+{
+#if 0
+ bool changed = false;
+ const pcs_mode mode = get_mode(phydev);
+
+ /* fill speed first */
+ phydev->speed = speed;
+
+ if (do_patch(phydev, mode))
+ do_reset(phydev);
+
+ changed |= set_master(phydev, role);
+ changed |= set_speed(phydev);
+ changed |= (mode == SGMII) ? set_sgmii(phydev) : set_rgmii(phydev);
+
+ if (changed)
+ do_reset(phydev);
+#endif
+}
+
+
diff --git a/marvell/linux/drivers/net/phy/phy.c b/marvell/linux/drivers/net/phy/phy.c
old mode 100644
new mode 100755
index e223f0d..7734f50
--- a/marvell/linux/drivers/net/phy/phy.c
+++ b/marvell/linux/drivers/net/phy/phy.c
@@ -394,6 +394,77 @@
}
EXPORT_SYMBOL(phy_ethtool_ksettings_get);
+/********************************************************************
+* @brief: jl3103_mmd_set, The phy chip jl3103 is dedicated to implementing devad selection
+* @param regnum [IN]: u32, The reg and devad values passed in by the application layer
+* @param regnum [OUT]: u32, The reg value of the outgoing write
+* @return : success 0x1/0x3/0x1f, failed 0
+* @todo: NA
+* @see: NA
+* @warning: NA
+*********************************************************************/
+static int jl3103_mmd_set(u32 *regnum)
+{
+ int mmd = 0;
+ if(*regnum & BIT(12)){
+ *regnum = *regnum & (~BIT(12));
+ mmd = 0x3;
+ }
+ else if(*regnum & BIT(14)){
+ *regnum = *regnum & (~BIT(14));
+ mmd = 0x1f;
+ }
+ else{
+ mmd = 0x1;
+ }
+ return mmd;
+}
+
+/********************************************************************
+* @brief: jl3103_read_phy, Read the phy address of jl3103
+* @param bus [IN]: struct mii_bus, The bus address passed to mdio
+* @param addr [IN]: int, Pass in the addr address of mdio
+* @param regnum [IN]: u32, Pass in the phy register address
+* @return : success all, failed null
+* @todo: NA
+* @see: NA
+* @warning: NA
+*********************************************************************/
+static int jl3103_read_phy(struct mii_bus *bus, int addr, u32 regnum)
+{
+ int val = 0;
+ int mmd = jl3103_mmd_set(®num);
+ int reg = regnum;
+ mdiobus_write(bus, addr, 0x0d, mmd);
+ mdiobus_write(bus, addr, 0x0e, reg);
+ mdiobus_write(bus, addr, 0x0d, 0x4000 | mmd);
+ val = mdiobus_read(bus, addr, 0x0e);
+ return val;
+}
+
+/********************************************************************
+* @brief: jl3103_write_phy, Write the phy address of jl3103
+* @param bus [IN]: struct mii_bus, The bus address passed to mdio
+* @param addr [IN]: int, Pass in the addr address of mdio
+* @param regnum [IN]: u32, Pass in the phy register address
+* @param val [IN]: u16, Pass in the phy register address
+* @return : success 0, failed !0
+* @todo: NA
+* @see: NA
+* @warning: NA
+*********************************************************************/
+static int jl3103_write_phy(struct mii_bus *bus, int addr, u32 regnum, u16 val)
+{
+ int mmd = jl3103_mmd_set(®num);
+ int reg = regnum;
+ int err = 0;
+ mdiobus_write(bus, addr, 0x0d, mmd);
+ mdiobus_write(bus, addr, 0x0e, reg);
+ mdiobus_write(bus, addr, 0x0d, 0x4000 | mmd);
+ err = mdiobus_write(bus, addr, 0x0e, val);
+ return err;
+}
+
/**
* phy_mii_ioctl - generic PHY MII ioctl interface
* @phydev: the phy_device struct
@@ -424,6 +495,10 @@
} else {
prtad = mii_data->phy_id;
devad = mii_data->reg_num;
+ ///--Added read JL3103 register
+ mii_data->val_out = jl3103_read_phy(phydev->mdio.bus, prtad,
+ devad);
+ return 0;
}
mii_data->val_out = mdiobus_read(phydev->mdio.bus, prtad,
devad);
@@ -477,7 +552,12 @@
}
}
- mdiobus_write(phydev->mdio.bus, prtad, devad, val);
+ ///--Add write JL3103 register
+ if (mdio_phy_id_is_c45(mii_data->phy_id)) {
+ mdiobus_write(phydev->mdio.bus, prtad, devad, val);
+ } else {
+ jl3103_write_phy(phydev->mdio.bus, prtad, devad, val);
+ }
if (prtad == phydev->mdio.addr &&
devad == MII_BMCR &&
@@ -964,8 +1044,11 @@
old_state = phydev->state;
- if (phydev->sfp_bus)
- sfp_upstream_start(phydev->sfp_bus);
+ /* if (phydev->adjust_state)
+ phydev->adjust_state(phydev->attached_dev); */
+
+ if ((phydev->drv)&&(phydev->drv->private_proc))
+ phydev->drv->private_proc(phydev);
switch (phydev->state) {
case PHY_DOWN:
diff --git a/marvell/linux/drivers/net/phy/phy_device.c b/marvell/linux/drivers/net/phy/phy_device.c
old mode 100644
new mode 100755
index 76a68bb..bfc2e14
--- a/marvell/linux/drivers/net/phy/phy_device.c
+++ b/marvell/linux/drivers/net/phy/phy_device.c
@@ -809,6 +809,68 @@
}
/**
+ * get_phy_c22_id - reads the specified addr for its clause 22 ID.
+ * @bus: the target MII bus
+ * @addr: PHY address on the MII bus
+ * @phy_id: where to store the ID retrieved.
+ *
+ * Read the 802.3 clause 22 PHY ID from the PHY at @addr on the @bus,
+ * placing it in @phy_id. Return zero on successful read and the ID is
+ * valid, %-EIO on bus access error, or %-ENODEV if no device responds
+ * or invalid ID.
+ */
+
+static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
+{
+ int phy_reg;
+
+ /* Grab the bits from PHYIR1, and put them in the upper half */
+// phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
+#ifdef CONFIG_JLSEMI_PHY
+ mdiobus_write(bus, addr, 0x0d, 1);
+ mdiobus_write(bus, addr, 0x0e, 2);
+ mdiobus_write(bus, addr, 0x0d, 0x4000 | 1);
+ phy_reg = mdiobus_read(bus, addr, 0x0e);
+#else
+ phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
+#endif
+ if (phy_reg < 0) {
+ /* returning -ENODEV doesn't stop bus scanning */
+ return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
+ }
+
+ *phy_id = phy_reg << 16;
+
+ /* Grab the bits from PHYIR2, and put them in the lower half */
+// phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
+#ifdef CONFIG_JLSEMI_PHY
+ mdiobus_write(bus, addr, 0x0d, 1);
+ mdiobus_write(bus, addr, 0x0e, 3);
+ mdiobus_write(bus, addr, 0x0d, 0x4000 | 1);
+ phy_reg = mdiobus_read(bus, addr, 0x0e);
+#else
+ phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
+#endif
+ if (phy_reg < 0) {
+ /* returning -ENODEV doesn't stop bus scanning */
+ return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
+ }
+
+ *phy_id |= phy_reg;
+
+#ifdef CONFIG_JLSEMI_PHY
+ printk("[%s] read with c45 phy id:0x%x addr:0x%x\n", __func__, *phy_id, addr);
+#else
+ printk("[%s] read with c22 phy id:0x%x\n", __func__, *phy_id);
+#endif
+ /* If the phy_id is mostly Fs, there is no device there */
+ if ((*phy_id & 0x1fffffff) == 0x1fffffff)
+ return -ENODEV;
+
+ return 0;
+}
+
+/**
* get_phy_device - reads the specified PHY device and returns its @phy_device
* struct
* @bus: the target MII bus
@@ -827,7 +889,8 @@
c45_ids.devices_in_package = 0;
memset(c45_ids.device_ids, 0xff, sizeof(c45_ids.device_ids));
- r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);
+ //r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);
+ r = get_phy_c22_id(bus, addr, &phy_id);
if (r)
return ERR_PTR(r);