Newer
Older
/* This returns the status bits of the device. The return value
* is never checked, and this is what the 8260 driver did, so we
* do the same. Presumably, this would be zero if there were no
* errors
*/
static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
{
int i;
int result = 0;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
volatile tsec_t *regs = priv->regs;
/* Find an empty buffer descriptor */
for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
debug("%s: tsec: tx buffers full\n", dev->name);
return result;
}
}
rtx.txbd[txIdx].bufPtr = (uint) packet;
rtx.txbd[txIdx].length = length;
rtx.txbd[txIdx].status |=
(TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
/* Tell the DMA to go */
regs->tstat = TSTAT_CLEAR_THALT;
/* Wait for buffer to be transmitted */
for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
debug("%s: tsec: tx error\n", dev->name);
return result;
}
}
txIdx = (txIdx + 1) % TX_BUF_CNT;
result = rtx.txbd[txIdx].status & TXBD_STATS;
return result;
}
static int tsec_recv(struct eth_device *dev)
struct tsec_private *priv = (struct tsec_private *)dev->priv;
volatile tsec_t *regs = priv->regs;
while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
length = rtx.rxbd[rxIdx].length;
/* Send the packet up if there were no errors */
if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
NetReceive(NetRxPackets[rxIdx], length - 4);
} else {
printf("Got error %x\n",
(rtx.rxbd[rxIdx].status & RXBD_STATS));
}
rtx.rxbd[rxIdx].length = 0;
/* Set the wrap bit if this is the last element in the list */
rtx.rxbd[rxIdx].status =
RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
rxIdx = (rxIdx + 1) % PKTBUFSRX;
}
if (regs->ievent & IEVENT_BSY) {
regs->ievent = IEVENT_BSY;
regs->rstat = RSTAT_CLEAR_RHALT;
}
return -1;
}
static void tsec_halt(struct eth_device *dev)
struct tsec_private *priv = (struct tsec_private *)dev->priv;
volatile tsec_t *regs = priv->regs;
regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
while ((regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))
!= (IEVENT_GRSC | IEVENT_GTSC)) ;
regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
/* Shut down the PHY, as needed */
if(priv->phyinfo)
phy_run_commands(priv, priv->phyinfo->shutdown);
static struct phy_info phy_info_M88E1149S = {
0x1410ca,
"Marvell 88E1149S",
4,
/* 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,}
},
/* 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},
/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */
static struct phy_info phy_info_BCM5461S = {
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
0x02060c1, /* 5461 ID */
"Broadcom BCM5461S",
0, /* not clear to me what minor revisions we can shift away */
(struct phy_cmd[]) { /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, 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_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
{miim_end,}
},
(struct phy_cmd[]) { /* shutdown */
{miim_end,}
},
};
static struct phy_info phy_info_BCM5464S = {
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
0x02060b1, /* 5464 ID */
"Broadcom BCM5464S",
0, /* not clear to me what minor revisions we can shift away */
(struct phy_cmd[]) { /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, 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_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
{miim_end,}
},
(struct phy_cmd[]) { /* shutdown */
{miim_end,}
},
};
static struct phy_info phy_info_BCM5482S = {
0x0143bcb,
"Broadcom BCM5482S",
4,
(struct phy_cmd[]) { /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
/* Setup read from auxilary control shadow register 7 */
{MIIM_BCM54xx_AUXCNTL, MIIM_BCM54xx_AUXCNTL_ENCODE(7), NULL},
/* Read Misc Control register and or in Ethernet@Wirespeed */
{MIIM_BCM54xx_AUXCNTL, 0, &mii_BCM54xx_wirespeed},
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
/* Initial config/enable of secondary SerDes interface */
{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf), NULL},
/* Write intial value to secondary SerDes Contol */
{MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_SSD | 0, NULL},
{MIIM_BCM54XX_EXP_DATA, MIIM_CONTROL_RESTART, NULL},
/* Enable copper/fiber auto-detect */
{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201)},
{miim_end,}
},
(struct phy_cmd[]) { /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Determine copper/fiber, auto-negotiate, and read the result */
{MIIM_STATUS, miim_read, &mii_parse_BCM5482_sr},
{miim_end,}
},
(struct phy_cmd[]) { /* shutdown */
{miim_end,}
},
};
static struct phy_info phy_info_M88E1011S = {
0x01410c6,
"Marvell 88E1011S",
4,
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
(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,}
},
static struct phy_info phy_info_M88E1111S = {
0x01410cc,
"Marvell 88E1111S",
4,
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
(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 struct phy_info phy_info_M88E1118 = {
0x01410e1,
"Marvell 88E1118",
4,
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{0x16, 0x0002, NULL}, /* Change Page Number */
{0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */
{0x16, 0x0003, NULL}, /* Change Page Number */
{0x10, 0x021e, NULL}, /* Adjust LED control */
{0x16, 0x0000, NULL}, /* Change Page Number */
{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,}
{0x16, 0x0000, NULL}, /* Change Page Number */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
/* Read the status */
{MIIM_88E1011_PHY_STATUS, miim_read,
&mii_parse_88E1011_psr},
{miim_end,}
/*
* Since to access LED register we need do switch the page, we
* do LED configuring in the miim_read-like function as follows
*/
static uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv)
{
uint pg;
/* Switch the page to access the led register */
pg = read_phy_reg(priv, MIIM_88E1121_PHY_PAGE);
write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, MIIM_88E1121_PHY_LED_PAGE);
/* Configure leds */
write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL,
MIIM_88E1121_PHY_LED_DEF);
/* Restore the page pointer */
write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg);
return 0;
}
static struct phy_info phy_info_M88E1121R = {
0x01410cb,
"Marvell 88E1121R",
4,
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
(struct phy_cmd[]) { /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
/* Configure leds */
{MIIM_88E1121_PHY_LED_CTRL, miim_read, &mii_88E1121_set_led},
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
/* Disable IRQs and de-assert interrupt */
{MIIM_88E1121_PHY_IRQ_EN, 0, NULL},
{MIIM_88E1121_PHY_IRQ_STATUS, miim_read, NULL},
{miim_end,}
},
(struct phy_cmd[]) { /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
{MIIM_STATUS, miim_read, &mii_parse_sr},
{MIIM_STATUS, miim_read, &mii_parse_link},
{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,
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
(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},
/* Configure the PHY */
{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,}
},
static struct phy_info phy_info_cis8204 = {
0x3f11,
"Cicada Cis8204",
6,
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
(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 */
static struct phy_info phy_info_cis8201 = {
0xfc41,
"CIS8201",
4,
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
(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,}
},
static struct phy_info phy_info_VSC8211 = {
0xfc4b,
"Vitesse VSC8211",
4,
(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 */
static struct phy_info phy_info_VSC8244 = {
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,}
},
static struct phy_info phy_info_VSC8641 = {
0x7043,
"Vitesse VSC8641",
4,
(struct phy_cmd[]) { /* config */
/* 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,}
},
};
static struct phy_info phy_info_VSC8221 = {
0xfc55,
"Vitesse VSC8221",
4,
(struct phy_cmd[]) { /* config */
/* 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,}
},
};
static struct phy_info phy_info_VSC8601 = {
0x00007042,
"Vitesse VSC8601",
4,
(struct phy_cmd[]) { /* config */
/* Override PHY config settings */
/* Configure some basic stuff */
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
#ifdef CONFIG_SYS_VSC8601_SKEWFIX
{MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL},
#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
{MIIM_EXT_PAGE_ACCESS,1,NULL},
#define VSC8101_SKEW \
(CONFIG_SYS_VSC8601_SKEW_TX << 14) | (CONFIG_SYS_VSC8601_SKEW_RX << 12)
{MIIM_VSC8601_SKEW_CTRL,VSC8101_SKEW,NULL},
{MIIM_EXT_PAGE_ACCESS,0,NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_CONTROL, MIIM_CONTROL_RESTART, &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,}
},
static struct phy_info phy_info_dm9161 = {
0x0181b88,
"Davicom DM9161E",
4,
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
(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,}
},
/* a generic flavor. */
static 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,}
}
};
static 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
static uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
{
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;
}
static 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,}
},
static struct phy_info phy_info_rtl8211b = {
0x001cc91,
"RealTek RTL8211B",
4,
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, 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,}
},
/* 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_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr},
{miim_end,}
},
{miim_end,}
},
};
static struct phy_info *phy_info[] = {
&phy_info_M88E1121R,
&phy_info_VSC8641,
&phy_info_VSC8221,
&phy_info_dp83865,
&phy_info_generic, /* must be last; has ID 0 and 32 bit mask */
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
*/
static 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)) {
if (theInfo == &phy_info_generic) {
printf("%s: No support for PHY id %x; assuming generic\n",
dev->name, phy_ID);
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
*/
static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
{
int i;
uint result;
volatile tsec_mdio_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++;
}
}
#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;
}
ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, 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;
}
tsec_local_mdio_write(priv->phyregs, addr, reg, value);
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
#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 ? */