Hello everyone,
We have Implemented Ethernet phy related changes in u-boot net driver MCSDK for SFP integration in TI k2hk evm , but we need to implement same changes in PDK for same board but since the structure of the program is different from MCSDK to PDK I need your support regarding this ethernet changes so how to proceed with this.
The corresponding MCSDK changes to is given in below ethernet driver file keystone_net.c file and phy address and other info is saved in board/ti/ks2_evm/board_k2hk.c.
Thanks and regards,
Phaneesh A Kashyap
/*
* Ethernet driver for TI KS2 EVM.
*
* Copyright (C) 2012 Texas Instruments Incorporated
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <common.h>
#include <command.h>
#include <asm/arch/hardware.h>
#include <net.h>
#include <miiphy.h>
#include <malloc.h>
#include <asm/arch/emac_defs.h>
#include <asm/arch/psc_defs.h>
#include <asm/arch/keystone_nav.h>
unsigned int emac_dbg = 0;
#define debug_emac(fmt, args...) if (emac_dbg) printf(fmt, ##args)
unsigned int emac_open = 0;
unsigned int xmac_open;
static unsigned int loopback_test = 0;
static unsigned int sys_has_mdio = 1;
#ifdef KS2_EMAC_GIG_ENABLE
#define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x)
#else
#define emac_gigabit_enable(x) /* no gigabit to enable */
#endif
#define RX_BUFF_NUMS 24
#define RX_BUFF_LEN 1520
#define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
#define PHY_CALC_MASK(fieldOffset, fieldLen, mask) \
if ((fieldLen + fieldOffset) >= 16) \
mask = (0 - (1 << fieldOffset)); \
else \
mask = (((1 << (fieldLen + fieldOffset))) - (1 << fieldOffset))
static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __attribute__((aligned(16)));
struct rx_buff_desc net_rx_buffs = {
.buff_ptr = rx_buffs,
.num_buffs = RX_BUFF_NUMS,
.buff_len = RX_BUFF_LEN,
.rx_flow = CPSW_NET_RX_FLOW,
};
extern int cpu_to_bus(u32 *ptr, u32 length);
static void keystone2_eth_mdio_enable(void);
static int gen_init_phy(int phy_addr);
static int gen_is_phy_connected(int phy_addr);
static int gen_get_link_speed(int phy_addr);
static int gen_auto_negotiate(int phy_addr);
static int marvell_88e1111_init_phy(int phy_addr);
static int marvell_88e1111_is_phy_connected(int phy_addr);
static int marvell_88e1111_get_link_speed(int phy_addr);
static int marvell_88e1111_auto_negotiate(int phy_addr);
void sgmii_serdes_setup_156p25mhz(void);
/* EMAC Addresses */
static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
phy_t phy;
#ifdef CONFIG_MCAST_TFTP
int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set)
{
return 0;
}
#endif
static void chip_delay(u32 del)
{
volatile unsigned int i;
for (i = 0; i < (del / 8); i++);
}
int keystone2_eth_read_mac_addr(struct eth_device *dev)
{
eth_priv_t *eth_priv;
u32 maca = 0;
u32 macb = 0;
eth_priv = (eth_priv_t*)dev->priv;
/* Read the e-fuse mac address */
if ((eth_priv->slave_port<=2) && IS_1GE(eth_priv)) {
maca = __raw_readl(MAC_ID_BASE_ADDR);
macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
// printf("LWS before maca--->%i macb--->%i \n",maca,macb);//added
/* tmp: workaround for MAC ID regs swapping issue */
if (!(maca & 0x00ff0000)) {
maca = macb;
macb = __raw_readl(MAC_ID_BASE_ADDR);
}
// printf("LWS after maca--->%i macb--->%i \n",&maca,&macb);//added
}
dev->enetaddr[0] = (macb >> 8) & 0xff;
dev->enetaddr[1] = (macb >> 0) & 0xff;
dev->enetaddr[2] = (maca >> 24) & 0xff;
dev->enetaddr[3] = (maca >> 16) & 0xff;
dev->enetaddr[4] = (maca >> 8) & 0xff;
dev->enetaddr[5] = (maca >> 0) & 0xff;
// printf("LWS maca--->%i macb--->%i \n",&maca,&macb); //added
return 0;
}
static void keystone2_eth_mdio_enable(void)
{
u_int32_t clkdiv;
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
// printf("LWS Inside_mido_enable\n");
writel((clkdiv & 0xffff) |
MDIO_CONTROL_ENABLE |
MDIO_CONTROL_FAULT |
MDIO_CONTROL_FAULT_ENABLE,
&adap_mdio->CONTROL);
while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE)
;
}
/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
{
int tmp;
unsigned int tmp1 = readl(&adap_mdio->USERACCESS0);
// printf("LWS read_val_adap_mdio = %u \n",tmp1);
while (tmp1 & MDIO_USERACCESS0_GO)
;
writel(MDIO_USERACCESS0_GO |
MDIO_USERACCESS0_WRITE_READ |
((reg_num & 0x1f) << 21) |
((phy_addr & 0x1f) << 16),
&adap_mdio->USERACCESS0);
/* Wait for command to complete */
while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO)
;
if (tmp & MDIO_USERACCESS0_ACK) {
*data = tmp & 0xffff;
return(0);
}
*data = -1;
return(-1);
}
/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
{
// printf("LWS adap_mdio->USERACCESS0-----> %u \n",adap_mdio->USERACCESS0);
// printf("LWS value in USERACCESS0-----> %x \n",readl(&adap_mdio->USERACCESS0));
while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
;
writel(MDIO_USERACCESS0_GO |
MDIO_USERACCESS0_WRITE_WRITE |
((reg_num & 0x1f) << 21) |
((phy_addr & 0x1f) << 16) |
(data & 0xffff),
&adap_mdio->USERACCESS0);
/* Wait for command to complete */
while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
;
return(0);
}
/* Read bits from a register */
int keystone2_eth_phy_readbits(u8 phy_addr, u8 reg_num, u16 offset,
u16 len, u16 *data)
{
u16 reg, mask;
PHY_CALC_MASK(offset, len, mask);
if (keystone2_eth_phy_read(phy_addr, reg_num, ®) != 0)
return -1;
*data = (reg & mask) >> offset;
return 0;
}
/* Write bits to a register */
int keystone2_eth_phy_writebits(u8 phy_addr, u8 reg_num, u16 offset, u16 len,
u16 data)
{
u16 reg, mask;
PHY_CALC_MASK(offset, len, mask);
if (keystone2_eth_phy_read(phy_addr, reg_num, ®) != 0)
return -1;
reg &= ~mask;
reg |= data << offset;
if (keystone2_eth_phy_write(phy_addr, reg_num, reg) != 0)
return -1;
return 0;
}
/* PHY functions for a generic PHY */
static int __attribute__((unused)) gen_init_phy(int phy_addr)
{
int ret = -1;
if (!gen_get_link_speed(phy_addr)) {
/* Try another time */
ret = gen_get_link_speed(phy_addr);
}
return(ret);
}
static int __attribute__((unused)) gen_is_phy_connected(int phy_addr)
{
u_int16_t dummy;
return keystone2_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
}
static int gen_get_link_speed(int phy_addr)
{
u_int16_t tmp;
// printf("Inside gen get link speed \n");
if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
(tmp & 0x04)) {
// printf("PHY address = %d and MII Status reg = %x \n",phy_addr+1,tmp);
#if 0
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr, 22,1 );
keystone2_eth_phy_read(phy_addr,0x01, &tmp);
printf("Port 2 Page 1 reg 1 = %x \n",tmp);
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr+1, 22,1 );
keystone2_eth_phy_read(phy_addr+1,0x01, &tmp);
printf("Port 3 Page 1 reg 1 = %x \n",tmp);
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr, 22,4 );
keystone2_eth_phy_read(phy_addr,17, &tmp);
printf("Port 2 Page 4 reg 17 = %x \n",tmp);
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr+1, 22,4 );
keystone2_eth_phy_read(phy_addr+1,17, &tmp);
printf("Port 3 Page 4 reg 17 = %x \n",tmp);
#endif
return(0);
}
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr, 22,1 );
keystone2_eth_phy_read(phy_addr,0x01, &tmp);
//printf("Port 2 Page 1 reg 1 = %x \n",tmp);
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr+1, 22,1 );
keystone2_eth_phy_read(phy_addr+1,0x01, &tmp);
//printf("Port 3 Page 1 reg 1 = %x \n",tmp);
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr, 22,4 );
keystone2_eth_phy_read(phy_addr,17, &tmp);
//printf("Port 2 Page 4 reg 17 = %x \n",tmp);
/*Fiber link status*/
keystone2_eth_phy_write(phy_addr+1, 22,4 );
keystone2_eth_phy_read(phy_addr+1,17, &tmp);
//printf("Port 3 Page 4 reg 17 = %x \n",tmp);
return(-1);
}
static int __attribute__((unused)) gen_auto_negotiate(int phy_addr)
{
u_int16_t tmp;
if (keystone2_eth_phy_read(phy_addr, MII_BMCR, &tmp))
return(-1);
/* Restart Auto_negotiation */
tmp |= BMCR_ANENABLE;
keystone2_eth_phy_write(phy_addr, MII_BMCR, tmp);
/*check AutoNegotiate complete */
udelay (10000);
if (keystone2_eth_phy_read(phy_addr, MII_BMSR, &tmp))
return(-1);
if (!(tmp & BMSR_ANEGCOMPLETE))
return(0);
return(gen_get_link_speed(phy_addr));
}
int marvell_88e1512_init_phy(int phy_addr)
{
/* As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512/88E1514
Rev A0, Errata Section 3.1 */
keystone2_eth_phy_write(phy_addr, 22, 0x00ff); /* reg page 0xff */
keystone2_eth_phy_write(phy_addr, 17, 0x214B);
keystone2_eth_phy_write(phy_addr, 16, 0x2144);
keystone2_eth_phy_write(phy_addr, 17, 0x0C28);
keystone2_eth_phy_write(phy_addr, 16, 0x2146);
keystone2_eth_phy_write(phy_addr, 17, 0xB233);
keystone2_eth_phy_write(phy_addr, 16, 0x214D);
keystone2_eth_phy_write(phy_addr, 17, 0xCC0C);
keystone2_eth_phy_write(phy_addr, 16, 0x2159);
keystone2_eth_phy_write(phy_addr, 22, 0x0000); /* reg page 0 */
keystone2_eth_phy_write(phy_addr, 22, 18); /* reg page 18 */
/* Write HWCFG_MODE = SGMII to Copper */
keystone2_eth_phy_writebits(phy_addr, 20, 0, 3, 1);
/* Phy reset */
keystone2_eth_phy_writebits(phy_addr, 20, 15, 1, 1);
keystone2_eth_phy_write(phy_addr, 22, 0); /* reg page 18 */
udelay(100);
return 0;
}
/* PHY functions for Marvell 88E1111 PHY */
static int marvell_88e1111_init_phy(int phy_addr)
{
int ret = -1;
if (!marvell_88e1111_get_link_speed(phy_addr)) {
/* Try another time */
ret = marvell_88e1111_get_link_speed(phy_addr);
}
return(ret);
}
static int marvell_88e1111_is_phy_connected(int phy_addr)
{
u_int16_t dummy;
return keystone2_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
}
static int marvell_88e1111_get_link_speed(int phy_addr)
{
u_int16_t tmp;
unsigned int tmp1 = keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp);
printf("reading MII_STATUS_REG-->%u \n",tmp1);
if ((!tmp1) && (tmp & MII_STATUS_LINK_MASK)) {
printf("condition %x \n",tmp & MII_STATUS_LINK_MASK);
return(0);
}
return(-1);
}
static int marvell_88e1111_auto_negotiate(int phy_addr)
{
u_int16_t tmp;
if (keystone2_eth_phy_read(phy_addr, MII_BMCR, &tmp))
return(-1);
/* Restart Auto_negotiation */
tmp |= BMCR_ANENABLE;
keystone2_eth_phy_write(phy_addr, MII_BMCR, tmp);
/*check AutoNegotiate complete */
udelay (10000);
if (keystone2_eth_phy_read(phy_addr, MII_BMSR, &tmp))
return(-1);
if (!(tmp & BMSR_ANEGCOMPLETE))
return(0);
return(marvell_88e1111_get_link_speed(phy_addr));
}
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
static int keystone2_mii_phy_read(const char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
{
return keystone2_eth_phy_read(addr, reg, value) ? -1 : 0;
}
static int keystone2_mii_phy_write(const char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
{
return keystone2_eth_phy_write(addr, reg, value) ? -1 : 0;
}
#endif
static void __attribute__((unused))
keystone2_eth_gigabit_enable(struct eth_device *dev)
{
u_int16_t data;
eth_priv_t *eth_priv = (eth_priv_t*)dev->priv;
if (IS_XGE(eth_priv))
return;
if (sys_has_mdio) {
if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) ||
!(data & (1 << 6))) /* speed selection MSB */
return;
}
/*
* Check if link detected is giga-bit
* If Gigabit mode detected, enable gigbit in MAC
*/
writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + \
CPGMACSL_REG_CTL) | EMAC_MACCONTROL_GIGFORCE | \
EMAC_MACCONTROL_GIGABIT_ENABLE,
DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
}
int keystone_sgmii_link_status(int port)
{
u32 status = 0;
// printf("LWS PORT num---------> %d \n",port);
status = __raw_readl(SGMII_STATUS_REG(port));
// printf("SGMII Status = %x \n",status);
return (status & SGMII_REG_STATUS_LINK);
}
#define MII_88E1510_GEN_CTRL_REG_1 0x14
#define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7
#define MII_88E1510_SGMII_TO_QSGMII_MODE 0x5 /* SGMII to QSGMII */
#define MII_88E1510_QSGMII_TO_FIBER_MODE 0x2 /* QSGMII to BASE1000 */
#define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */
#define MII_88E1548_GEN_CTRL_REG_1_AUTO_MEDIA_MASK 0x30
#define MII_88E1548_GEN_CTRL_REG_1_AUTO_MEDIA 0x20
#define QSGMIIGLOBALCTRLREG 0x1B
#define QSGMIIOPCROSSOVERMASK 0x3
#define QSGMIIOPCROSSOVER 0x3
#define QSGMIIPOWERUPMASK 0x0800
#define EN_LOOPBACK 0x4000
#define FIBERCTRLREG 0x0
#define FIBERRSTMASK 0x8000
#define FIBERRST 0x8000
#define FIBER_SPECI_CONTROL_REG 16
#define FIBER_SPECI_MODE_MASK 3
#define FIBER_SYSTEM_MODE 10
#define FIBER_MEDIA_MODE 11
#define QSGMII_SPECI_CONTROL_REG 16
#define QSGMII_SPECI_MODE_MASK 1
#define QSGMII_SYSTEM_MODE 0
#define QSGMII_MEDIA_MODE 1
#define QSGMIICONTROLMASK 0x8000
#define QSGMIICTRLVAL 0x8000
int regRead(u_int8_t phy_addr, int page, u_int8_t reg_num){
int ret = 0;
keystone2_eth_phy_write(phy_addr,22,page);
keystone2_eth_phy_read(phy_addr,reg_num,&ret);
return ret;
}
static int hwd = 0 ;
void fibberSettings(eth_priv_t *eth_priv){
signed int port,page,i,tmp;
signed int ret=0;
// printf("LWS eth_priv->int_name------> %s \n",eth_priv->int_name); //added
// printf("LWS entered fiber_settings phy_addr--> %d \n",eth_priv->phy_addr);// Added
// printf("LWS Slave_port--> %d \n",eth_priv->slave_port); // Added
/*==================================================================================================================================================================*/
/*Hardware reset*/
/*==================================================================================================================================================================*/
if ( hwd < 1 ) {
keystone2_eth_phy_write(eth_priv->phy_addr,22,4); /*Sel Page 4*/
keystone2_eth_phy_read(eth_priv->phy_addr,27,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,27,(ret | 0x8000)); /*Hardware reset*/
keystone2_eth_phy_read(eth_priv->phy_addr,27,&ret);
hwd++;
udelay(100000);
}
/*==================================================================================================================================================================*/
/*PHY Init*/
/*==================================================================================================================================================================*/
keystone2_eth_phy_write(eth_priv->phy_addr,22,0xFF);
keystone2_eth_phy_write(eth_priv->phy_addr,17,0x2148);
keystone2_eth_phy_read(eth_priv->phy_addr,17,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x2144);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,17,0x0C28);
keystone2_eth_phy_read(eth_priv->phy_addr,17,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x2146);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,17,0xB233);
keystone2_eth_phy_read(eth_priv->phy_addr,17,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x214D);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,17,0xDC0C);
keystone2_eth_phy_read(eth_priv->phy_addr,17,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x2159);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,17,0x68BA);
keystone2_eth_phy_read(eth_priv->phy_addr,17,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x2142);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,17,0x8056);
keystone2_eth_phy_read(eth_priv->phy_addr,17,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x2141);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,22,0xFB);
keystone2_eth_phy_write(eth_priv->phy_addr,7,0xD);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,22,0x0);
/*Fiber init*/
keystone2_eth_phy_write(eth_priv->phy_addr,22,0x1);
keystone2_eth_phy_writebits(eth_priv->phy_addr,16,9,1,0);
keystone2_eth_phy_write(eth_priv->phy_addr,22,0x0);
/*==================================================================================================================================================================*/
/*Mode Setting*/
/*==================================================================================================================================================================*/
/*Read the global control register 1 and set the mode to SGMII to QSGMII for Port 0*/
keystone2_eth_phy_write(eth_priv->phy_addr,22,18); /*Select Page No 18*/
keystone2_eth_phy_read(eth_priv->phy_addr,20,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,20,0x205);
keystone2_eth_phy_write(eth_priv->phy_addr,20,0x8205); /*Reset*/
keystone2_eth_phy_read(eth_priv->phy_addr,20,&ret);
/*Read the global control register 1 and set the mode to QSGMII to 1000Base for Port 0*/
keystone2_eth_phy_write((eth_priv->phy_addr+1),22,18); /*Select Page No 18*/
keystone2_eth_phy_write((eth_priv->phy_addr+1),20,0x207);
keystone2_eth_phy_write(eth_priv->phy_addr+1,20,0x8207);/*Reset*/
keystone2_eth_phy_read((eth_priv->phy_addr+1),20,&ret);
/*Sel of port mode System/Media */
keystone2_eth_phy_write(eth_priv->phy_addr,22,4); /*Select Page No 4*/
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x6205); //LWS SGMII media mode
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,4); /*Select Page No 4*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,16,0x6204); //LWS SGMII system mode
keystone2_eth_phy_read(eth_priv->phy_addr+1,16,&ret);
/*QSGMII o/p Crossover*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,4); /*Select Page No 4*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,27,0x7E03);
keystone2_eth_phy_read(eth_priv->phy_addr+1,27,&ret);
/*autoneg and speed sel */
keystone2_eth_phy_write(eth_priv->phy_addr,22,4); /*Select Page No 4*/
keystone2_eth_phy_write(eth_priv->phy_addr,0,0x9140);
keystone2_eth_phy_read(eth_priv->phy_addr,0,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,4); /*Select Page No 4*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,0,0x9140);
keystone2_eth_phy_read(eth_priv->phy_addr+1,0,&ret);
/*MAC power up and clocks */
keystone2_eth_phy_write(eth_priv->phy_addr,22,2); /*Select Page No 2*/
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x4008);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,2); /*Select Page No 2*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,16,0x4008);
keystone2_eth_phy_read(eth_priv->phy_addr+1,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,22,1); /*Select Page No 1*/
keystone2_eth_phy_write(eth_priv->phy_addr,16,0x408C);
keystone2_eth_phy_read(eth_priv->phy_addr,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,22,1); /*Select Page No 1*/
keystone2_eth_phy_write(eth_priv->phy_addr,26,0x44);
keystone2_eth_phy_read(eth_priv->phy_addr,26,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr,22,1); /*Select Page No 1*/
keystone2_eth_phy_write(eth_priv->phy_addr,0,0x9140);
keystone2_eth_phy_read(eth_priv->phy_addr,0,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,1); /*Select Page No 1*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,16,0x408C);
keystone2_eth_phy_read(eth_priv->phy_addr+1,16,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,1); /*Select Page No 1*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,26,0x44);
keystone2_eth_phy_read(eth_priv->phy_addr+1,26,&ret);
keystone2_eth_phy_write(eth_priv->phy_addr+1,22,1); /*Select Page No 1*/
keystone2_eth_phy_write(eth_priv->phy_addr+1,0,0x8140);
keystone2_eth_phy_read(eth_priv->phy_addr+1,0,&ret);
#if 0
for(page=0;page<=18;page++){
keystone2_eth_phy_write((eth_priv->phy_addr),22,page);
for(i=0;i<32;i++){
keystone2_eth_phy_read((eth_priv->phy_addr), i, &tmp);
printf("PHY Address = %d Page = %d REG = %d val = %4x \n",(eth_priv->phy_addr),page,i,tmp);
}
}
printf("\n\n");
for(page=0;page<=18;page++){
keystone2_eth_phy_write((eth_priv->phy_addr +1 ),22,page);
for(i=0;i<32;i++){
keystone2_eth_phy_read((eth_priv->phy_addr+ 1), i, &tmp);
printf("PHY Address = %d Page = %d REG = %d val = %4x \n",(eth_priv->phy_addr+1),page,i,tmp);
}
}
#endif
}
static int fibersetdone = 0;
int keystone_get_link_status(struct eth_device *dev)
{
// int fibersetdone = 0;
eth_priv_t *eth_priv = (eth_priv_t*)dev->priv;
int sgmii_link;
int link_state = 0;
// printf("Before Fibersettings0 -->%d \n",fibersetdone);
// printf("Before Fibersettings1 -->%d \n",fibersetdone1);
#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
int j;
if ((eth_priv->phy_addr == 0x08) && (eth_priv->phy_addr == 0x0a) && (fibersetdone<=1) ){
fibberSettings(eth_priv);
fibersetdone++;
// printf("Fibersettings0 Done -->%d \n",fibersetdone);
}
//eth_priv->phy_addr = eth_priv->phy_addr+1;
// printf("LWS portname------>%s \n",eth_priv->int_name);//added
// printf("LWS SFP phy_addr---------->%d \n",eth_priv->phy_addr); //added
keystone2_eth_phy_write(eth_priv->phy_addr,22,1);
//printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n SGMII port = %d PHY address = %x \n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n",eth_priv->slave_port,eth_priv->phy_addr);
for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0); j++) {
#endif
//printf("Inside SGMII link check\n");
sgmii_link = keystone_sgmii_link_status(eth_priv->slave_port - 1);
phy.get_link_speed (eth_priv->phy_addr);
// printf("Link_Speed---->%d \n", phy.get_link_speed (eth_priv->phy_addr));
if (sgmii_link) {
link_state = 1;
//printf("SGMII link is high \n");
if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY)
if (phy.get_link_speed (eth_priv->phy_addr)) {
// link_state = 0 ;
udelay(1000);
}
}else{
//printf("SGMII link is low \n");
}
#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
}
#endif
// printf("LWS link_state-----> %d \n",link_state);
return link_state;
}
int keystone_sgmii_config(int port, int interface)
{
unsigned int i, status, mask;
unsigned int mr_adv_ability, control;
switch (interface) {
case SGMII_LINK_MAC_MAC_AUTONEG:
mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE |
SGMII_REG_MR_ADV_LINK |
SGMII_REG_MR_ADV_FULL_DUPLEX |
SGMII_REG_MR_ADV_GIG_MODE);
control = (SGMII_REG_CONTROL_MASTER |
SGMII_REG_CONTROL_AUTONEG);
break;
case SGMII_LINK_MAC_PHY:
case SGMII_LINK_MAC_PHY_FORCED:
mr_adv_ability = SGMII_REG_MR_ADV_ENABLE;
control = SGMII_REG_CONTROL_AUTONEG;
break;
case SGMII_LINK_MAC_MAC_FORCED:
mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE |
SGMII_REG_MR_ADV_LINK |
SGMII_REG_MR_ADV_FULL_DUPLEX |
SGMII_REG_MR_ADV_GIG_MODE);
control = SGMII_REG_CONTROL_MASTER;
break;
case SGMII_LINK_MAC_FIBER:
mr_adv_ability = 0x20;
control = SGMII_REG_CONTROL_AUTONEG;
break;
default:
mr_adv_ability = SGMII_REG_MR_ADV_ENABLE;
control = SGMII_REG_CONTROL_AUTONEG;
}
__raw_writel(0, SGMII_CTL_REG(port));
/*
* Wait for the SerDes pll to lock,
* but don't trap if lock is never read
*/
for (i = 0; i < 1000; i++) {
udelay(2000);
status = __raw_readl(SGMII_STATUS_REG(port));
if ((status & SGMII_REG_STATUS_LOCK) != 0)
break;
}
__raw_writel(mr_adv_ability, SGMII_MRADV_REG(port));
__raw_writel(control, SGMII_CTL_REG(port));
mask = SGMII_REG_STATUS_LINK;
if (control & SGMII_REG_CONTROL_AUTONEG)
mask |= SGMII_REG_STATUS_AUTONEG;
for (i = 0; i < 2000; i++) {
udelay(2000);
status = __raw_readl(SGMII_STATUS_REG(port));
if ((status & mask) == mask)
break;
}
return 0;
}
int mac_sl_reset(u32 port)
{
u32 i, v;
if (port >= DEVICE_N_GMACSL_PORTS)
return (GMACSL_RET_INVALID_PORT);
/* Set the soft reset bit */
DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) +
CPGMACSL_REG_RESET, CPGMAC_REG_RESET_VAL_RESET);
/* Wait for the bit to clear */
for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
v = DEVICE_REG32_R (DEVICE_EMACSL_BASE(port) +
CPGMACSL_REG_RESET);
if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
CPGMAC_REG_RESET_VAL_RESET)
return (GMACSL_RET_OK);
}
/* Timeout on the reset */
return (GMACSL_RET_WARN_RESET_INCOMPLETE);
}
int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
{
u32 v, i;
int ret = GMACSL_RET_OK;
if (port >= DEVICE_N_GMACSL_PORTS)
return (GMACSL_RET_INVALID_PORT);
if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
}
/* Must wait if the device is undergoing reset */
for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) +
CPGMACSL_REG_RESET);
if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
CPGMAC_REG_RESET_VAL_RESET)
break;
}
if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
return (GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE);
DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN,
cfg->max_rx_len);
DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL,
cfg->ctl);
if (!cpu_is_k2hk())
/* Map RX packet flow priority to 0 */
DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + \
CPGMACSL_REG_RX_PRI_MAP, 0);
return (ret);
}
int ethss_config(u32 ctl, u32 max_pkt_size)
{
u32 i;
/* Max length register */
DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_MAXLEN, max_pkt_size);
/* Control register */
DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_CTL, ctl);
/* All statistics enabled by default */
DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN,
CPSW_REG_VAL_STAT_ENABLE_ALL);
/* Reset and enable the ALE */
DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL,
CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
CPSW_REG_VAL_ALE_CTL_BYPASS);
/* All ports put into forward mode */
for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++)
DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i),
CPSW_REG_VAL_PORTCTL_FORWARD_MODE);
return (0);
}
int ethss_start(void)
{
int i;
struct mac_sl_cfg cfg;
cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER;
cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL;
for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
mac_sl_reset(i);
mac_sl_config(i, &cfg);
}
return (0);
}
int ethss_stop(void)
{
int i;
for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++)
mac_sl_reset(i);
return (0);
}
int32_t cpmac_drv_send(u32* buffer, int num_bytes, int slave_port_num)
{
if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
return netcp_send(buffer, num_bytes, slave_port_num);
}
/* Eth device open */
static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
{
int link;
eth_priv_t *eth_priv = (eth_priv_t*)dev->priv;
debug_emac("+ emac_open\n");
if (xmac_open) {
printf("keystone2_eth_open ERR - 10G intf is still open!\n");
return -1;
}
net_rx_buffs.rx_flow = eth_priv->rx_flow;
sys_has_mdio =
(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
sgmii_serdes_setup_156p25mhz();
if (sys_has_mdio)
keystone2_eth_mdio_enable();
keystone_sgmii_config(eth_priv->slave_port - 1,
eth_priv->sgmii_link_type);
udelay(10000);
/* On chip switch configuration */
ethss_config(target_get_sw_ctl(), target_get_sw_max_pkt_size());
/* TODO: add error handling code */
if (qm_init()) {
printf("ERROR: qm_init()\n");
return (-1);
}
if (netcp_init(&net_rx_buffs)) {
qm_close();
printf("ERROR: netcp_init()\n");
return (-1);
}
/*
* Streaming switch configuration. If not present this
* statement is defined to void in target.h.
* If present this is usually defined to a series of register writes
*/
hwConfigStreamingSwitch();
if (sys_has_mdio) {
/* Init MDIO & get link state */
keystone2_eth_mdio_enable();
if (!loopback_test) {
link = keystone_get_link_status(dev);
if (link == 0) {
netcp_close();
qm_close();
return -1;
}
}
}
if (!loopback_test) {
emac_gigabit_enable(dev);
}
ethss_start();
debug_emac("- emac_open\n");
emac_open = 1;
return(0);
}
/* Eth device close */
void keystone2_eth_close(struct eth_device *dev)
{
debug_emac("+ emac_close\n");
if (!emac_open)
return;
ethss_stop();
netcp_close();
qm_close();
emac_open = 0;
debug_emac("- emac_close\n");
}
void keystone2_eth_open_close(struct eth_device *dev)
{
keystone2_eth_open(dev, NULL);
keystone2_eth_close(dev);
}
/*
* This function sends a single packet on the network and returns
* positive number (number of bytes transmitted) or negative for error
*/
static int keystone2_eth_send_packet(struct eth_device *dev,
volatile void *packet, int length)
{
int ret_status = -1;
eth_priv_t *eth_priv = (eth_priv_t*)dev->priv;
if (!loopback_test) {
if (keystone_get_link_status(dev) == 0)
return -1;
}
if (cpmac_drv_send ((u32*) packet, length, eth_priv->slave_port) != 0)
return ret_status;
//printf("Inside keystone send packet functioni =%x \n",length);
return (length);
}
/*
* This function handles receipt of a packet from the network
*/
static int keystone2_eth_rcv_packet(struct eth_device *dev)
{
void *hd;
int pkt_size;
u32 *pkt;
hd = netcp_recv(&pkt, &pkt_size);
if (hd == NULL)
return (0);
NetReceive((uchar *)pkt, pkt_size);
netcp_release_rxhd(hd);
//printf("Inside keystone2Rx packet %x \n",pkt_size);
return pkt_size;
}
inline void keystone2_emac_set_loopback_test(int val)
{
loopback_test = val;
}
static int xmac_sl_reset(u32 port)
{
u32 i, v;
if (port >= DEVICE_N_XMACSL_PORTS)
return GMACSL_RET_INVALID_PORT;
/* Set the soft reset bit */
DEVICE_REG32_W(DEVICE_XMACSL_BASE(port) +
CPXMACSL_REG_RESET, CPGMAC_REG_RESET_VAL_RESET);
/* Wait for the bit to clear */
for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
v = DEVICE_REG32_R(DEVICE_XMACSL_BASE(port) +
CPXMACSL_REG_RESET);
if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
CPGMAC_REG_RESET_VAL_RESET)
return GMACSL_RET_OK;
}
/* Timeout on the reset */
return GMACSL_RET_WARN_RESET_INCOMPLETE;
}
static int xmac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
{
u32 v, i;
int ret = GMACSL_RET_OK;
if (port >= DEVICE_N_XMACSL_PORTS)
return GMACSL_RET_INVALID_PORT;
if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
}
/* Must wait if the device is undergoing reset */
for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
v = DEVICE_REG32_R(DEVICE_XMACSL_BASE(port) +
CPXMACSL_REG_RESET);
if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
CPGMAC_REG_RESET_VAL_RESET)
break;
}
if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE;
DEVICE_REG32_W(DEVICE_XMACSL_BASE(port) + CPXMACSL_REG_MAXLEN,
cfg->max_rx_len);
DEVICE_REG32_W(DEVICE_XMACSL_BASE(port) + CPXMACSL_REG_CTL,
cfg->ctl);
/* Map RX packet flow priority to 0 */
DEVICE_REG32_W(DEVICE_XMACSL_BASE(port) + CPXMACSL_REG_RX_PRI_MAP, 0);
return ret;
}
static int xgess_config(u32 ctl, u32 max_pkt_size)
{
u32 i;
DEVICE_REG32_W(KS2_XGESS_BASE + XGESS_REG_CTL,
XGESS_REG_VAL_XGMII_MODE);
/* Max length register */
DEVICE_REG32_W(DEVICE_CPSWX_BASE + CPSWX_REG_MAXLEN, max_pkt_size);
/* Control register */
DEVICE_REG32_W(DEVICE_CPSWX_BASE + CPSWX_REG_CTL, ctl);
/* All statistics enabled by default */
DEVICE_REG32_W(DEVICE_CPSWX_BASE + CPSWX_REG_STAT_PORT_EN,
CPSWX_REG_VAL_STAT_ENABLE_ALL);
/* Reset and enable the ALE */
DEVICE_REG32_W(DEVICE_CPSWX_BASE + CPSWX_REG_ALE_CONTROL,
CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
CPSW_REG_VAL_ALE_CTL_BYPASS);
/* All ports put into forward mode */
for (i = 0; i < DEVICE_CPSWX_NUM_PORTS; i++)
DEVICE_REG32_W(DEVICE_CPSWX_BASE + CPSWX_REG_ALE_PORTCTL(i),
CPSW_REG_VAL_PORTCTL_FORWARD_MODE);
return 0;
}
static int xgess_start(void)
{
int i;
struct mac_sl_cfg cfg;
cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER;
cfg.ctl = (XMACSL_XGMII_ENABLE |
XMACSL_XGIG_MODE |
XMACSL_RX_ENABLE_CSF |
GMACSL_RX_ENABLE_EXT_CTL);
for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
xmac_sl_reset(i);
xmac_sl_config(i, &cfg);
}
return 0;
}
static int xgess_stop(void)
{
int i;
for (i = 0; i < DEVICE_N_XMACSL_PORTS; i++)
xmac_sl_reset(i);
return 0;
}
/* XGE device open */
static int keystone2_xge_open(struct eth_device *dev, bd_t *bis)
{
eth_priv_t *eth_priv = (eth_priv_t *)dev->priv;
int ret;
debug_emac("+ xmac_open\n");
if (emac_open) {
printf("keystone2_xge_open ERR - 1G intf is still open!\n");
return -1;
}
net_rx_buffs.rx_flow = eth_priv->rx_flow;
xge_serdes_init();
udelay(10000);
xgess_config(target_get_sw_ctl(), target_get_sw_max_pkt_size());
/* TODO: add error handling code */
if (cpu_is_k2hk())
ret = qm2_init();
else if (cpu_is_k2e())
ret = qm_init();
else
return -1;
if (ret) {
printf("ERROR: xge qm(2) init()\n");
return -1;
}
if (netcpx_init(&net_rx_buffs)) {
if (cpu_is_k2hk())
qm2_close();
else
qm_close();
printf("ERROR: netcpx_init()\n");
return -1;
}
if (!loopback_test)
emac_gigabit_enable(dev);
xgess_start();
debug_emac("- xmac_open\n");
xmac_open = 1;
return 0;
}
/* XGE device close */
static void keystone2_xge_close(struct eth_device *dev)
{
debug_emac("+ xmac_close\n");
if (!xmac_open)
return;
if (cpu_is_k2l())
return;
xgess_stop();
netcpx_close();
if (cpu_is_k2hk())
qm2_close();
else
qm_close();
xmac_open = 0;
debug_emac("- xmac_close\n");
}
static int keystone2_xge_send_packet(struct eth_device *dev,
void *packet, int length)
{
int ret;
eth_priv_t *eth_priv = (eth_priv_t *)dev->priv;
if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
length = EMAC_MIN_ETHERNET_PKT_SIZE;
ret = netcpx_send((u32 *)packet, length, eth_priv->slave_port);
if (ret) {
printf("netcpx_send error: %d\n", ret);
return ret;
}
return length;
}
static int keystone2_xge_rcv_packet(struct eth_device *dev)
{
void *hd;
int pkt_size;
u32 *pkt;
hd = netcpx_recv(&pkt, &pkt_size);
if (hd == NULL)
return 0;
NetReceive((uchar *)pkt, pkt_size);
netcpx_release_rxhd(hd);
return pkt_size;
}
/*
* This function initializes the EMAC hardware. It does NOT initialize
* EMAC modules power or pin multiplexors, that is done by board_init()
* much earlier in bootup process. Returns 1 on success, 0 otherwise.
*/
int keystone2_emac_initialize(eth_priv_t *eth_priv)
{
struct eth_device *dev;
static int phy_registered = 0;
static int emac_poweron = 1;
static int xmac_poweron = 1;
unsigned int temp;
printf("eth_priv->int_name-------->%s \n",eth_priv->int_name);
dev = malloc(sizeof *dev);
if (dev == NULL)
return -1;
memset(dev, 0, sizeof *dev);
strcpy(dev->name, eth_priv->int_name);
dev->priv = eth_priv;
keystone2_eth_read_mac_addr(dev);
dev->iobase = 0;
dev->init = keystone2_eth_open;
dev->halt = keystone2_eth_close;
dev->send = keystone2_eth_send_packet;
dev->recv = keystone2_eth_rcv_packet;
#ifdef CONFIG_MCAST_TFTP
dev->mcast = keystone2_eth_bcast_addr;
#endif
eth_priv->dev = dev;
eth_register(dev);
if (emac_poweron && IS_1GE(eth_priv)) {
emac_poweron = 0;
/* Workaround to resolve a PA RX path issue in the Ethernet
* boot mode by turning off PA/CPGMAC/CRYPTO clock modules */
/* Set the streaming switch to forward the RX packets to CPSW */
hwConfigStreamingSwitch();
/* Turn off rx/tx packet DMA channels */
for (temp = 0; temp < DEVICE_PA_CDMA_RX_NUM_CHANNELS; temp++)
writel(0x0, DEVICE_PA_CDMA_RX_CHAN_CFG_BASE + 8 * temp);
for (temp = 0; temp < DEVICE_PA_CDMA_TX_NUM_CHANNELS; temp++)
writel(0x0, DEVICE_PA_CDMA_TX_CHAN_CFG_BASE + 8 * temp);
/* Power off PA/CPGMAC/CRYPTO */
if (psc_disable_module(KS2_LPSC_CRYPTO))
return -1;
if (psc_disable_module(KS2_LPSC_CPGMAC))
return -1;
if (psc_disable_module(KS2_LPSC_PA))
return -1;
/* By default, select PA PLL clock as PA clock source */
if (psc_enable_module(KS2_LPSC_PA))
return -1;
if (psc_enable_module(KS2_LPSC_CPGMAC))
return -1;
if (psc_enable_module(KS2_LPSC_CRYPTO))
return -1;
pll_pa_clk_sel(1);
} else if (IS_XGE(eth_priv)) {
dev->init = keystone2_xge_open;
dev->halt = keystone2_xge_close;
dev->send = keystone2_xge_send_packet;
dev->recv = keystone2_xge_rcv_packet;
#ifdef CONFIG_MCAST_TFTP
dev->mcast = keystone2_eth_bcast_addr;
#endif
if (xmac_poweron) {
xmac_poweron = 0;
if (psc_enable_module(KS2_LPSC_XGE))
return -1;
}
}
if ((eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) &&
!phy_registered) {
phy_registered = 1;
#ifdef CONFIG_ETH_PHY_MARVEL_88E1111
sprintf(phy.name, "88E1111");
phy.init = marvell_88e1111_init_phy;
phy.is_phy_connected = marvell_88e1111_is_phy_connected;
phy.get_link_speed = marvell_88e1111_get_link_speed;
phy.auto_negotiate = marvell_88e1111_auto_negotiate;
#else
sprintf(phy.name, "GENERIC");
phy.init = gen_init_phy;
phy.is_phy_connected = gen_is_phy_connected;
phy.get_link_speed = gen_get_link_speed;
phy.auto_negotiate = gen_auto_negotiate;
#endif
// printf("LWS PHY_Name = %s \n",phy.name);
miiphy_register(phy.name, keystone2_mii_phy_read,
keystone2_mii_phy_write);
}
if (!cpu_is_k2hk() &&
(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY)) {
keystone2_eth_mdio_enable();
marvell_88e1512_init_phy(eth_priv->phy_addr);
}
return(0);
}
/*
* Copyright (C) 2012 - 2014 Texas Instruments Inc.
*
* K2HK EVM : Board initialization
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <common.h>
#include <i2c.h>
#include <asm/arch/hardware.h>
#include <asm/arch/clock.h>
#include <asm/arch/clock_defs.h>
#include <asm/io.h>
#include <asm/arch/nand_defs.h>
#include <asm/arch/emac_defs.h>
DECLARE_GLOBAL_DATA_PTR;
unsigned int external_clk[ext_clk_count] = {
[sys_clk] = 122880000,
[alt_core_clk] = 125000000,
[pa_clk] = 122880000,
[tetris_clk] = 125000000,
[ddr3a_clk] = 100000000,
[ddr3b_clk] = 100000000,
[mcm_clk] = 312500000,
[pcie_clk] = 100000000,
[sgmii_srio_clk] = 156250000,
[xgmii_clk] = 156250000,
[usb_clk] = 100000000,
[rp1_clk] = 123456789 /* TODO: cannot find
what is that */
};
static struct async_emif_config async_emif_config[ASYNC_EMIF_NUM_CS] = {
{ /* CS0 */
.mode = ASYNC_EMIF_MODE_NAND,
.wr_setup = 0xf,
.wr_strobe = 0x3f,
.wr_hold = 7,
.rd_setup = 0xf,
.rd_strobe = 0x3f,
.rd_hold = 7,
.turn_around = 3,
.width = ASYNC_EMIF_8,
},
};
static struct pll_init_data core_pll_config[] = {
{ CORE_PLL, 13, 1, 2 }, /* 799 */
{ CORE_PLL, 122, 15, 1 }, /* 999 */
{ CORE_PLL, 625, 32, 2 }, /* 1200 */
};
static struct pll_init_data tetris_pll_config[] = {
{ TETRIS_PLL, 32, 5, 1 }, /* 800 */
{ TETRIS_PLL, 40, 5, 1 }, /* 1000 */
{ TETRIS_PLL, 48, 5, 1 }, /* 1200 */
{ TETRIS_PLL, 54, 5, 1 }, /* 1350 */
{ TETRIS_PLL, 56, 5, 1 }, /* 1400 */
};
static struct pll_init_data pa_pll_config =
{ PASS_PLL, 16, 1, 2 }; /* 983 */
#ifdef CONFIG_SPL_BOARD_INIT
static struct pll_init_data spl_pll_config[] = {
{ CORE_PLL, 13, 1, 2 }, /* 799 */
{ TETRIS_PLL, 8, 1, 2 }, /* 500 */
};
void spl_init_keystone_plls(void)
{
init_plls(ARRAY_SIZE(spl_pll_config), spl_pll_config);
}
#endif
int dram_init(void)
{
init_ddr3();
gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
CONFIG_MAX_RAM_BANK_SIZE);
init_async_emif(ARRAY_SIZE(async_emif_config), async_emif_config);
init_ddr3_ecc(K2HK_DDR3A_EMIF_CTRL_BASE);
return 0;
}
#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
eth_priv_t eth_priv_cfg[] = {
#if 1
{
.int_name = "K2HK_EMAC",
.rx_flow = CPSW_PORT_RX_FLOW(0),
.phy_addr = 0, /*Vyapi V1*/
// .phy_addr = 8, /*Vyapi V2*/
.slave_port = 1,
.sgmii_link_type = SGMII_LINK_MAC_PHY,
},
{
.int_name = "K2HK_EMAC1",
.rx_flow = CPSW_PORT_RX_FLOW(1),
// .phy_addr = 8,
.phy_addr = 1, //LWS
.slave_port = 2,
.sgmii_link_type = SGMII_LINK_MAC_PHY,
},
{
.int_name = "K2HK_EMAC2",
.rx_flow = CPSW_PORT_RX_FLOW(2),
.phy_addr = 1,
// .phy_addr = 10, //added
.slave_port = 3,
.sgmii_link_type = SGMII_LINK_MAC_PHY,
},
#endif
{
.int_name = "K2HK_EMAC3",
.rx_flow = CPSW_PORT_RX_FLOW(3),
.phy_addr = 0,
.slave_port = 4,
.sgmii_link_type = SGMII_LINK_MAC_PHY,
},
{
.int_name = "K2HK_XMAC0",
.rx_flow = 0,
.slave_port = 1,
.sgmii_link_type = XGMII_LINK_MAC_MAC_FORCED,
},
{
.int_name = "K2HK_XMAC1",
.rx_flow = 8,
.slave_port = 2,
.sgmii_link_type = XGMII_LINK_MAC_MAC_FORCED,
},
};
inline int get_num_eth_ports(void){
int total_ports = sizeof(eth_priv_cfg) / sizeof(eth_priv_t);
// printf("LWS 'get_num_eth' total_ports----->%d \n",total_ports);
return sizeof(eth_priv_cfg) / sizeof(eth_priv_t);
}
eth_priv_t *get_eth_priv_ptr(int port_num)
{
if (port_num < 0 || port_num >= get_num_eth_ports())
return NULL;
return ð_priv_cfg[port_num];
}
int get_eth_env_param(char *env_name)
{
char *env;
int res = -1;
env = getenv(env_name);
if (env)
res = simple_strtol(env, NULL, 0);
return res;
}
static int board_has_xge(void)
{
int ret, current_bus, has_xge = 1, restore = 0;
current_bus = i2c_get_bus_num();
// printf("LWS i2c 'board_has_xge' current bus_num------->%d \n",current_bus);
if (current_bus != RTM_BOC_XGE_RETIMER_I2C_BUS) {
ret = i2c_set_bus_num(RTM_BOC_XGE_RETIMER_I2C_BUS);
if (ret) {
has_xge = 0;
goto done;
}
restore = 1;
}
ret = i2c_probe(RTM_BOC_XGE_RETIMER1_I2C_ADDR);
if (!ret)
goto done;
ret = i2c_probe(RTM_BOC_XGE_RETIMER2_I2C_ADDR);
if (!ret)
goto done;
has_xge = 0;
done:
/* restore previous bus num */
if (restore)
i2c_set_bus_num(current_bus);
// printf("LWS 'board_has_xge'has_xge--->%d \n",has_xge);
return has_xge;
}
int board_eth_init(bd_t *bis)
{
int j;
int res;
char link_type_name[32];
int has_xge = board_has_xge();
// printf("LWS---> 'board_eth_init' has_xge---> %d \n",has_xge); //added
for (j = 0; j < get_num_eth_ports(); j++) {
if (IS_XGE(ð_priv_cfg[j]) && !has_xge)
continue;
sprintf(link_type_name, "sgmii%d_link_type", j);
// printf("LWS link_type name %s \n",link_type_name);//added
res = get_eth_env_param(link_type_name);
// printf("LWS res=%d \n",res);//added
if (res >= 0)
eth_priv_cfg[j].sgmii_link_type = res;
if (j<=1){
keystone2_emac_initialize(ð_priv_cfg[j]);
keystone2_eth_open_close(eth_priv_cfg[j].dev);
// printf("LWS $$$$$$$$$$$$$$$$ open close %d\n",j);
}
// keystone2_eth_open_close(eth_priv_cfg[0].dev);
// keystone2_eth_open_close(eth_priv_cfg[1].dev);
// keystone2_eth_open_close(eth_priv_cfg[2].dev);
}
return 0;
}
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_F)
int board_early_init_f(void)
{
int speed;
speed = get_max_dev_speed();
if (speed != SPD800 && speed != SPD_RSV)
init_pll(&core_pll_config[speed]);
else
init_pll(&core_pll_config[SPD800]);
init_pll(&pa_pll_config);
speed = get_max_arm_speed();
if (speed != SPD800 && speed != SPD_RSV)
init_pll(&tetris_pll_config[speed]);
else
init_pll(&tetris_pll_config[SPD800]);
return 0;
}
#endif
int board_init(void)
{
gd->bd->bi_arch_number = -1;
gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
return 0;
}