diff options
| author | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-05 10:12:53 +0000 | 
|---|---|---|
| committer | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-05 10:12:53 +0000 | 
| commit | 5c105d9f3fd086aff195d3849dcf847d6b0bd927 (patch) | |
| tree | 1229a11f725bfa58aa7c57a76898553bb5f6654a /package/uboot-ar71xx/files/drivers/net/phy | |
| download | openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.tar.gz openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.zip | |
branch Attitude Adjustment
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/uboot-ar71xx/files/drivers/net/phy')
| -rw-r--r-- | package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h | 188 | ||||
| -rw-r--r-- | package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c | 786 | 
2 files changed, 974 insertions, 0 deletions
| diff --git a/package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h new file mode 100644 index 000000000..f0567dd64 --- /dev/null +++ b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2010 + * Michael Kurz <michi.kurz@googlemail.com>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef RTL8366_MII_H +#define RTL8366_MII_H + +#define	MII_CONTROL_REG		    0 +#define	MII_STATUS_REG	    	1 +#define	MII_PHY_ID0		        2 +#define	MII_PHY_ID1		        3 +#define	MII_LOCAL_CAP	    	4 +#define	MII_REMOTE_CAP		    5 +#define	MII_EXT_AUTONEG		    6 +#define	MII_LOCAL_NEXT_PAGE	    7 +#define	MII_REMOTE_NEXT_PAGE	8 +#define	MII_GIGA_CONTROL	    9 +#define	MII_GIGA_STATUS		    10 +#define	MII_EXT_STATUS_REG	    15 + +/* Control register */ +#define	MII_CONTROL_1000MBPS	6 +#define	MII_CONTROL_COLL_TEST	7 +#define	MII_CONTROL_FULLDUPLEX	8 +#define	MII_CONTROL_RENEG	    9 +#define	MII_CONTROL_ISOLATE	    10 +#define	MII_CONTROL_POWERDOWN	11 +#define	MII_CONTROL_AUTONEG	    12 +#define	MII_CONTROL_100MBPS	    13 +#define	MII_CONTROL_LOOPBACK	14 +#define	MII_CONTROL_RESET	    15 + +/* Status/Extended status register */ +/* Basic status */ +#define	MII_STATUS_CAPABILITY	0 +#define	MII_STATUS_JABBER	    1 +#define	MII_STATUS_LINK_UP	    2 +#define	MII_STATUS_AUTONEG_ABLE	3 +#define	MII_STATUS_REMOTE_FAULT	4 +#define	MII_STATUS_AUTONEG_DONE	5 +#define	MII_STATUS_NO_PREAMBLE	6 +#define	MII_STATUS_RESERVED	    7 +#define	MII_STATUS_EXTENDED	    8 +#define	MII_STATUS_100_T2_HALF	9 +#define	MII_STATUS_100_T2_FULL	10 +#define	MII_STATUS_10_TX_HALF	11 +#define	MII_STATUS_10_TX_FULL	12 +#define	MII_STATUS_100_TX_HALF	13 +#define	MII_STATUS_100_TX_FULL	14 +#define	MII_STATUS_100_T4	    15 + +#define	MII_GIGA_CONTROL_HALF	8 +#define	MII_GIGA_CONTROL_FULL	9 +#define	MII_GIGA_STATUS_HALF	10 +#define	MII_GIGA_STATUS_FULL	11 + +/* Extended status */ +#define	MII_STATUS_1000_T_HALF	12 +#define	MII_STATUS_1000_T_FULL	13 +#define	MII_STATUS_1000_X_HALF	14 +#define	MII_STATUS_1000_X_FULL	15 + +/* Local/Remmote capability register */ +#define	MII_CAP_10BASE_TX	    5 +#define	MII_CAP_10BASE_TX_FULL	6 +#define	MII_CAP_100BASE_TX	    7 +#define	MII_CAP_100BASE_TX_FULL	8 +#define	MII_CAP_100BASE_T4	    9 +#define	MII_CAP_SYMM_PAUSE	    10 +#define	MII_CAP_ASYMM_PAUSE	    11 +#define	MII_CAP_RESERVED	    12 +#define	MII_CAP_REMOTE_FAULT	13 +#define	MII_CAP_ACKNOWLEDGE	    14 +#define	MII_CAP_NEXT_PAGE	    15 +#define	MII_CAP_IEEE_802_3	    0x0001 + +#define	MII_LINK_MODE_MASK	    0x1f + +#define REALTEK_RTL8366_CHIP_ID0    0x001C +#define REALTEK_RTL8366_CHIP_ID1    0xC940 +#define REALTEK_RTL8366_CHIP_ID1_MP 0xC960 + +#define REALTEK_MIN_PORT_ID     0 +#define REALTEK_MAX_PORT_ID     5 +#define REALTEK_MIN_PHY_ID      REALTEK_MIN_PORT_ID +#define REALTEK_MAX_PHY_ID      4 +#define REALTEK_CPU_PORT_ID     REALTEK_MAX_PORT_ID +#define REALTEK_PHY_PORT_MASK   ((1<<(REALTEK_MAX_PHY_ID+1)) - (1<<REALTEK_MIN_PHY_ID)) +#define REALTEK_CPU_PORT_MASK   (1<<REALTEK_CPU_PORT_ID) +#define REALTEK_ALL_PORT_MASK   (REALTEK_PHY_PORT_MASK | REALTEK_CPU_PORT_MASK) + +/* port ability */ +#define RTL8366S_PORT_ABILITY_BASE			0x0011 + +/* port vlan control register */ +#define RTL8366S_PORT_VLAN_CTRL_BASE			0x0058 + +/* port linking status */ +#define RTL8366S_PORT_LINK_STATUS_BASE			0x0060 +#define RTL8366S_PORT_STATUS_SPEED_BIT			0 +#define RTL8366S_PORT_STATUS_SPEED_MSK			0x0003 +#define RTL8366S_PORT_STATUS_DUPLEX_BIT			2 +#define RTL8366S_PORT_STATUS_DUPLEX_MSK			0x0004 +#define RTL8366S_PORT_STATUS_LINK_BIT			4 +#define RTL8366S_PORT_STATUS_LINK_MSK			0x0010 +#define RTL8366S_PORT_STATUS_TXPAUSE_BIT		5 +#define RTL8366S_PORT_STATUS_TXPAUSE_MSK		0x0020 +#define RTL8366S_PORT_STATUS_RXPAUSE_BIT		6 +#define RTL8366S_PORT_STATUS_RXPAUSE_MSK		0x0040 +#define RTL8366S_PORT_STATUS_AN_BIT			7 +#define RTL8366S_PORT_STATUS_AN_MSK			0x0080 + +/* internal control */ +#define RTL8366S_RESET_CONTROL_REG			0x0100 +#define RTL8366S_RESET_QUEUE_BIT			2 + +#define RTL8366S_CHIP_ID_REG				0x0105 + +/* MAC control */ +#define RTL8366S_MAC_FORCE_CTRL0_REG			0x0F04 +#define RTL8366S_MAC_FORCE_CTRL1_REG			0x0F05 + + +/* PHY registers control */ +#define RTL8366S_PHY_ACCESS_CTRL_REG			0x8028 +#define RTL8366S_PHY_ACCESS_DATA_REG			0x8029 + +#define RTL8366S_PHY_CTRL_READ				1 +#define RTL8366S_PHY_CTRL_WRITE				0 + +#define RTL8366S_PHY_REG_MASK				0x1F +#define RTL8366S_PHY_PAGE_OFFSET			5 +#define RTL8366S_PHY_PAGE_MASK				(0x7<<5) +#define RTL8366S_PHY_NO_OFFSET				9 +#define RTL8366S_PHY_NO_MASK				(0x1F<<9) + +#define RTL8366S_PHY_NO_MAX				4 +#define RTL8366S_PHY_PAGE_MAX				7 +#define RTL8366S_PHY_ADDR_MAX				31 + +/* cpu port control reg */ +#define RTL8366S_CPU_CTRL_REG				0x004F +#define RTL8366S_CPU_DRP_BIT				14 +#define RTL8366S_CPU_DRP_MSK				0x4000 +#define RTL8366S_CPU_INSTAG_BIT				15 +#define RTL8366S_CPU_INSTAG_MSK				0x8000 + +/* LED registers*/ +#define RTL8366S_LED_BLINK_REG				0x420 +#define RTL8366S_LED_BLINKRATE_BIT			0 +#define RTL8366S_LED_BLINKRATE_MSK			0x0007 +#define RTL8366S_LED_INDICATED_CONF_REG			0x421 +#define RTL8366S_LED_0_1_FORCE_REG			0x422 +#define RTL8366S_LED_2_3_FORCE_REG			0x423 +#define RTL8366S_LEDCONF_LEDFORCE			0x1F +#define RTL8366S_LED_GROUP_MAX				4 + +#define RTL8366S_GREEN_FEATURE_REG			0x000A +#define RTL8366S_GREEN_FEATURE_TX_BIT			3 +#define RTL8366S_GREEN_FEATURE_TX_MSK			0x0008 +#define RTL8366S_GREEN_FEATURE_RX_BIT			4 +#define RTL8366S_GREEN_FEATURE_RX_MSK			0x0010 + +#define	RTL8366S_MODEL_ID_REG	0x5C +#define	RTL8366S_REV_ID_REG	0x5D +#define	RTL8366S_MODEL_8366SR	0x6027 +#define	RTL8366S_MODEL_8366RB	0x5937 + +#endif diff --git a/package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c new file mode 100644 index 000000000..e3c531654 --- /dev/null +++ b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c @@ -0,0 +1,786 @@ +/* + * (C) Copyright 2010 + * Michael Kurz <michi.kurz@googlemail.com>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <net.h> +#include <netdev.h> +#include <miiphy.h> +#include MII_GPIOINCLUDE + +#include "rtl8366.h" + +#ifdef DEBUG_RTL8366 +	#define DBG(fmt,args...)	printf (fmt ,##args) +#else +	#define DBG(fmt,args...) +#endif + + +//------------------------------------------------------------------- +// Soft SMI functions +//------------------------------------------------------------------- + +#define DELAY 2 + +static void smi_init(void) +{ +    MII_SDAINPUT; +    MII_SCKINPUT; + +	MII_SETSDA(1); +	MII_SETSCK(1); + +    udelay(20); +} + +static void smi_start(void) +{ +/* + * rtl8366 chip needs a extra clock with + * SDA high before start condition + */ + +    /* set gpio pins output */ +    MII_SDAOUTPUT; +    MII_SCKOUTPUT; +    udelay(DELAY); + +    /* set initial state: SCK:0, SDA:1 */ +    MII_SETSCK(0); +    MII_SETSDA(1); +    udelay(DELAY); + +    /* toggle clock */ +    MII_SETSCK(1); +    udelay(DELAY); +    MII_SETSCK(0); +    udelay(DELAY); + +    /* start condition */ +    MII_SETSCK(1); +    udelay(DELAY); +    MII_SETSDA(0); +    udelay(DELAY); +    MII_SETSCK(0); +    udelay(DELAY); +    MII_SETSDA(1); +} + +static void smi_stop(void) +{ +/* + * rtl8366 chip needs a extra clock with + * SDA high after stop condition + */ + +    /* stop condition */ +	udelay(DELAY); +    MII_SETSDA(0); +    MII_SETSCK(1); +    udelay(DELAY); +    MII_SETSDA(1); +    udelay(DELAY); +    MII_SETSCK(1); +    udelay(DELAY); +    MII_SETSCK(0); +    udelay(DELAY); + +    /* toggle clock */ +    MII_SETSCK(1); +    udelay(DELAY); +    MII_SETSCK(0); +    udelay(DELAY); +    MII_SETSCK(1); + +    /* set gpio pins input */ +    MII_SDAINPUT; +    MII_SCKINPUT; +} + +static void smi_writeBits(uint32_t data, uint8_t length) +{ +    uint8_t test; + +    for( ; length > 0; length--) { +        udelay(DELAY); + +        /* output data */ +        test = (((data & (1 << (length - 1))) != 0) ? 1 : 0); +        MII_SETSDA(test); +        udelay(DELAY); + +        /* toogle clock */ +        MII_SETSCK(1); +        udelay(DELAY); +        MII_SETSCK(0); +    } +} + +static uint32_t smi_readBits(uint8_t length) +{ +    uint32_t ret; + +    MII_SDAINPUT; + +    for(ret = 0 ; length > 0; length--) { +        udelay(DELAY); + +        ret <<= 1; + +        /* toogle clock */ +        MII_SETSCK(1); +        udelay(DELAY); +        ret |= MII_GETSDA; +        MII_SETSCK(0); +    } + +    MII_SDAOUTPUT; + +    return ret; +} + +static int smi_waitAck(void) +{ +    uint32_t retry = 0; + +	while (smi_readBits(1)) { +		if (retry++ == 5) +			return -1; +	} + +	return 0; + +} + +static int smi_read(uint32_t reg, uint32_t *data) +{ +    uint32_t rawData; + +    /* send start condition */ +    smi_start(); +    /* send CTRL1 code: 0b1010*/ +    smi_writeBits(0x0a, 4); +    /* send CTRL2 code: 0b100 */ +    smi_writeBits(0x04, 3); +    /* send READ command */ +    smi_writeBits(0x01, 1); + +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; + +    /* send address low */ +    smi_writeBits(reg & 0xFF, 8); +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; +    /* send address high */ +    smi_writeBits((reg & 0xFF00) >> 8, 8); +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; + +    /* read data low */ +    rawData = (smi_readBits(8) & 0xFF); +    /* send ACK */ +    smi_writeBits(0, 1); +    /* read data high */ +    rawData |= (smi_readBits(8) & 0xFF) << 8; +    /* send NACK */ +    smi_writeBits(1, 1); + +    /* send stop condition */ +    smi_stop(); + +    if (data) +        *data = rawData; + +    return 0; +} + +static int smi_write(uint32_t reg, uint32_t data) +{ +    /* send start condition */ +    smi_start(); +    /* send CTRL1 code: 0b1010*/ +    smi_writeBits(0x0a, 4); +    /* send CTRL2 code: 0b100 */ +    smi_writeBits(0x04, 3); +    /* send WRITE command */ +    smi_writeBits(0x00, 1); + +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; + +    /* send address low */ +    smi_writeBits(reg & 0xFF, 8); +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; +    /* send address high */ +    smi_writeBits((reg & 0xFF00) >> 8, 8); +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; + +    /* send data low */ +    smi_writeBits(data & 0xFF, 8); +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; +    /* send data high */ +    smi_writeBits((data & 0xFF00) >> 8, 8); +    /* wait for ACK */ +    if (smi_waitAck()) +        return -1; + +    /* send stop condition */ +    smi_stop(); + +    return 0; +} + + +//------------------------------------------------------------------- +// Switch register read / write functions +//------------------------------------------------------------------- +static int rtl8366_readRegister(uint32_t reg, uint16_t *data) +{ +    uint32_t regData; + +    DBG("rtl8366: read register=%#04x, data=", reg); + +    if (smi_read(reg, ®Data)) { +        printf("\nrtl8366 smi read failed!\n"); +        return -1; +    } + +    if (data) +        *data = regData; + +    DBG("%#04x\n", regData); + +    return 0; +} + +static int rtl8366_writeRegister(uint32_t reg, uint16_t data) +{ +    DBG("rtl8366: write register=%#04x, data=%#04x\n", reg, data); + +    if (smi_write(reg, data)) { +        printf("rtl8366 smi write failed!\n"); +        return -1; +    } + +    return 0; +} + +static int rtl8366_setRegisterBit(uint32_t reg, uint32_t bitNum, uint32_t value) +{ +    uint16_t regData; + +    if (bitNum >= 16) +        return -1; + +    if (rtl8366_readRegister(reg, ®Data)) +        return -1; + +    if (value) +        regData |= (1 << bitNum); +    else +        regData &= ~(1 << bitNum); + +    if (rtl8366_writeRegister(reg, regData)) +        return -1; + +    return 0; +} + +//------------------------------------------------------------------- +// MII PHY read / write functions +//------------------------------------------------------------------- +static int rtl8366_getPhyReg(uint32_t phyNum, uint32_t reg, uint16_t *data) +{ +    uint16_t phyAddr, regData; + +    if (phyNum > RTL8366S_PHY_NO_MAX) { +		printf("rtl8366s: invalid phy number!\n"); +		return -1; +	} + +    if (phyNum > RTL8366S_PHY_ADDR_MAX) { +		printf("rtl8366s: invalid phy register number!\n"); +		return -1; +	} + +	if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, +                           RTL8366S_PHY_CTRL_READ)) +        return -1; + +    phyAddr = 0x8000 | (1 << (phyNum + RTL8366S_PHY_NO_OFFSET)) +                     | (reg & RTL8366S_PHY_REG_MASK); +    if (rtl8366_writeRegister(phyAddr, 0)) +        return -1; + +    if (rtl8366_readRegister(RTL8366S_PHY_ACCESS_DATA_REG, ®Data)) +        return -1; + +    if (data) +        *data = regData; + +    return 0; +} + +static int rtl8366_setPhyReg(uint32_t phyNum, uint32_t reg, uint16_t data) +{ +    uint16_t phyAddr; + +    if (phyNum > RTL8366S_PHY_NO_MAX) { +		printf("rtl8366s: invalid phy number!\n"); +		return -1; +	} + +    if (phyNum > RTL8366S_PHY_ADDR_MAX) { +		printf("rtl8366s: invalid phy register number!\n"); +		return -1; +	} + +	if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, +                           RTL8366S_PHY_CTRL_WRITE)) +        return -1; + +    phyAddr = 0x8000 | (1 << (phyNum + RTL8366S_PHY_NO_OFFSET)) +                     | (reg & RTL8366S_PHY_REG_MASK); +    if (rtl8366_writeRegister(phyAddr, data)) +        return -1; + +    return 0; +} + +static int rtl8366_miiread(char *devname, uchar phy_adr, uchar reg, ushort *data) +{ +    uint16_t regData; + +    DBG("rtl8366_miiread: devname=%s, addr=%#02x, reg=%#02x\n", +          devname, phy_adr, reg); + +    if (strcmp(devname, RTL8366_DEVNAME) != 0) +        return -1; + +    if (rtl8366_getPhyReg(phy_adr, reg, ®Data)) { +        printf("rtl8366_miiread: write failed!\n"); +        return -1; +    } + +    if (data) +        *data = regData; + +    return 0; +} + +static int rtl8366_miiwrite(char *devname, uchar phy_adr, uchar reg, ushort data) +{ +    DBG("rtl8366_miiwrite: devname=%s, addr=%#02x, reg=%#02x, data=%#04x\n", +          devname, phy_adr, reg, data); + +    if (strcmp(devname, RTL8366_DEVNAME) != 0) +        return -1; + +    if (rtl8366_setPhyReg(phy_adr, reg, data)) { +        printf("rtl8366_miiwrite: write failed!\n"); +        return -1; +    } + +    return 0; +} + +int rtl8366_mii_register(bd_t *bis) +{ +    miiphy_register(strdup(RTL8366_DEVNAME), rtl8366_miiread, +			rtl8366_miiwrite); + +    return 0; +} + + +//------------------------------------------------------------------- +// Switch management functions +//------------------------------------------------------------------- + +int rtl8366s_setGreenFeature(uint32_t tx, uint32_t rx) +{ +    if (rtl8366_setRegisterBit(RTL8366S_GREEN_FEATURE_REG, +                               RTL8366S_GREEN_FEATURE_TX_BIT, tx)) +        return -1; + +    if (rtl8366_setRegisterBit(RTL8366S_GREEN_FEATURE_REG, +                               RTL8366S_GREEN_FEATURE_RX_BIT, rx)) +        return -1; + +    return 0; +} + +int rtl8366s_setPowerSaving(uint32_t phyNum, uint32_t enabled) +{ +    uint16_t regData; + +    if (phyNum > RTL8366S_PHY_NO_MAX) +        return -1; + +    if (rtl8366_getPhyReg(phyNum, 12, ®Data)) +        return -1; + +    if (enabled) +        regData |= (1 << 12); +    else +        regData &= ~(1 << 12); + +    if (rtl8366_setPhyReg(phyNum, 12, regData)) +        return -1; + +    return 0; +} + +int rtl8366s_setGreenEthernet(uint32_t greenFeature, uint32_t powerSaving) +{ +    uint32_t phyNum, i; +    uint16_t regData; + +	const uint16_t greenSettings[][2] = +	{ +		{0xBE5B,0x3500}, +		{0xBE5C,0xB975}, +		{0xBE5D,0xB9B9}, +		{0xBE77,0xA500}, +		{0xBE78,0x5A78}, +		{0xBE79,0x6478} +	}; + +    if (rtl8366_readRegister(RTL8366S_MODEL_ID_REG, ®Data)) +        return -1; + +	switch (regData) +	{ +		case 0x0000: +			for (i = 0; i < 6; i++) { +				if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, RTL8366S_PHY_CTRL_WRITE)) +					return -1; +				if (rtl8366_writeRegister(greenSettings[i][0], greenSettings[i][1])) +					return -1; +			} +			break; + +		case RTL8366S_MODEL_8366SR: +			if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, RTL8366S_PHY_CTRL_WRITE)) +				return -1; +			if (rtl8366_writeRegister(greenSettings[0][0], greenSettings[0][1])) +				return -1; +			break; + +		default: +			printf("rtl8366s_initChip: unsupported chip found!\n"); +			return -1; +	} + +    if (rtl8366s_setGreenFeature(greenFeature, powerSaving)) +        return -1; + +    for (phyNum = 0; phyNum <= RTL8366S_PHY_NO_MAX; phyNum++) { +        if (rtl8366s_setPowerSaving(phyNum, powerSaving)) +            return -1; +    } + +    return 0; +} + +int rtl8366s_setCPUPortMask(uint8_t port, uint32_t enabled) +{ +	if(port >= 6){ +		printf("rtl8366s_setCPUPortMask: invalid port number\n"); +		return -1; +	} + +	return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG, port, enabled); +} + +int rtl8366s_setCPUDisableInsTag(uint32_t enable) +{ +	return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG, +		RTL8366S_CPU_INSTAG_BIT, enable); +} + +int rtl8366s_setCPUDropUnda(uint32_t enable) +{ +	return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG, +		RTL8366S_CPU_DRP_BIT, enable); +} + +int rtl8366s_setCPUPort(uint8_t port, uint32_t noTag, uint32_t dropUnda) +{ +	uint32_t i; + +	if(port >= 6){ +		printf("rtl8366s_setCPUPort: invalid port number\n"); +		return -1; +	} + +	/* reset register */ +	for(i = 0; i < 6; i++) +	{ +		if(rtl8366s_setCPUPortMask(i, 0)){ +			printf("rtl8366s_setCPUPort: rtl8366s_setCPUPortMask failed\n"); +			return -1; +		} +	} + +	if(rtl8366s_setCPUPortMask(port, 1)){ +		printf("rtl8366s_setCPUPort: rtl8366s_setCPUPortMask failed\n"); +		return -1; +	} + +	if(rtl8366s_setCPUDisableInsTag(noTag)){ +		printf("rtl8366s_setCPUPort: rtl8366s_setCPUDisableInsTag fail\n"); +		return -1; +	} + +	if(rtl8366s_setCPUDropUnda(dropUnda)){ +		printf("rtl8366s_setCPUPort: rtl8366s_setCPUDropUnda fail\n"); +		return -1; +	} + +	return 0; +} + +int rtl8366s_setLedConfig(uint32_t ledNum, uint8_t config) +{ +    uint16_t regData; + +	if(ledNum >= RTL8366S_LED_GROUP_MAX) { +		DBG("rtl8366s_setLedConfig: invalid led group\n"); +		return -1; +	} + +    if(config > RTL8366S_LEDCONF_LEDFORCE) { +		DBG("rtl8366s_setLedConfig: invalid led config\n"); +		return -1; +	} + +	if (rtl8366_readRegister(RTL8366S_LED_INDICATED_CONF_REG, ®Data)) { +        printf("rtl8366s_setLedConfig: failed to get led register!\n"); +        return -1; +	} + +	regData &= ~(0xF << (ledNum * 4)); +	regData |= config << (ledNum * 4); + +	if (rtl8366_writeRegister(RTL8366S_LED_INDICATED_CONF_REG, regData)) { +        printf("rtl8366s_setLedConfig: failed to set led register!\n"); +        return -1; +	} + +	return 0; +} + +int rtl8366s_getLedConfig(uint32_t ledNum, uint8_t *config) +{ +    uint16_t regData; + +	if(ledNum >= RTL8366S_LED_GROUP_MAX) { +		DBG("rtl8366s_getLedConfig: invalid led group\n"); +		return -1; +	} + +    if (rtl8366_readRegister(RTL8366S_LED_INDICATED_CONF_REG, ®Data)) { +        printf("rtl8366s_getLedConfig: failed to get led register!\n"); +        return -1; +	} + +	if (config) +        *config = (regData >> (ledNum * 4)) & 0xF; + +    return 0; +} + +int rtl8366s_setLedForceValue(uint32_t group0, uint32_t group1, +                              uint32_t group2, uint32_t group3) +{ +    uint16_t regData; + +    regData = (group0 & 0x3F) | ((group1 & 0x3F) << 6); +	if (rtl8366_writeRegister(RTL8366S_LED_0_1_FORCE_REG, regData)) { +        printf("rtl8366s_setLedForceValue: failed to set led register!\n"); +        return -1; +	} + +    regData = (group2 & 0x3F) | ((group3 & 0x3F) << 6); +	if (rtl8366_writeRegister(RTL8366S_LED_2_3_FORCE_REG, regData)) { +        printf("rtl8366s_setLedForceValue: failed to set led register!\n"); +        return -1; +	} + +	return 0; +} + +int rtl8366s_initChip(void) +{ +    uint32_t ledGroup, i = 0; +    uint16_t regData; +    uint8_t ledData[RTL8366S_LED_GROUP_MAX]; +	const uint16_t (*chipData)[2]; + +	const uint16_t chipB[][2] = +	{ +		{0x0000,	0x0038},{0x8100,	0x1B37},{0xBE2E,	0x7B9F},{0xBE2B,	0xA4C8}, +		{0xBE74,	0xAD14},{0xBE2C,	0xDC00},{0xBE69,	0xD20F},{0xBE3B,	0xB414}, +		{0xBE24,	0x0000},{0xBE23,	0x00A1},{0xBE22,	0x0008},{0xBE21,	0x0120}, +		{0xBE20,	0x1000},{0xBE24,	0x0800},{0xBE24,	0x0000},{0xBE24,	0xF000}, +		{0xBE23,	0xDF01},{0xBE22,	0xDF20},{0xBE21,	0x101A},{0xBE20,	0xA0FF}, +		{0xBE24,	0xF800},{0xBE24,	0xF000},{0x0242,	0x02BF},{0x0245,	0x02BF}, +		{0x0248,	0x02BF},{0x024B,	0x02BF},{0x024E,	0x02BF},{0x0251,	0x02BF}, +		{0x0230,	0x0A32},{0x0233,	0x0A32},{0x0236,	0x0A32},{0x0239,	0x0A32}, +		{0x023C,	0x0A32},{0x023F,	0x0A32},{0x0254,	0x0A3F},{0x0255,	0x0064}, +		{0x0256,	0x0A3F},{0x0257,	0x0064},{0x0258,	0x0A3F},{0x0259,	0x0064}, +		{0x025A,	0x0A3F},{0x025B,	0x0064},{0x025C,	0x0A3F},{0x025D,	0x0064}, +		{0x025E,	0x0A3F},{0x025F,	0x0064},{0x0260,	0x0178},{0x0261,	0x01F4}, +		{0x0262,	0x0320},{0x0263,	0x0014},{0x021D,	0x9249},{0x021E,	0x0000}, +		{0x0100,	0x0004},{0xBE4A,	0xA0B4},{0xBE40,	0x9C00},{0xBE41,	0x501D}, +		{0xBE48,	0x3602},{0xBE47,	0x8051},{0xBE4C,	0x6465},{0x8000,	0x1F00}, +		{0x8001,	0x000C},{0x8008,	0x0000},{0x8007,	0x0000},{0x800C,	0x00A5}, +		{0x8101,	0x02BC},{0xBE53,	0x0005},{0x8E45,	0xAFE8},{0x8013,	0x0005}, +		{0xBE4B,	0x6700},{0x800B,	0x7000},{0xBE09,	0x0E00}, +		{0xFFFF, 0xABCD} +	}; + +    const uint16_t chipDefault[][2] = +    { +        {0x0242, 0x02BF},{0x0245, 0x02BF},{0x0248, 0x02BF},{0x024B, 0x02BF}, +		{0x024E, 0x02BF},{0x0251, 0x02BF}, +		{0x0254, 0x0A3F},{0x0256, 0x0A3F},{0x0258, 0x0A3F},{0x025A, 0x0A3F}, +		{0x025C, 0x0A3F},{0x025E, 0x0A3F}, +		{0x0263, 0x007C},{0x0100, 0x0004}, +		{0xBE5B, 0x3500},{0x800E, 0x200F},{0xBE1D, 0x0F00},{0x8001, 0x5011}, +		{0x800A, 0xA2F4},{0x800B, 0x17A3},{0xBE4B, 0x17A3},{0xBE41, 0x5011}, +		{0xBE17, 0x2100},{0x8000, 0x8304},{0xBE40, 0x8304},{0xBE4A, 0xA2F4}, +		{0x800C, 0xA8D5},{0x8014, 0x5500},{0x8015, 0x0004},{0xBE4C, 0xA8D5}, +		{0xBE59, 0x0008},{0xBE09, 0x0E00},{0xBE36, 0x1036},{0xBE37, 0x1036}, +		{0x800D, 0x00FF},{0xBE4D, 0x00FF}, +		{0xFFFF, 0xABCD} +    }; + +	DBG("rtl8366s_initChip\n"); + +    /* save current led config and set to led force */ +    for (ledGroup = 0; ledGroup < RTL8366S_LED_GROUP_MAX; ledGroup++) { +        if (rtl8366s_getLedConfig(ledGroup, &ledData[ledGroup])) +            return -1; + +        if (rtl8366s_setLedConfig(ledGroup, RTL8366S_LEDCONF_LEDFORCE)) +            return -1; +    } + +    if (rtl8366s_setLedForceValue(0,0,0,0)) +        return -1; + +    if (rtl8366_readRegister(RTL8366S_MODEL_ID_REG, ®Data)) +        return -1; + +	switch (regData) +	{ +		case 0x0000: +			chipData = chipB; +			break; + +		case RTL8366S_MODEL_8366SR: +			chipData = chipDefault; +			break; + +		default: +			printf("rtl8366s_initChip: unsupported chip found!\n"); +			return -1; +	} + +    DBG("rtl8366s_initChip: found %x chip\n", regData); + +    while ((chipData[i][0] != 0xFFFF) && (chipData[i][1] != 0xABCD)) { + +        /* phy settings*/ +        if ((chipData[i][0] & 0xBE00) == 0xBE00) { +            if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, +                                      RTL8366S_PHY_CTRL_WRITE)) +                return -1; +        } + +        if (rtl8366_writeRegister(chipData[i][0], chipData[i][1])) +            return -1; + +        i++; +    } + +    /* chip needs some time */ +    udelay(100 * 1000); + +    /* restore led config */ +    for (ledGroup = 0; ledGroup < RTL8366S_LED_GROUP_MAX; ledGroup++) { +        if (rtl8366s_setLedConfig(ledGroup, ledData[ledGroup])) +            return -1; +    } + +    return 0; +} + +int rtl8366s_initialize(void) +{ +	uint16_t regData; + +    DBG("rtl8366s_initialize: start setup\n"); + +    smi_init(); + +	rtl8366_readRegister(RTL8366S_CHIP_ID_REG, ®Data); +	DBG("Realtek 8366SR switch ID %#04x\n", regData); + +	if (regData != 0x8366) { +		printf("rtl8366s_initialize: found unsupported switch\n"); +		return -1; +	} + +    if (rtl8366s_initChip()) { +        printf("rtl8366s_initialize: init chip failed\n"); +        return -1; +    } + +	if (rtl8366s_setGreenEthernet(1, 1)) { +       printf("rtl8366s_initialize: set green ethernet failed\n"); +       return -1; +   } + +   	/* Set port 5 noTag and don't dropUnda */ +	if (rtl8366s_setCPUPort(5, 1, 0)) { +		printf("rtl8366s_initialize: set CPU port failed\n"); +		return -1; +	} + +    return 0; +} | 
