3 * Michael Kurz <michi.kurz@googlemail.com>.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 #include MII_GPIOINCLUDE
34 #define DBG(fmt,args...) printf (fmt ,##args)
36 #define DBG(fmt,args...)
40 //-------------------------------------------------------------------
42 //-------------------------------------------------------------------
46 static void smi_init(void)
57 static void smi_start(void)
60 * rtl8366 chip needs a extra clock with
61 * SDA high before start condition
64 /* set gpio pins output */
69 /* set initial state: SCK:0, SDA:1 */
90 static void smi_stop(void)
93 * rtl8366 chip needs a extra clock with
94 * SDA high after stop condition
116 /* set gpio pins input */
121 static void smi_writeBits(uint32_t data
, uint8_t length
)
125 for( ; length
> 0; length
--) {
129 test
= (((data
& (1 << (length
- 1))) != 0) ? 1 : 0);
140 static uint32_t smi_readBits(uint8_t length
)
146 for(ret
= 0 ; length
> 0; length
--) {
163 static int smi_waitAck(void)
167 while (smi_readBits(1)) {
176 static int smi_read(uint32_t reg
, uint32_t *data
)
180 /* send start condition */
182 /* send CTRL1 code: 0b1010*/
183 smi_writeBits(0x0a, 4);
184 /* send CTRL2 code: 0b100 */
185 smi_writeBits(0x04, 3);
186 /* send READ command */
187 smi_writeBits(0x01, 1);
193 /* send address low */
194 smi_writeBits(reg
& 0xFF, 8);
198 /* send address high */
199 smi_writeBits((reg
& 0xFF00) >> 8, 8);
205 rawData
= (smi_readBits(8) & 0xFF);
209 rawData
|= (smi_readBits(8) & 0xFF) << 8;
213 /* send stop condition */
222 static int smi_write(uint32_t reg
, uint32_t data
)
224 /* send start condition */
226 /* send CTRL1 code: 0b1010*/
227 smi_writeBits(0x0a, 4);
228 /* send CTRL2 code: 0b100 */
229 smi_writeBits(0x04, 3);
230 /* send WRITE command */
231 smi_writeBits(0x00, 1);
237 /* send address low */
238 smi_writeBits(reg
& 0xFF, 8);
242 /* send address high */
243 smi_writeBits((reg
& 0xFF00) >> 8, 8);
249 smi_writeBits(data
& 0xFF, 8);
254 smi_writeBits((data
& 0xFF00) >> 8, 8);
259 /* send stop condition */
266 //-------------------------------------------------------------------
267 // Switch register read / write functions
268 //-------------------------------------------------------------------
269 static int rtl8366_readRegister(uint32_t reg
, uint16_t *data
)
273 DBG("rtl8366: read register=%#04x, data=", reg
);
275 if (smi_read(reg
, ®Data
)) {
276 printf("\nrtl8366 smi read failed!\n");
283 DBG("%#04x\n", regData
);
288 static int rtl8366_writeRegister(uint32_t reg
, uint16_t data
)
290 DBG("rtl8366: write register=%#04x, data=%#04x\n", reg
, data
);
292 if (smi_write(reg
, data
)) {
293 printf("rtl8366 smi write failed!\n");
300 static int rtl8366_setRegisterBit(uint32_t reg
, uint32_t bitNum
, uint32_t value
)
307 if (rtl8366_readRegister(reg
, ®Data
))
311 regData
|= (1 << bitNum
);
313 regData
&= ~(1 << bitNum
);
315 if (rtl8366_writeRegister(reg
, regData
))
321 //-------------------------------------------------------------------
322 // MII PHY read / write functions
323 //-------------------------------------------------------------------
324 static int rtl8366_getPhyReg(uint32_t phyNum
, uint32_t reg
, uint16_t *data
)
326 uint16_t phyAddr
, regData
;
328 if (phyNum
> RTL8366S_PHY_NO_MAX
) {
329 printf("rtl8366s: invalid phy number!\n");
333 if (phyNum
> RTL8366S_PHY_ADDR_MAX
) {
334 printf("rtl8366s: invalid phy register number!\n");
338 if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG
,
339 RTL8366S_PHY_CTRL_READ
))
342 phyAddr
= 0x8000 | (1 << (phyNum
+ RTL8366S_PHY_NO_OFFSET
))
343 | (reg
& RTL8366S_PHY_REG_MASK
);
344 if (rtl8366_writeRegister(phyAddr
, 0))
347 if (rtl8366_readRegister(RTL8366S_PHY_ACCESS_DATA_REG
, ®Data
))
356 static int rtl8366_setPhyReg(uint32_t phyNum
, uint32_t reg
, uint16_t data
)
360 if (phyNum
> RTL8366S_PHY_NO_MAX
) {
361 printf("rtl8366s: invalid phy number!\n");
365 if (phyNum
> RTL8366S_PHY_ADDR_MAX
) {
366 printf("rtl8366s: invalid phy register number!\n");
370 if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG
,
371 RTL8366S_PHY_CTRL_WRITE
))
374 phyAddr
= 0x8000 | (1 << (phyNum
+ RTL8366S_PHY_NO_OFFSET
))
375 | (reg
& RTL8366S_PHY_REG_MASK
);
376 if (rtl8366_writeRegister(phyAddr
, data
))
382 static int rtl8366_miiread(char *devname
, uchar phy_adr
, uchar reg
, ushort
*data
)
386 DBG("rtl8366_miiread: devname=%s, addr=%#02x, reg=%#02x\n",
387 devname
, phy_adr
, reg
);
389 if (strcmp(devname
, RTL8366_DEVNAME
) != 0)
392 if (rtl8366_getPhyReg(phy_adr
, reg
, ®Data
)) {
393 printf("rtl8366_miiread: write failed!\n");
403 static int rtl8366_miiwrite(char *devname
, uchar phy_adr
, uchar reg
, ushort data
)
405 DBG("rtl8366_miiwrite: devname=%s, addr=%#02x, reg=%#02x, data=%#04x\n",
406 devname
, phy_adr
, reg
, data
);
408 if (strcmp(devname
, RTL8366_DEVNAME
) != 0)
411 if (rtl8366_setPhyReg(phy_adr
, reg
, data
)) {
412 printf("rtl8366_miiwrite: write failed!\n");
419 int rtl8366_mii_register(bd_t
*bis
)
421 miiphy_register(strdup(RTL8366_DEVNAME
), rtl8366_miiread
,
428 //-------------------------------------------------------------------
429 // Switch management functions
430 //-------------------------------------------------------------------
432 int rtl8366s_setGreenFeature(uint32_t tx
, uint32_t rx
)
434 if (rtl8366_setRegisterBit(RTL8366S_GREEN_FEATURE_REG
,
435 RTL8366S_GREEN_FEATURE_TX_BIT
, tx
))
438 if (rtl8366_setRegisterBit(RTL8366S_GREEN_FEATURE_REG
,
439 RTL8366S_GREEN_FEATURE_RX_BIT
, rx
))
445 int rtl8366s_setPowerSaving(uint32_t phyNum
, uint32_t enabled
)
449 if (phyNum
> RTL8366S_PHY_NO_MAX
)
452 if (rtl8366_getPhyReg(phyNum
, 12, ®Data
))
456 regData
|= (1 << 12);
458 regData
&= ~(1 << 12);
460 if (rtl8366_setPhyReg(phyNum
, 12, regData
))
466 int rtl8366s_setGreenEthernet(uint32_t greenFeature
, uint32_t powerSaving
)
471 const uint16_t greenSettings
[][2] =
481 if (rtl8366_readRegister(RTL8366S_MODEL_ID_REG
, ®Data
))
487 for (i
= 0; i
< 6; i
++) {
488 if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG
, RTL8366S_PHY_CTRL_WRITE
))
490 if (rtl8366_writeRegister(greenSettings
[i
][0], greenSettings
[i
][1]))
495 case RTL8366S_MODEL_8366SR
:
496 if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG
, RTL8366S_PHY_CTRL_WRITE
))
498 if (rtl8366_writeRegister(greenSettings
[0][0], greenSettings
[0][1]))
503 printf("rtl8366s_initChip: unsupported chip found!\n");
507 if (rtl8366s_setGreenFeature(greenFeature
, powerSaving
))
510 for (phyNum
= 0; phyNum
<= RTL8366S_PHY_NO_MAX
; phyNum
++) {
511 if (rtl8366s_setPowerSaving(phyNum
, powerSaving
))
518 int rtl8366s_setCPUPortMask(uint8_t port
, uint32_t enabled
)
521 printf("rtl8366s_setCPUPortMask: invalid port number\n");
525 return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG
, port
, enabled
);
528 int rtl8366s_setCPUDisableInsTag(uint32_t enable
)
530 return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG
,
531 RTL8366S_CPU_INSTAG_BIT
, enable
);
534 int rtl8366s_setCPUDropUnda(uint32_t enable
)
536 return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG
,
537 RTL8366S_CPU_DRP_BIT
, enable
);
540 int rtl8366s_setCPUPort(uint8_t port
, uint32_t noTag
, uint32_t dropUnda
)
545 printf("rtl8366s_setCPUPort: invalid port number\n");
550 for(i
= 0; i
< 6; i
++)
552 if(rtl8366s_setCPUPortMask(i
, 0)){
553 printf("rtl8366s_setCPUPort: rtl8366s_setCPUPortMask failed\n");
558 if(rtl8366s_setCPUPortMask(port
, 1)){
559 printf("rtl8366s_setCPUPort: rtl8366s_setCPUPortMask failed\n");
563 if(rtl8366s_setCPUDisableInsTag(noTag
)){
564 printf("rtl8366s_setCPUPort: rtl8366s_setCPUDisableInsTag fail\n");
568 if(rtl8366s_setCPUDropUnda(dropUnda
)){
569 printf("rtl8366s_setCPUPort: rtl8366s_setCPUDropUnda fail\n");
576 int rtl8366s_setLedConfig(uint32_t ledNum
, uint8_t config
)
580 if(ledNum
>= RTL8366S_LED_GROUP_MAX
) {
581 DBG("rtl8366s_setLedConfig: invalid led group\n");
585 if(config
> RTL8366S_LEDCONF_LEDFORCE
) {
586 DBG("rtl8366s_setLedConfig: invalid led config\n");
590 if (rtl8366_readRegister(RTL8366S_LED_INDICATED_CONF_REG
, ®Data
)) {
591 printf("rtl8366s_setLedConfig: failed to get led register!\n");
595 regData
&= ~(0xF << (ledNum
* 4));
596 regData
|= config
<< (ledNum
* 4);
598 if (rtl8366_writeRegister(RTL8366S_LED_INDICATED_CONF_REG
, regData
)) {
599 printf("rtl8366s_setLedConfig: failed to set led register!\n");
606 int rtl8366s_getLedConfig(uint32_t ledNum
, uint8_t *config
)
610 if(ledNum
>= RTL8366S_LED_GROUP_MAX
) {
611 DBG("rtl8366s_getLedConfig: invalid led group\n");
615 if (rtl8366_readRegister(RTL8366S_LED_INDICATED_CONF_REG
, ®Data
)) {
616 printf("rtl8366s_getLedConfig: failed to get led register!\n");
621 *config
= (regData
>> (ledNum
* 4)) & 0xF;
626 int rtl8366s_setLedForceValue(uint32_t group0
, uint32_t group1
,
627 uint32_t group2
, uint32_t group3
)
631 regData
= (group0
& 0x3F) | ((group1
& 0x3F) << 6);
632 if (rtl8366_writeRegister(RTL8366S_LED_0_1_FORCE_REG
, regData
)) {
633 printf("rtl8366s_setLedForceValue: failed to set led register!\n");
637 regData
= (group2
& 0x3F) | ((group3
& 0x3F) << 6);
638 if (rtl8366_writeRegister(RTL8366S_LED_2_3_FORCE_REG
, regData
)) {
639 printf("rtl8366s_setLedForceValue: failed to set led register!\n");
646 int rtl8366s_initChip(void)
648 uint32_t ledGroup
, i
= 0;
650 uint8_t ledData
[RTL8366S_LED_GROUP_MAX
];
651 const uint16_t (*chipData
)[2];
653 const uint16_t chipB
[][2] =
655 {0x0000, 0x0038},{0x8100, 0x1B37},{0xBE2E, 0x7B9F},{0xBE2B, 0xA4C8},
656 {0xBE74, 0xAD14},{0xBE2C, 0xDC00},{0xBE69, 0xD20F},{0xBE3B, 0xB414},
657 {0xBE24, 0x0000},{0xBE23, 0x00A1},{0xBE22, 0x0008},{0xBE21, 0x0120},
658 {0xBE20, 0x1000},{0xBE24, 0x0800},{0xBE24, 0x0000},{0xBE24, 0xF000},
659 {0xBE23, 0xDF01},{0xBE22, 0xDF20},{0xBE21, 0x101A},{0xBE20, 0xA0FF},
660 {0xBE24, 0xF800},{0xBE24, 0xF000},{0x0242, 0x02BF},{0x0245, 0x02BF},
661 {0x0248, 0x02BF},{0x024B, 0x02BF},{0x024E, 0x02BF},{0x0251, 0x02BF},
662 {0x0230, 0x0A32},{0x0233, 0x0A32},{0x0236, 0x0A32},{0x0239, 0x0A32},
663 {0x023C, 0x0A32},{0x023F, 0x0A32},{0x0254, 0x0A3F},{0x0255, 0x0064},
664 {0x0256, 0x0A3F},{0x0257, 0x0064},{0x0258, 0x0A3F},{0x0259, 0x0064},
665 {0x025A, 0x0A3F},{0x025B, 0x0064},{0x025C, 0x0A3F},{0x025D, 0x0064},
666 {0x025E, 0x0A3F},{0x025F, 0x0064},{0x0260, 0x0178},{0x0261, 0x01F4},
667 {0x0262, 0x0320},{0x0263, 0x0014},{0x021D, 0x9249},{0x021E, 0x0000},
668 {0x0100, 0x0004},{0xBE4A, 0xA0B4},{0xBE40, 0x9C00},{0xBE41, 0x501D},
669 {0xBE48, 0x3602},{0xBE47, 0x8051},{0xBE4C, 0x6465},{0x8000, 0x1F00},
670 {0x8001, 0x000C},{0x8008, 0x0000},{0x8007, 0x0000},{0x800C, 0x00A5},
671 {0x8101, 0x02BC},{0xBE53, 0x0005},{0x8E45, 0xAFE8},{0x8013, 0x0005},
672 {0xBE4B, 0x6700},{0x800B, 0x7000},{0xBE09, 0x0E00},
676 const uint16_t chipDefault
[][2] =
678 {0x0242, 0x02BF},{0x0245, 0x02BF},{0x0248, 0x02BF},{0x024B, 0x02BF},
679 {0x024E, 0x02BF},{0x0251, 0x02BF},
680 {0x0254, 0x0A3F},{0x0256, 0x0A3F},{0x0258, 0x0A3F},{0x025A, 0x0A3F},
681 {0x025C, 0x0A3F},{0x025E, 0x0A3F},
682 {0x0263, 0x007C},{0x0100, 0x0004},
683 {0xBE5B, 0x3500},{0x800E, 0x200F},{0xBE1D, 0x0F00},{0x8001, 0x5011},
684 {0x800A, 0xA2F4},{0x800B, 0x17A3},{0xBE4B, 0x17A3},{0xBE41, 0x5011},
685 {0xBE17, 0x2100},{0x8000, 0x8304},{0xBE40, 0x8304},{0xBE4A, 0xA2F4},
686 {0x800C, 0xA8D5},{0x8014, 0x5500},{0x8015, 0x0004},{0xBE4C, 0xA8D5},
687 {0xBE59, 0x0008},{0xBE09, 0x0E00},{0xBE36, 0x1036},{0xBE37, 0x1036},
688 {0x800D, 0x00FF},{0xBE4D, 0x00FF},
692 DBG("rtl8366s_initChip\n");
694 /* save current led config and set to led force */
695 for (ledGroup
= 0; ledGroup
< RTL8366S_LED_GROUP_MAX
; ledGroup
++) {
696 if (rtl8366s_getLedConfig(ledGroup
, &ledData
[ledGroup
]))
699 if (rtl8366s_setLedConfig(ledGroup
, RTL8366S_LEDCONF_LEDFORCE
))
703 if (rtl8366s_setLedForceValue(0,0,0,0))
706 if (rtl8366_readRegister(RTL8366S_MODEL_ID_REG
, ®Data
))
715 case RTL8366S_MODEL_8366SR
:
716 chipData
= chipDefault
;
720 printf("rtl8366s_initChip: unsupported chip found!\n");
724 DBG("rtl8366s_initChip: found %x chip\n", regData
);
726 while ((chipData
[i
][0] != 0xFFFF) && (chipData
[i
][1] != 0xABCD)) {
729 if ((chipData
[i
][0] & 0xBE00) == 0xBE00) {
730 if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG
,
731 RTL8366S_PHY_CTRL_WRITE
))
735 if (rtl8366_writeRegister(chipData
[i
][0], chipData
[i
][1]))
741 /* chip needs some time */
744 /* restore led config */
745 for (ledGroup
= 0; ledGroup
< RTL8366S_LED_GROUP_MAX
; ledGroup
++) {
746 if (rtl8366s_setLedConfig(ledGroup
, ledData
[ledGroup
]))
753 int rtl8366s_initialize(void)
757 DBG("rtl8366s_initialize: start setup\n");
761 rtl8366_readRegister(RTL8366S_CHIP_ID_REG
, ®Data
);
762 DBG("Realtek 8366SR switch ID %#04x\n", regData
);
764 if (regData
!= 0x8366) {
765 printf("rtl8366s_initialize: found unsupported switch\n");
769 if (rtl8366s_initChip()) {
770 printf("rtl8366s_initialize: init chip failed\n");
774 if (rtl8366s_setGreenEthernet(1, 1)) {
775 printf("rtl8366s_initialize: set green ethernet failed\n");
779 /* Set port 5 noTag and don't dropUnda */
780 if (rtl8366s_setCPUPort(5, 1, 0)) {
781 printf("rtl8366s_initialize: set CPU port failed\n");