ipq807x: CIG WF186w: support port and autoNego setting from user space

Fixes: WIFI-12963
Signed-off-by: Ken <xshi@actiontec.com>
This commit is contained in:
Ken
2023-09-28 14:17:55 +08:00
committed by John Crispin
parent 4cdb20fea4
commit 3c868746a0

View File

@@ -548,7 +548,7 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
===================================================================
--- /dev/null
+++ linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/phy/rtl8367c.c
@@ -0,0 +1,2462 @@
@@ -0,0 +1,2976 @@
+/*
+ * Platform driver for the Realtek RTL8367R-VB/S/C ethernet switches
+ *
@@ -568,6 +568,14 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/rtl8367.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <linux/pm.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+
+
+#include "rtl8366_smi.h"
+
@@ -845,6 +853,84 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+
+#define RTL8367S_DW8051_EN_OFFSET 5
+#define SGMII_INIT_SIZE 1223
+
+/*****/
+#define RTL8367S_REG_SPEED_SELECTION_LOW_OFFSET 13
+#define RTL8367S_REG_AUTO_NEGO_EN_OFFSET 12
+#define RTL8367S_REG_POWER_DOWN_OFFSET 11
+#define RTL8367S_REG_RESTART_AUTO_NEGO_OFFSET 9
+#define RTL8367S_REG_DUPLEX_MODE_OFFSET 8
+#define RTL8367S_REG_SPEED_SELECTION_HIGH_OFFSET 6
+#define RTL8367S_SET_BIT(x,bit) (x |= (1<<bit))
+#define RTL8367S_CLEAR_BIT(x,bit) (x &= ~(1<<bit))
+#define RTL8367S_DATA_INIT 0x1140
+#define RTL8367S_CHECK_BIT(x,bit) ((x>>bit)&0x1)
+
+#define PHY_CONTROL_REG 0
+#define PHY_STATUS_REG 1
+#define RTL8367C_REGBITLENGTH 16
+#define RTL8367C_REG_PHY_AD 0x130f
+#define RTL8367C_PDNPHY_OFFSET 5
+#define MDC_MDIO_PHY_ID 0x1d /* PHY ID 0 or 29 */
+#define MDC_MDIO_CTRL0_REG 0x1f
+#define MDC_MDIO_ADDR_OP 0x000E
+#define MDC_MDIO_ADDRESS_REG 0x17
+#define MDC_MDIO_DATA_WRITE_REG 0x18
+#define MDC_MDIO_CTRL1_REG 0x15
+#define MDC_MDIO_WRITE_OP 0x0003
+#define MDC_MDIO_READ_OP 0x0001
+#define MDC_MDIO_DATA_READ_REG 0x19
+#ifdef MDIO_12_5_MHZ
+#define CTRL_0_REG_C45_DEFAULT_VALUE 0x15107
+#else
+#define CTRL_0_REG_C45_DEFAULT_VALUE 0x151FF
+#endif
+#define IPQ_MDIO_BASE 0x90000
+#define MDIO_CTRL_0_REG 0x40
+#define MDIO_CTRL_1_REG 0x44
+#define MDIO_CTRL_2_REG 0x48
+#define MDIO_CTRL_3_REG 0x4c
+#define MDIO_CTRL_4_REG 0x50
+#define MDIO_CTRL_4_ACCESS_BUSY (1 << 16)
+#define MDIO_CTRL_4_ACCESS_START (1 << 8)
+#define MDIO_CTRL_4_ACCESS_CODE_READ 0
+#define MDIO_CTRL_4_ACCESS_CODE_WRITE 1
+#define MDIO_CTRL_4_ACCESS_CODE_C45_ADDR 0
+#define MDIO_CTRL_4_ACCESS_CODE_C45_WRITE 1
+#define MDIO_CTRL_4_ACCESS_CODE_C45_READ 2
+#define CTRL_0_REG_DEFAULT_VALUE 0x150FF
+#define MDIO_CTRL_4_ACCESS_BUSY (1 << 16)
+#define IPQ_MDIO_RETRY 1000
+#define IPQ_MDIO_DELAY 5
+#define RTL8367C_REG_GPHY_OCP_MSB_0 0x1d15
+#define RTL8367C_CFG_CPU_OCPADR_MSB_MASK 0xFC0
+#define RTL8367C_PHY_BASE 0x2000
+#define RTL8367C_PHY_EXT_BASE 0xA000
+#define RTL8367C_REGDATAMAX 0xFFFF
+#define RTL8367C_PHY_OFFSET 5
+#define RTL8367C_PHY_REGNOMAX 0x1F
+
+typedef enum rt_error_code_e
+{
+ RT_ERR_FAILED = -1, /* General Error */
+ /* 0x0000xxxx for common error code */
+ RT_ERR_OK = 0, /* 0x00000000, OK */
+ RT_ERR_INPUT, /* 0x00000001, invalid input parameter */
+ RT_ERR_UNIT_ID, /* 0x00000002, invalid unit id */
+ RT_ERR_PORT_ID, /* 0x00000003, invalid port id */
+ RT_ERR_PORT_MASK, /* 0x00000004, invalid port mask */
+ RT_ERR_PORT_LINKDOWN, /* 0x00000005, link down port status */
+ RT_ERR_ENTRY_INDEX, /* 0x00000006, invalid entry index */
+ RT_ERR_NULL_POINTER, /* 0x00000007, input parameter is null pointer */
+ RT_ERR_QUEUE_ID, /* 0x00000008, invalid queue id */
+ RT_ERR_QUEUE_NUM, /* 0x00000009, invalid queue number */
+ RT_ERR_BUSYWAIT_TIMEOUT, /* 0x0000000a, busy watting time out */
+ RT_ERR_MAC, /* 0x0000000b, invalid mac address */
+ RT_ERR_OUT_OF_RANGE, /* 0x0000000c, input parameter out of range */
+ RT_ERR_PHY_REG_ID, /* 0x000e0001, invalid PHY reg id*/
+ RT_ERR_SMI, /* 0x0000000e, SMI error */
+};
+
+u8 Sgmii_Init[SGMII_INIT_SIZE] = {
+0x02,0x03,0xA9,0xE4,0xF5,0xA8,
+0xD2,0xAF,0x22,0x00,0x00,0x02,0x04,0x35,
@@ -1235,6 +1321,7 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+0x00,0x00,0x42,0x06,0x31,0x00,0x00,0x00,
+0xE4,0xF5,0x8E,0x22};
+
+static int rtl8367c_setAsicReg(struct rtl8366_smi *smi,u32 reg, u32 value);
+
+struct rtl8367b_initval {
+ u16 reg;
@@ -2159,7 +2246,423 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+ return 0;
+}
+
+static int rtl8367c_setAsicReg(struct rtl8366_smi *smi, u32 reg, u32 value)
+{
+
+ int err;
+
+ REG_WR(smi, reg, value);
+ if(err != RT_ERR_OK)
+ return RT_ERR_SMI;
+
+ return RT_ERR_OK;
+}
+
+static int rtl8367c_getAsicReg(struct rtl8366_smi *smi, u32 reg, u32 *pValue)
+{
+ u32 regData;
+ int err;
+
+ REG_RD(smi, reg, &regData);
+ if(err != RT_ERR_OK)
+ return RT_ERR_SMI;
+
+ *pValue = regData;
+
+ return RT_ERR_OK;
+}
+
+static int rtl8367c_setAsicRegBits(struct rtl8366_smi *smi, u32 reg, u32 bits, u32 value)
+{
+ u32 regData;
+ int err;
+ u32 bitsShift;
+ u32 valueShifted;
+
+ if(bits >= (1 << RTL8367C_REGBITLENGTH) )
+ return RT_ERR_INPUT;
+
+ bitsShift = 0;
+ while(!(bits & (1 << bitsShift)))
+ {
+ bitsShift++;
+ if(bitsShift >= RTL8367C_REGBITLENGTH)
+ return RT_ERR_INPUT;
+ }
+ valueShifted = value << bitsShift;
+
+ if(valueShifted > RTL8367C_REGDATAMAX)
+ return RT_ERR_INPUT;
+ REG_RD(smi, reg, &regData);
+ if(err != RT_ERR_OK)
+ return RT_ERR_SMI;
+ regData = regData & (~bits);
+ regData = regData | (valueShifted & bits);
+ REG_WR(smi, reg, regData);
+ if(err != RT_ERR_OK)
+ return RT_ERR_SMI;
+
+ return RT_ERR_OK;
+}
+
+static int rtl8367c_getAsicPHYOCPReg(struct rtl8366_smi *smi, int phyNo, u32 ocpAddr, u32 *pRegData)
+{
+ int retVal;
+ u32 regAddr;
+ u32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
+
+ /* OCP prefix */
+ ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
+ retVal = rtl8367c_setAsicRegBits(smi, RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix);
+ if(retVal != RT_ERR_OK)
+ return retVal;
+
+ /*prepare access address*/
+ ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
+ ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
+ regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
+ retVal = rtl8367c_getAsicReg(smi, regAddr, pRegData);
+ if(retVal != RT_ERR_OK)
+ return retVal;
+
+ return RT_ERR_OK;
+
+
+}
+
+static int rtl8367c_setAsicPHYOCPReg(struct rtl8366_smi *smi, int phyNo, u32 ocpAddr, u32 ocpData )
+{
+ int retVal;
+ u32 regAddr;
+ u32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
+
+ /* OCP prefix */
+ ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
+ if((retVal = rtl8367c_setAsicRegBits(smi, RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
+ return retVal;
+
+ /*prepare access address*/
+ ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
+ ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
+ regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
+ if((retVal = rtl8367c_setAsicReg(smi, regAddr, ocpData)) != RT_ERR_OK)
+ return retVal;
+
+ return RT_ERR_OK;
+}
+
+static u16 rtl8367c_getAsicPHYReg(struct rtl8366_smi *smi, int phyNo, u32 phyAddr, u32 *pRegData )
+{
+ u32 ocp_addr;
+
+ ocp_addr = 0xa400 + phyAddr*2;
+
+ return rtl8367c_getAsicPHYOCPReg(smi, phyNo, ocp_addr, pRegData);
+}
+
+static u32 rtl8367c_setAsicPHYReg(struct rtl8366_smi *smi, int phyNo, u32 phyAddr, u32 phyData )
+{
+ u32 ocp_addr;
+
+ if(phyAddr > RTL8367C_PHY_REGNOMAX)
+ return RT_ERR_PHY_REG_ID;
+
+ ocp_addr = 0xa400 + phyAddr*2;
+
+ return rtl8367c_setAsicPHYOCPReg(smi, phyNo, ocp_addr, phyData);
+}
+
+static int dal_rtl8367c_port_phyReg_set(struct rtl8366_smi *smi, int port, u32 reg, u32 regData)
+{
+ int retVal;
+
+
+ if ((retVal = rtl8367c_setAsicPHYReg(smi, port, reg, regData)) != RT_ERR_OK)
+ return retVal;
+
+ return RT_ERR_OK;
+}
+
+static int dal_rtl8367c_port_phyReg_get(struct rtl8366_smi *smi, int port, u32 reg, u32 *pData)
+{
+ int retVal;
+
+
+ if ((retVal = rtl8367c_getAsicPHYReg(smi, port, reg, pData)) != RT_ERR_OK)
+ return retVal;
+
+ return RT_ERR_OK;
+}
+
+static int ipq_mdio_wait_busy(void)
+{
+ int i;
+ u32 busy;
+ for (i = 0; i < IPQ_MDIO_RETRY; i++) {
+ busy = readl(IPQ_MDIO_BASE +
+ MDIO_CTRL_4_REG) &
+ MDIO_CTRL_4_ACCESS_BUSY;
+ if (!busy)
+ return 0;
+ }
+ printk("%s: MDIO operation timed out\n",__func__);
+ return -ETIMEDOUT;
+}
+
+
+static int rtk_mdio_write(struct rtl8366_smi *smi, int mii_id, int regnum, u32 value)
+{
+ u32 cmd;
+
+ if (regnum & MII_ADDR_C45) {
+ unsigned int mmd = (regnum >> 16) & 0x1F;
+ unsigned int reg = regnum & 0xFFFF;
+
+ writel(CTRL_0_REG_C45_DEFAULT_VALUE,
+ IPQ_MDIO_BASE + MDIO_CTRL_0_REG);
+
+ /* Issue the phy address and reg */
+ writel((mii_id << 8) | mmd,
+ IPQ_MDIO_BASE + MDIO_CTRL_1_REG);
+
+ writel(reg, IPQ_MDIO_BASE + MDIO_CTRL_2_REG);
+
+ /* issue read command */
+ cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_ADDR;
+
+ writel(cmd, IPQ_MDIO_BASE + MDIO_CTRL_4_REG);
+
+ if (ipq_mdio_wait_busy())
+ return -ETIMEDOUT;
+ } else {
+ writel(CTRL_0_REG_DEFAULT_VALUE,
+ IPQ_MDIO_BASE + MDIO_CTRL_0_REG);
+
+ /* Issue the phy addreass and reg */
+ writel((mii_id << 8 | regnum),
+ IPQ_MDIO_BASE + MDIO_CTRL_1_REG);
+ }
+
+ /* Issue a write data */
+ writel(value, IPQ_MDIO_BASE + MDIO_CTRL_2_REG);
+
+ if (regnum & MII_ADDR_C45) {
+ cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_WRITE ;
+ } else {
+ cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_WRITE ;
+ }
+
+ writel(cmd, IPQ_MDIO_BASE + MDIO_CTRL_4_REG);
+ /* Wait for write complete */
+
+ if (ipq_mdio_wait_busy())
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int rtk_mdio_read(struct rtl8366_smi *smi, int mii_id, int regnum, u32 *data)
+{
+ u32 val,cmd;
+
+ if (regnum & MII_ADDR_C45) {
+
+ unsigned int mmd = (regnum >> 16) & 0x1F;
+ unsigned int reg = regnum & 0xFFFF;
+
+ writel(CTRL_0_REG_C45_DEFAULT_VALUE,
+ IPQ_MDIO_BASE + MDIO_CTRL_0_REG);
+
+ /* Issue the phy address and reg */
+ writel((mii_id << 8) | mmd,
+ IPQ_MDIO_BASE + MDIO_CTRL_1_REG);
+
+
+ writel(reg, IPQ_MDIO_BASE + MDIO_CTRL_2_REG);
+
+ /* issue read command */
+ cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_ADDR;
+ } else {
+
+ writel(CTRL_0_REG_DEFAULT_VALUE,
+ IPQ_MDIO_BASE + MDIO_CTRL_0_REG);
+
+ /* Issue the phy address and reg */
+ writel((mii_id << 8 | regnum ) ,
+ IPQ_MDIO_BASE + MDIO_CTRL_1_REG);
+
+ /* issue read command */
+ cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_READ ;
+ }
+
+ /* issue read command */
+ writel(cmd, IPQ_MDIO_BASE + MDIO_CTRL_4_REG);
+
+ if (ipq_mdio_wait_busy())
+ return -ETIMEDOUT;
+
+ if (regnum & MII_ADDR_C45) {
+ cmd = MDIO_CTRL_4_ACCESS_START | MDIO_CTRL_4_ACCESS_CODE_C45_READ;
+ writel(cmd, IPQ_MDIO_BASE + MDIO_CTRL_4_REG);
+
+ if (ipq_mdio_wait_busy())
+ return -ETIMEDOUT;
+ }
+
+ /* Read data */
+ val = readl(IPQ_MDIO_BASE + MDIO_CTRL_3_REG);
+
+ if (data != NULL)
+ *data = val;
+
+ return val;
+}
+
+static int rtl8367c_setAsicRegBit(struct rtl8366_smi *smi, u32 reg, u32 bit, u32 value)
+{
+ u32 regData;
+ int err;
+
+ if(bit >= RTL8367C_REGBITLENGTH)
+ return RT_ERR_INPUT;
+
+ REG_RD(smi, reg, &regData);
+ if(err != RT_ERR_OK)
+ return RT_ERR_SMI;
+
+ if(value)
+ regData = regData | (1 << bit);
+ else
+ regData = regData & (~(1 << bit));
+
+ REG_WR(smi, reg, regData);
+ if(err != RT_ERR_OK)
+ return RT_ERR_SMI;
+
+ return RT_ERR_OK;
+}
+
+static int rtl8367c_setAsicPortEnableAll(struct rtl8366_smi *smi, u32 enable)
+{
+ if(enable >= 2)
+ return RT_ERR_INPUT;
+ return rtl8367c_setAsicRegBit(smi, RTL8367C_REG_PHY_AD, RTL8367C_PDNPHY_OFFSET, enable);
+}
+
+static int dal_rtl8367c_port_phyEnableAll_set(struct switch_dev *dev,const struct switch_attr *attr,struct switch_val *val)
+{
+ struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+ int retVal;
+ u32 data;
+ int port = val->port_vlan;
+ int enable;
+ enable = val->value.i;
+ if(enable >= 2)
+ return -EINVAL;
+
+ if ((retVal = rtl8367c_setAsicPortEnableAll(smi, enable)) != RT_ERR_OK)
+ return retVal;
+
+ if ((retVal = dal_rtl8367c_port_phyReg_get(smi, port, PHY_CONTROL_REG, &data)) != RT_ERR_OK)
+ return retVal;
+
+ if (1 == enable)
+ {
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_POWER_DOWN_OFFSET);
+ RTL8367S_SET_BIT(data,RTL8367S_REG_RESTART_AUTO_NEGO_OFFSET);
+ }
+ else
+ {
+ RTL8367S_SET_BIT(data,RTL8367S_REG_POWER_DOWN_OFFSET);
+ }
+
+ if ((retVal = dal_rtl8367c_port_phyReg_set(smi, port, PHY_CONTROL_REG, data)) != RT_ERR_OK)
+ return retVal;
+
+ return RT_ERR_OK;
+}
+
+int get_port_state(struct switch_dev *dev,const struct switch_attr *attr,struct switch_val *val)
+{
+
+ struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+ u32 data;
+ int port;
+ port = val->port_vlan;
+
+ dal_rtl8367c_port_phyReg_get(smi, port, PHY_CONTROL_REG, &data);
+
+ if(RTL8367S_CHECK_BIT(data,RTL8367S_REG_POWER_DOWN_OFFSET)) //check whether bit11 is true
+ {
+ printk("disabled\n");
+ }
+ else
+ {
+ printk("enabled\n");
+ }
+
+ return 0;
+}
+
+static int dal_rtl8367c_port_crtl_status(struct switch_dev *dev,const struct switch_attr *attr,struct switch_val *val)
+{
+ struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+ int retVal;
+ u32 data;
+ int port = val->port_vlan;
+ int enable;
+ enable = val->value.i;
+ if(enable >= 5)
+ return -EINVAL;
+ if ((retVal = dal_rtl8367c_port_phyReg_get(smi, port, PHY_CONTROL_REG, &data)) != RT_ERR_OK)
+ return retVal;
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_AUTO_NEGO_EN_OFFSET); //diasble auto
+ switch(enable)
+ {
+ case 0: //10M-half
+ {
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_DUPLEX_MODE_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_LOW_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_HIGH_OFFSET);
+ }
+ break;
+ case 1: //10M-full
+ {
+ RTL8367S_SET_BIT(data,RTL8367S_REG_DUPLEX_MODE_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_LOW_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_HIGH_OFFSET);
+ }
+ break;
+ case 2: //100M-half
+ {
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_DUPLEX_MODE_OFFSET);
+ RTL8367S_SET_BIT(data,RTL8367S_REG_SPEED_SELECTION_LOW_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_HIGH_OFFSET);
+ }
+ break;
+ case 3: //100M-full
+ {
+ RTL8367S_SET_BIT(data,RTL8367S_REG_DUPLEX_MODE_OFFSET);
+ RTL8367S_SET_BIT(data,RTL8367S_REG_SPEED_SELECTION_LOW_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_HIGH_OFFSET);
+ }
+ break;
+ case 4: //1000M-full == auto
+ {
+ RTL8367S_SET_BIT(data,RTL8367S_REG_AUTO_NEGO_EN_OFFSET);
+ RTL8367S_SET_BIT(data,RTL8367S_REG_DUPLEX_MODE_OFFSET);
+ RTL8367S_CLEAR_BIT(data,RTL8367S_REG_SPEED_SELECTION_LOW_OFFSET);
+ RTL8367S_SET_BIT(data,RTL8367S_REG_SPEED_SELECTION_HIGH_OFFSET);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((retVal = dal_rtl8367c_port_phyReg_set(smi, port, PHY_CONTROL_REG, data)) != RT_ERR_OK)
+ return retVal;
+ return RT_ERR_OK;
+}
+
+static int rtl8367s_extif_set_force(struct rtl8366_smi *smi, int id, int mode,
+ struct rtl8367_port_ability *pa)
@@ -2610,7 +3113,6 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+ rtl8366_smi_read_reg(smi, RTL8367S_SDS_MISC, &sds_misc);
+
+ rtl8366_smi_read_reg(smi, RTL8367B_PORT_STATUS_REG(port), &data);
+
+ link->link = !!(data & RTL8367B_PORT_STATUS_LINK);
+ if (!link->link)
+ return 0;
@@ -2684,14 +3186,13 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+ RTL8367B_SWC0_MAX_LENGTH_MASK, max_len);
+}
+
+
+static int rtl8367b_sw_reset_port_mibs(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+ int port;
+
+
+ port = val->port_vlan;
+ if (port >= RTL8367B_NUM_PORTS)
+ return -EINVAL;
@@ -2747,6 +3248,20 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+ .max = 33,
+ .set = NULL,
+ .get = rtl8366_sw_get_port_mib,
+ }, {
+ .type = SWITCH_TYPE_INT,
+ .name = "enable_port",
+ .description = "Enable or disable the port",
+ .set = dal_rtl8367c_port_phyEnableAll_set,
+ .get = get_port_state,
+ .max = 1,
+ }, {
+ .type = SWITCH_TYPE_INT,
+ .name = "set_autoNego",
+ .description = "Set auto nego of the port---"
+ "0:10M-half 1:10M-full 2:100M-half 3:100M-full 4:1000M-full(auto)",
+ .set = dal_rtl8367c_port_crtl_status,
+ .max = 4,
+ },
+};
+
@@ -3006,10 +3521,9 @@ Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/drivers/net/ph
+
+module_platform_driver(rtl8367b_driver);
+
+MODULE_DESCRIPTION(RTL8367B_DRIVER_DESC);
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_DESCRIPTION(RTL8367S_DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" RTL8367B_DRIVER_NAME);
+MODULE_ALIAS("platform:" RTL8367S_DRIVER_NAME);
+
Index: linux-4.4.60-qsdk-11f09717303ecd83c3a64e9efe23f25921dc1016/include/linux/rtl8367.h
===================================================================