diff options
author | Felix Fietkau <nbd@nbd.name> | 2020-10-24 21:15:20 +0200 |
---|---|---|
committer | Daniel Golle <daniel@makrotopia.org> | 2021-02-28 00:45:56 +0000 |
commit | c46ccb69d17e584479df849a107423175a143c83 (patch) | |
tree | 10c0b329ba571cbdd366e48e61173a64e56c841d /target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c | |
parent | 11425c9de29c8b9c5e4d7eec163a6afbb7fbdce2 (diff) | |
download | upstream-c46ccb69d17e584479df849a107423175a143c83.tar.gz upstream-c46ccb69d17e584479df849a107423175a143c83.tar.bz2 upstream-c46ccb69d17e584479df849a107423175a143c83.zip |
mediatek: mt7622: add Linux 5.10 support
Switch mt7622 subtarget to Linux 5.10, it has been tested by many of us
on several devices for a couple of weeks already.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c')
-rw-r--r-- | target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c | 444 |
1 files changed, 444 insertions, 0 deletions
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 index 0000000000..c272cad48e --- /dev/null +++ b/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c @@ -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) */ +} + |