Newer
Older
/* Read the status */
{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
{miim_end,}
},
(struct phy_cmd[]) { /* shutdown */
{miim_end,}
},
};
struct phy_info phy_info_M88E1011S = {
0x01410c6,
"Marvell 88E1011S",
4,
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
(struct phy_cmd[]){ /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{0x1d, 0x1f, NULL},
{0x1e, 0x200c, NULL},
{0x1d, 0x5, NULL},
{0x1e, 0x0, NULL},
{0x1e, 0x100, NULL},
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_88E1011_PHY_STATUS, miim_read,
&mii_parse_88E1011_psr},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
struct phy_info phy_info_M88E1111S = {
0x01410cc,
"Marvell 88E1111S",
4,
(struct phy_cmd[]){ /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{0x1b, 0x848f, &mii_m88e1111s_setmode},
{0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_88E1011_PHY_STATUS, miim_read,
&mii_parse_88E1011_psr},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv)
{
uint mii_data = read_phy_reg(priv, mii_reg);
/* Setting MIIM_88E1145_PHY_EXT_CR */
if (priv->flags & TSEC_REDUCED)
return mii_data |
MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY;
else
return mii_data;
}
static struct phy_info phy_info_M88E1145 = {
0x01410cd,
"Marvell 88E1145",
4,
(struct phy_cmd[]){ /* config */
/* Reset the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
/* Errata E0, E1 */
{29, 0x001b, NULL},
{30, 0x418f, NULL},
{29, 0x0016, NULL},
{30, 0xa2da, NULL},
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO,
NULL},
{MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode},
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{MIIM_CONTROL, MIIM_CONTROL_INIT, NULL},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
{MIIM_88E1111_PHY_LED_CONTROL,
MIIM_88E1111_PHY_LED_DIRECT, NULL},
/* Read the Status */
{MIIM_88E1011_PHY_STATUS, miim_read,
&mii_parse_88E1011_psr},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
struct phy_info phy_info_cis8204 = {
0x3f11,
"Cicada Cis8204",
6,
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
(struct phy_cmd[]){ /* config */
/* Override PHY config settings */
{MIIM_CIS8201_AUX_CONSTAT,
MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
/* Configure some basic stuff */
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
{MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT,
&mii_cis8204_fixled},
{MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT,
&mii_cis8204_setmode},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Read the Status (2x to make sure link is right) */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_CIS8201_AUX_CONSTAT, miim_read,
&mii_parse_cis8201},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
};
/* Cicada 8201 */
struct phy_info phy_info_cis8201 = {
0xfc41,
"CIS8201",
4,
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
(struct phy_cmd[]){ /* config */
/* Override PHY config settings */
{MIIM_CIS8201_AUX_CONSTAT,
MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
/* Set up the interface mode */
{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT,
NULL},
/* Configure some basic stuff */
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Read the Status (2x to make sure link is right) */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_CIS8201_AUX_CONSTAT, miim_read,
&mii_parse_cis8201},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
struct phy_info phy_info_VSC8244 = {
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
0x3f1b,
"Vitesse VSC8244",
6,
(struct phy_cmd[]){ /* config */
/* Override PHY config settings */
/* Configure some basic stuff */
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Read the Status (2x to make sure link is right) */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_VSC8244_AUX_CONSTAT, miim_read,
&mii_parse_vsc8244},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
struct phy_info phy_info_dm9161 = {
0x0181b88,
"Davicom DM9161E",
4,
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
(struct phy_cmd[]){ /* config */
{MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
/* Do not bypass the scrambler/descrambler */
{MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
/* Clear 10BTCSR to default */
{MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT,
NULL},
/* Configure some basic stuff */
{MIIM_CONTROL, MIIM_CR_INIT, NULL},
/* Restart Auto Negotiation */
{MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_DM9161_SCSR, miim_read,
&mii_parse_dm9161_scsr},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
/* a generic flavor. */
struct phy_info phy_info_generic = {
0,
"Unknown/Generic PHY",
32,
(struct phy_cmd[]) { /* config */
{PHY_BMCR, PHY_BMCR_RESET, NULL},
{PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL},
{miim_end,}
},
(struct phy_cmd[]) { /* startup */
{PHY_BMSR, miim_read, NULL},
{PHY_BMSR, miim_read, &mii_parse_sr},
{PHY_BMSR, miim_read, &mii_parse_link},
{miim_end,}
},
(struct phy_cmd[]) { /* shutdown */
{miim_end,}
}
};
uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
{
unsigned int speed;
if (priv->link) {
speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
switch (speed) {
case MIIM_LXT971_SR2_10HDX:
priv->speed = 10;
priv->duplexity = 0;
break;
case MIIM_LXT971_SR2_10FDX:
priv->speed = 10;
priv->duplexity = 1;
break;
case MIIM_LXT971_SR2_100HDX:
priv->speed = 100;
priv->duplexity = 0;
default:
priv->speed = 100;
priv->duplexity = 1;
}
} else {
priv->speed = 0;
priv->duplexity = 0;
}
return 0;
static struct phy_info phy_info_lxt971 = {
0x0001378e,
"LXT971",
4,
(struct phy_cmd[]){ /* config */
{MIIM_CR, MIIM_CR_INIT, mii_cr_init}, /* autonegotiate */
{miim_end,}
},
(struct phy_cmd[]){ /* startup - enable interrupts */
/* { 0x12, 0x00f2, NULL }, */
{MIIM_STATUS, miim_read, NULL},
{MIIM_STATUS, miim_read, &mii_parse_sr},
{MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown - disable interrupts */
{miim_end,}
},
/* Parse the DP83865's link and auto-neg status register for speed and duplex
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
{
switch (mii_reg & MIIM_DP83865_SPD_MASK) {
case MIIM_DP83865_SPD_1000:
priv->speed = 1000;
break;
case MIIM_DP83865_SPD_100:
priv->speed = 100;
break;
default:
priv->speed = 10;
break;
}
if (mii_reg & MIIM_DP83865_DPX_FULL)
priv->duplexity = 1;
else
priv->duplexity = 0;
return 0;
}
struct phy_info phy_info_dp83865 = {
0x20005c7,
"NatSemi DP83865",
4,
(struct phy_cmd[]){ /* config */
{MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the link and auto-neg status */
{MIIM_DP83865_LANR, miim_read,
&mii_parse_dp83865_lanr},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
struct phy_info *phy_info[] = {
&phy_info_cis8204,
&phy_info_dp83865,
&phy_info_generic,
NULL
};
/* Grab the identifier of the device's PHY, and search through
* all of the known PHYs to see if one matches. If so, return
* it, if not, return NULL
*/
struct phy_info *get_phy_info(struct eth_device *dev)
{
struct tsec_private *priv = (struct tsec_private *)dev->priv;
uint phy_reg, phy_ID;
int i;
struct phy_info *theInfo = NULL;
/* Grab the bits from PHYIR1, and put them in the upper half */
phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
phy_ID = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
phy_ID |= (phy_reg & 0xffff);
/* loop through all the known PHY types, and find one that */
/* matches the ID we read from the PHY. */
for (i = 0; phy_info[i]; i++) {
if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) {
printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
return NULL;
} else {
debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
}
return theInfo;
/* Execute the given series of commands on the given device's
* PHY, running functions as necessary
*/
void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
{
int i;
uint result;
volatile tsec_t *phyregs = priv->phyregs;
phyregs->miimcfg = MIIMCFG_RESET;
phyregs->miimcfg = MIIMCFG_INIT_VALUE;
while (phyregs->miimind & MIIMIND_BUSY) ;
for (i = 0; cmd->mii_reg != miim_end; i++) {
if (cmd->mii_data == miim_read) {
result = read_phy_reg(priv, cmd->mii_reg);
if (cmd->funct != NULL)
(*(cmd->funct)) (result, priv);
if (cmd->funct != NULL)
result = (*(cmd->funct)) (cmd->mii_reg, priv);
else
result = cmd->mii_data;
write_phy_reg(priv, cmd->mii_reg, result);
}
cmd++;
}
}
/* Relocate the function pointers in the phy cmd lists */
static void relocate_cmds(void)
{
struct phy_cmd **cmdlistptr;
struct phy_cmd *cmd;
for (i = 0; phy_info[i]; i++) {
/* First thing's first: relocate the pointers to the
* PHY command structures (the structs were done) */
phy_info[i] = (struct phy_info *)((uint) phy_info[i]
+ gd->reloc_off);
phy_info[i]->name += gd->reloc_off;
phy_info[i]->config =
(struct phy_cmd *)((uint) phy_info[i]->config
+ gd->reloc_off);
(struct phy_cmd *)((uint) phy_info[i]->startup
+ gd->reloc_off);
(struct phy_cmd *)((uint) phy_info[i]->shutdown
+ gd->reloc_off);
cmdlistptr = &phy_info[i]->config;
j = 0;
for (; cmdlistptr <= &phy_info[i]->shutdown; cmdlistptr++) {
k = 0;
for (cmd = *cmdlistptr;
cmd->mii_reg != miim_end;
cmd++) {
/* Only relocate non-NULL pointers */
cmd->funct += gd->reloc_off;
k++;
}
j++;
}
}
relocated = 1;
}
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
/*
* Read a MII PHY register.
*
* Returns:
static int tsec_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
michael.firth@bt.com
committed
struct tsec_private *priv = privlist[0];
printf("Can't read PHY at address %d\n", addr);
return -1;
}
michael.firth@bt.com
committed
ret = (unsigned short)read_any_phy_reg(priv, addr, reg);
return 0;
}
/*
* Write a MII PHY register.
*
* Returns:
static int tsec_miiphy_write(char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
michael.firth@bt.com
committed
struct tsec_private *priv = privlist[0];
printf("Can't write PHY at address %d\n", addr);
return -1;
}
michael.firth@bt.com
committed
write_any_phy_reg(priv, addr, reg, value);
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
#ifdef CONFIG_MCAST_TFTP
/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
/* Set the appropriate hash bit for the given addr */
/* The algorithm works like so:
* 1) Take the Destination Address (ie the multicast address), and
* do a CRC on it (little endian), and reverse the bits of the
* result.
* 2) Use the 8 most significant bits as a hash into a 256-entry
* table. The table is controlled through 8 32-bit registers:
* gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is
* gaddr7. This means that the 3 most significant bits in the
* hash index which gaddr register to use, and the 5 other bits
* indicate which bit (assuming an IBM numbering scheme, which
* for PowerPC (tm) is usually the case) in the tregister holds
* the entry. */
static int
tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
{
struct tsec_private *priv = privlist[1];
volatile tsec_t *regs = priv->regs;
volatile u32 *reg_array, value;
u8 result, whichbit, whichreg;
result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
whichbit = result & 0x1f; /* the 5 LSB = which bit to set */
whichreg = result >> 5; /* the 3 MSB = which reg to set it in */
value = (1 << (31-whichbit));
reg_array = &(regs->hash.gaddr0);
if (set) {
reg_array[whichreg] |= value;
} else {
reg_array[whichreg] &= ~value;
}
return 0;
}
#endif /* Multicast TFTP ? */