blob: 5e99cb3cf381a8431a2dac1d21fb3f507198bd01 [file] [log] [blame]
/*
* Copyright (C) 2012 Realtek Semiconductor Corp.
* All Rights Reserved.
*
* This program is the proprietary software of Realtek Semiconductor
* Corporation and/or its licensors, and only be used, duplicated,
* modified or distributed under the authorized license from Realtek.
*
* ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
*
* $Revision: $
* $Date: $
*
* Purpose : RTK switch driver module init for RTL8367/RTL8367B
* Feature : Init switch and configure it for operation
*
*/
#include "rtl8367b_init.h"
#include "rtl8367b_smi.h"
#include <asm/arch/arasan_emac_ahb.h>
ret_t rtl8367b_poll_linkup(struct emac_private *priv)
{
/* either PHY1 or PHY2 should have link established */
const uint32_t delay_us = 1000;
const int poll_secs = 2;
const uint32_t mask = PhyLinkIsUp | PhyAutoNegComplete;
const unsigned long start = get_timer(0);
printf("%s: polling for link up...\n", __FUNCTION__);
while (1) {
int phy;
for (phy = RTL8367B_QTN_EXT_PHY_ADDR_MIN; phy <= RTL8367B_QTN_EXT_PHY_ADDR_MAX; phy++) {
uint32_t val;
if (rtl8367b_getAsicPHYReg(phy, PhyBMSR, &val) != RT_ERR_OK) {
return -1;
}
if ((val & mask) == mask) {
printf("%s: link found, phy %d\n",
__FUNCTION__, phy);
return 0;
}
}
if (ctrlc() || (get_timer(start) > (poll_secs * CONFIG_SYS_HZ))) {
break;
}
udelay(delay_us);
}
printf("%s: no link found\n", __FUNCTION__);
return -1;
}
static void rtl8367b_ext_reset(void)
{
const int delay_us = 20000;
uint32_t mask = RUBY_SYS_CTL_RESET_EXT;
writel(mask, RUBY_SYS_CTL_CPU_VEC_MASK);
writel(0, RUBY_SYS_CTL_CPU_VEC);
udelay(delay_us);
writel(mask, RUBY_SYS_CTL_CPU_VEC);
udelay(delay_us);
writel(0, RUBY_SYS_CTL_CPU_VEC);
udelay(delay_us);
writel(0, RUBY_SYS_CTL_CPU_VEC_MASK);
}
static uint32_t smi_mdio_read_adapter(struct emac_private *priv, uint8_t reg)
{
uint32_t val;
if (rtl8367b_getAsicPHYReg(priv->phy_addr, reg, &val) != RT_ERR_OK) {
return MDIO_READ_FAIL;
}
return val;
}
static int smi_mdio_write_adapter(struct emac_private *priv, uint8_t reg, uint16_t value)
{
return rtl8367b_setAsicPHYReg(priv->phy_addr, reg, value);
}
static ret_t rtl8367b_init_port(rtk_port_mac_ability_t *mac_cfg, rtk_mode_ext_t mode, rtk_ext_port_t port)
{
ret_t ret;
rtk_data_t rgmii_tx_delay = 0;
rtk_data_t rgmii_rx_delay = 4;
ret = rtk_port_macForceLinkExt_set(port, mode, mac_cfg);
if (RT_ERR_OK != ret) {
printf("rtk_port_macForceLinkExt_set failed, port %d (%d)\n", port, ret);
return ret;
}
ret = rtk_port_rgmiiDelayExt_set(port, rgmii_tx_delay, rgmii_rx_delay);
if (RT_ERR_OK != ret) {
printf("rtk_port_rgmiiDelayExt_set failed, port %d (%d)\n", port, ret);
return ret;
}
return RT_ERR_OK;
}
/* Function Name:
* rtl8367b_init
* Description:
* Initialize RTL8367B Chipsets
* Return:
* RT_ERR_OK - Success
* RT_ERR_FAILED - Failure
* Note:
* None
*/
ret_t rtl8367b_init(struct emac_private *priv, uint32_t emac_cfg)
{
ret_t ret = RT_ERR_OK;
rtk_port_mac_ability_t mac_cfg;
rtk_mode_ext_t mode;
printf("%s...\n", __FUNCTION__);
priv->mdio->read = &smi_mdio_read_adapter;
priv->mdio->write = &smi_mdio_write_adapter;
rtl8367b_ext_reset();
smi_mdio_base_set(priv->mdio->base);
ret = rtk_switch_init();
if (RT_ERR_OK != ret) {
printf("rtl8635MB switch init failed!!! (%d)\n", ret);
return ret;
}
/*
* Set external interface 0 to RGMII with Force mode, 1000M, Full-duplex,
* enable TX&RX pause
*/
mode = MODE_EXT_RGMII;
mac_cfg.forcemode = MAC_FORCE;
mac_cfg.speed = SPD_1000M;
mac_cfg.duplex = FULL_DUPLEX;
mac_cfg.link = PORT_LINKUP;
mac_cfg.nway = DISABLED;
mac_cfg.txpause = ENABLED;
mac_cfg.rxpause = ENABLED;
if (emac_cfg & EMAC_PHY_RTL8363SB_P0) {
ret = rtl8367b_init_port(&mac_cfg, mode, EXT_PORT_0);
if (RT_ERR_OK != ret) {
return ret;
}
}
if (emac_cfg & EMAC_PHY_RTL8363SB_P1) {
ret = rtl8367b_init_port(&mac_cfg, mode, EXT_PORT_1);
if (RT_ERR_OK != ret) {
return ret;
}
}
printf("%s completed successfully\n", __FUNCTION__);
return ret;
}