mediatek: mt7622: add Linux 5.10 support
[openwrt/openwrt.git] / target / linux / mediatek / files-5.10 / drivers / net / phy / rtk / rtl8367c / smi.c
diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c b/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c
new file mode 100644 (file)
index 0000000..c272cad
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2013 Realtek Semiconductor Corp.
+ * All Rights Reserved.
+ *
+ * Unless you and Realtek execute a separate written software license
+ * agreement governing use of this software, this software is licensed
+ * to you under the terms of the GNU General Public License version 2,
+ * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+ *
+ * Purpose : RTL8367C switch low-level function for access register
+ * Feature : SMI related functions
+ *
+ */
+
+
+#include <rtk_types.h>
+#include <smi.h>
+#include "rtk_error.h"
+
+
+#if defined(MDC_MDIO_OPERATION)
+/*******************************************************************************/
+/*  MDC/MDIO porting                                                           */
+/*******************************************************************************/
+/* define the PHY ID currently used */
+/* carlos */
+#if 0
+#define MDC_MDIO_PHY_ID     0  /* PHY ID 0 or 29 */
+#else
+#define MDC_MDIO_PHY_ID     29  /* PHY ID 0 or 29 */
+#endif
+
+/* MDC/MDIO, redefine/implement the following Macro */ /*carlos*/
+#if 0
+#define MDC_MDIO_WRITE(preamableLength, phyID, regID, data)
+#define MDC_MDIO_READ(preamableLength, phyID, regID, pData)
+#else
+#define u32      unsigned int
+extern u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data);
+extern u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data);
+
+#define MDC_MDIO_WRITE(preamableLength, phyID, regID, data) mii_mgr_write(phyID, regID, data)
+#define MDC_MDIO_READ(preamableLength, phyID, regID, pData) mii_mgr_read(phyID, regID, pData)
+#endif
+
+
+
+
+
+#elif defined(SPI_OPERATION)
+/*******************************************************************************/
+/*  SPI porting                                                                */
+/*******************************************************************************/
+/* SPI, redefine/implement the following Macro */
+#define SPI_WRITE(data, length)
+#define SPI_READ(pData, length)
+
+
+
+
+
+#else
+/*******************************************************************************/
+/*  I2C porting                                                                */
+/*******************************************************************************/
+/* Define the GPIO ID for SCK & SDA */
+rtk_uint32  smi_SCK = 1;    /* GPIO used for SMI Clock Generation */
+rtk_uint32  smi_SDA = 2;    /* GPIO used for SMI Data signal */
+
+/* I2C, redefine/implement the following Macro */
+#define GPIO_DIRECTION_SET(gpioID, direction)
+#define GPIO_DATA_SET(gpioID, data)
+#define GPIO_DATA_GET(gpioID, pData)
+
+
+
+
+
+#endif
+
+static void rtlglue_drvMutexLock(void)
+{
+    /* It is empty currently. Implement this function if Lock/Unlock function is needed */
+    return;
+}
+
+static void rtlglue_drvMutexUnlock(void)
+{
+    /* It is empty currently. Implement this function if Lock/Unlock function is needed */
+    return;
+}
+
+
+
+#if defined(MDC_MDIO_OPERATION) || defined(SPI_OPERATION)
+    /* No local function in MDC/MDIO & SPI mode */
+#else
+static void _smi_start(void)
+{
+
+    /* change GPIO pin to Output only */
+    GPIO_DIRECTION_SET(smi_SCK, GPIO_DIR_OUT);
+    GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_OUT);
+
+    /* Initial state: SCK: 0, SDA: 1 */
+    GPIO_DATA_SET(smi_SCK, 0);
+    GPIO_DATA_SET(smi_SDA, 1);
+    CLK_DURATION(DELAY);
+
+    /* CLK 1: 0 -> 1, 1 -> 0 */
+    GPIO_DATA_SET(smi_SCK, 1);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 0);
+    CLK_DURATION(DELAY);
+
+    /* CLK 2: */
+    GPIO_DATA_SET(smi_SCK, 1);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SDA, 0);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 0);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SDA, 1);
+
+}
+
+
+
+static void _smi_writeBit(rtk_uint16 signal, rtk_uint32 bitLen)
+{
+    for( ; bitLen > 0; bitLen--)
+    {
+        CLK_DURATION(DELAY);
+
+        /* prepare data */
+        if ( signal & (1<<(bitLen-1)) )
+        {
+            GPIO_DATA_SET(smi_SDA, 1);
+        }
+        else
+        {
+            GPIO_DATA_SET(smi_SDA, 0);
+        }
+        CLK_DURATION(DELAY);
+
+        /* clocking */
+        GPIO_DATA_SET(smi_SCK, 1);
+        CLK_DURATION(DELAY);
+        GPIO_DATA_SET(smi_SCK, 0);
+    }
+}
+
+
+
+static void _smi_readBit(rtk_uint32 bitLen, rtk_uint32 *rData)
+{
+    rtk_uint32 u = 0;
+
+    /* change GPIO pin to Input only */
+    GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_IN);
+
+    for (*rData = 0; bitLen > 0; bitLen--)
+    {
+        CLK_DURATION(DELAY);
+
+        /* clocking */
+        GPIO_DATA_SET(smi_SCK, 1);
+        CLK_DURATION(DELAY);
+        GPIO_DATA_GET(smi_SDA, &u);
+        GPIO_DATA_SET(smi_SCK, 0);
+
+        *rData |= (u << (bitLen - 1));
+    }
+
+    /* change GPIO pin to Output only */
+    GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_OUT);
+}
+
+
+
+static void _smi_stop(void)
+{
+
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SDA, 0);
+    GPIO_DATA_SET(smi_SCK, 1);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SDA, 1);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 1);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 0);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 1);
+
+    /* add a click */
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 0);
+    CLK_DURATION(DELAY);
+    GPIO_DATA_SET(smi_SCK, 1);
+
+
+    /* change GPIO pin to Input only */
+    GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_IN);
+    GPIO_DIRECTION_SET(smi_SCK, GPIO_DIR_IN);
+}
+
+#endif /* End of #if defined(MDC_MDIO_OPERATION) || defined(SPI_OPERATION) */
+
+rtk_int32 smi_read(rtk_uint32 mAddrs, rtk_uint32 *rData)
+{
+#if (!defined(MDC_MDIO_OPERATION) && !defined(SPI_OPERATION))
+    rtk_uint32 rawData=0, ACK;
+    rtk_uint8  con;
+    rtk_uint32 ret = RT_ERR_OK;
+#endif
+
+    if(mAddrs > 0xFFFF)
+        return RT_ERR_INPUT;
+
+    if(rData == NULL)
+        return RT_ERR_NULL_POINTER;
+
+#if defined(MDC_MDIO_OPERATION)
+
+    /* Lock */
+    rtlglue_drvMutexLock();
+
+    /* Write address control code to register 31 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);
+
+    /* Write address to register 23 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_ADDRESS_REG, mAddrs);
+
+    /* Write read control code to register 21 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP);
+
+    /* Read data from register 25 */
+    MDC_MDIO_READ(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_DATA_READ_REG, rData);
+
+    /* Unlock */
+    rtlglue_drvMutexUnlock();
+
+    return RT_ERR_OK;
+
+#elif defined(SPI_OPERATION)
+
+    /* Lock */
+    rtlglue_drvMutexLock();
+
+    /* Write 8 bits READ OP_CODE */
+    SPI_WRITE(SPI_READ_OP, SPI_READ_OP_LEN);
+
+    /* Write 16 bits register address */
+    SPI_WRITE(mAddrs, SPI_REG_LEN);
+
+    /* Read 16 bits data */
+    SPI_READ(rData, SPI_DATA_LEN);
+
+    /* Unlock */
+    rtlglue_drvMutexUnlock();
+
+    return RT_ERR_OK;
+
+#else
+
+    /*Disable CPU interrupt to ensure that the SMI operation is atomic.
+      The API is based on RTL865X, rewrite the API if porting to other platform.*/
+    rtlglue_drvMutexLock();
+
+    _smi_start();                                /* Start SMI */
+
+    _smi_writeBit(0x0b, 4);                     /* CTRL code: 4'b1011 for RTL8370 */
+
+    _smi_writeBit(0x4, 3);                        /* CTRL code: 3'b100 */
+
+    _smi_writeBit(0x1, 1);                        /* 1: issue READ command */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK for issuing READ command*/
+    } while ((ACK != 0) && (con < ack_timer));
+
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_writeBit((mAddrs&0xff), 8);             /* Set reg_addr[7:0] */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK for setting reg_addr[7:0] */
+    } while ((ACK != 0) && (con < ack_timer));
+
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_writeBit((mAddrs>>8), 8);                 /* Set reg_addr[15:8] */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK by RTL8369 */
+    } while ((ACK != 0) && (con < ack_timer));
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_readBit(8, &rawData);                    /* Read DATA [7:0] */
+    *rData = rawData&0xff;
+
+    _smi_writeBit(0x00, 1);                        /* ACK by CPU */
+
+    _smi_readBit(8, &rawData);                    /* Read DATA [15: 8] */
+
+    _smi_writeBit(0x01, 1);                        /* ACK by CPU */
+    *rData |= (rawData<<8);
+
+    _smi_stop();
+
+    rtlglue_drvMutexUnlock();/*enable CPU interrupt*/
+
+    return ret;
+#endif /* end of #if defined(MDC_MDIO_OPERATION) */
+}
+
+
+
+rtk_int32 smi_write(rtk_uint32 mAddrs, rtk_uint32 rData)
+{
+#if (!defined(MDC_MDIO_OPERATION) && !defined(SPI_OPERATION))
+    rtk_int8 con;
+    rtk_uint32 ACK;
+    rtk_uint32 ret = RT_ERR_OK;
+#endif
+
+    if(mAddrs > 0xFFFF)
+        return RT_ERR_INPUT;
+
+    if(rData > 0xFFFF)
+        return RT_ERR_INPUT;
+
+#if defined(MDC_MDIO_OPERATION)
+
+    /* Lock */
+    rtlglue_drvMutexLock();
+
+    /* Write address control code to register 31 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);
+
+    /* Write address to register 23 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_ADDRESS_REG, mAddrs);
+
+    /* Write data to register 24 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_DATA_WRITE_REG, rData);
+
+    /* Write data control code to register 21 */
+    MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL1_REG, MDC_MDIO_WRITE_OP);
+
+    /* Unlock */
+    rtlglue_drvMutexUnlock();
+
+    return RT_ERR_OK;
+
+#elif defined(SPI_OPERATION)
+
+    /* Lock */
+    rtlglue_drvMutexLock();
+
+    /* Write 8 bits WRITE OP_CODE */
+    SPI_WRITE(SPI_WRITE_OP, SPI_WRITE_OP_LEN);
+
+    /* Write 16 bits register address */
+    SPI_WRITE(mAddrs, SPI_REG_LEN);
+
+    /* Write 16 bits data */
+    SPI_WRITE(rData, SPI_DATA_LEN);
+
+    /* Unlock */
+    rtlglue_drvMutexUnlock();
+
+    return RT_ERR_OK;
+#else
+
+    /*Disable CPU interrupt to ensure that the SMI operation is atomic.
+      The API is based on RTL865X, rewrite the API if porting to other platform.*/
+    rtlglue_drvMutexLock();
+
+    _smi_start();                                /* Start SMI */
+
+    _smi_writeBit(0x0b, 4);                     /* CTRL code: 4'b1011 for RTL8370*/
+
+    _smi_writeBit(0x4, 3);                        /* CTRL code: 3'b100 */
+
+    _smi_writeBit(0x0, 1);                        /* 0: issue WRITE command */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK for issuing WRITE command*/
+    } while ((ACK != 0) && (con < ack_timer));
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_writeBit((mAddrs&0xff), 8);             /* Set reg_addr[7:0] */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK for setting reg_addr[7:0] */
+    } while ((ACK != 0) && (con < ack_timer));
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_writeBit((mAddrs>>8), 8);                 /* Set reg_addr[15:8] */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK for setting reg_addr[15:8] */
+    } while ((ACK != 0) && (con < ack_timer));
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_writeBit(rData&0xff, 8);                /* Write Data [7:0] out */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                    /* ACK for writting data [7:0] */
+    } while ((ACK != 0) && (con < ack_timer));
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_writeBit(rData>>8, 8);                    /* Write Data [15:8] out */
+
+    con = 0;
+    do {
+        con++;
+        _smi_readBit(1, &ACK);                        /* ACK for writting data [15:8] */
+    } while ((ACK != 0) && (con < ack_timer));
+    if (ACK != 0) ret = RT_ERR_FAILED;
+
+    _smi_stop();
+
+    rtlglue_drvMutexUnlock();/*enable CPU interrupt*/
+
+    return ret;
+#endif /* end of #if defined(MDC_MDIO_OPERATION) */
+}
+