blob: ad822bb55879e103f1a5541d53650b03e60fcc18 [file] [log] [blame]
/* Copyright 2016 MediaTek Inc.
* Author: Nelson Chang <nelson.chang@mediatek.com>
* Author: Carlos Huang <carlos.huang@mediatek.com>
* Author: Harry Huang <harry.huang@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include "raether.h"
void enable_auto_negotiate(struct END_DEVICE *ei_local)
{
u32 reg_value;
pr_info("=================================\n");
pr_info("enable_auto_negotiate\n");
/* FIXME: we don't know how to deal with PHY end addr */
reg_value = sys_reg_read(ESW_PHY_POLLING);
reg_value |= (1 << 31);
reg_value &= ~(0x1f);
reg_value &= ~(0x1f << 8);
if (ei_local->architecture & (GE2_RGMII_AN | GE2_SGMII_AN)) {
/* setup PHY address for auto polling (Start Addr). */
/*avoid end phy address = 0 */
reg_value |= ((mac_to_gigaphy_mode_addr2 - 1) & 0x1f);
/* setup PHY address for auto polling (End Addr). */
reg_value |= (mac_to_gigaphy_mode_addr2 << 8);
} else if (ei_local->architecture & (GE1_RGMII_AN | GE1_SGMII_AN | LEOPARD_EPHY)) {
/* setup PHY address for auto polling (Start Addr). */
reg_value |= (mac_to_gigaphy_mode_addr << 0);
/* setup PHY address for auto polling (End Addr). */
reg_value |= ((mac_to_gigaphy_mode_addr + 1) << 8);
}
sys_reg_write(ESW_PHY_POLLING, reg_value);
}
void ra2880stop(struct END_DEVICE *ei_local)
{
unsigned int reg_value;
pr_info("ra2880stop()...");
reg_value = sys_reg_read(DMA_GLO_CFG);
reg_value &= ~(TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
sys_reg_write(DMA_GLO_CFG, reg_value);
pr_info("Done\n");
}
void set_mac_address(unsigned char p[6])
{
unsigned long reg_value;
reg_value = (p[0] << 8) | (p[1]);
sys_reg_write(GDMA1_MAC_ADRH, reg_value);
reg_value = (unsigned long)((p[2] << 24) | (p[3] << 16) | (p[4] << 8) | p[5]);
sys_reg_write(GDMA1_MAC_ADRL, reg_value);
}
void set_mac2_address(unsigned char p[6])
{
unsigned long reg_value;
reg_value = (p[0] << 8) | (p[1]);
sys_reg_write(GDMA2_MAC_ADRH, reg_value);
reg_value = (unsigned long)((p[2] << 24) | (p[3] << 16) | (p[4] << 8) | p[5]);
sys_reg_write(GDMA2_MAC_ADRL, reg_value);
}
static int getnext(const char *src, int separator, char *dest)
{
char *c;
int len;
if (!src || !dest)
return -1;
c = strchr(src, separator);
if (!c) {
strcpy(dest, src);
return -1;
}
len = c - src;
strncpy(dest, src, len);
dest[len] = '\0';
return len + 1;
}
int str_to_ip(unsigned int *ip, const char *str)
{
int len;
const char *ptr = str;
char buf[128];
unsigned char c[4];
int i;
int ret;
for (i = 0; i < 3; ++i) {
len = getnext(ptr, '.', buf);
if (len == -1)
return 1; /* parse error */
ret = kstrtoul(buf, 10, (unsigned long *)&c[i]);
if (ret)
return ret;
ptr += len;
}
ret = kstrtoul(ptr, 0, (unsigned long *)&c[3]);
if (ret)
return ret;
*ip = (c[0] << 24) + (c[1] << 16) + (c[2] << 8) + c[3];
return 0;
}
void set_ge1_force_1000(void)
{
sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0x100, 0x2105e33b);
}
void set_ge2_force_1000(void)
{
sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0x200, 0x2105e33b);
}
void set_ge1_an(void)
{
sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0x100, 0x21056300);
}
void set_ge2_an(void)
{
sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0x200, 0x21056300);
}
void set_ge2_gmii(void)
{
void __iomem *virt_addr;
unsigned int reg_value;
virt_addr = ioremap(ETHSYS_BASE, 0x20);
reg_value = sys_reg_read(virt_addr + 0x14);
/*[15:14] =0 RGMII, [8] = 0 SGMII disable*/
reg_value = reg_value & (~0xc100);
reg_value = reg_value | 0x4000;
sys_reg_write(virt_addr + 0x14, reg_value);
iounmap(virt_addr);
}
void set_ge0_gmii(void)
{
void __iomem *virt_addr;
unsigned int reg_value;
virt_addr = ioremap(ETHSYS_BASE, 0x20);
reg_value = sys_reg_read(virt_addr + 0x14);
/*[15:14] =0 RGMII, [8] = 0 SGMII disable*/
reg_value = reg_value & (~0xc000);
reg_value = reg_value | 0x400;
sys_reg_write(virt_addr + 0x14, reg_value);
iounmap(virt_addr);
}
void set_ge2_force_link_down(void)
{
sys_reg_write(ETHDMASYS_ETH_MAC_BASE + 0x200, 0x2105e300);
}