📄 tsec.c
字号:
/* 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}, /* 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,} },};struct phy_info phy_info_cis8204 = { 0x3f11, "Cicada Cis8204", 6, (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, (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 = { 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, (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. */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; break; 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 * information */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_cis8201, &phy_info_BCM5461S, &phy_info_BCM5464S, &phy_info_M88E1011S, &phy_info_M88E1111S, &phy_info_M88E1145, &phy_info_M88E1149S, &phy_info_dm9161, &phy_info_lxt971, &phy_info_VSC8244, &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)) { theInfo = phy_info[i]; break; } } if (theInfo == NULL) { 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); } else { 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; int i, j, k; 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); phy_info[i]->startup = (struct phy_cmd *)((uint) phy_info[i]->startup + gd->reloc_off); phy_info[i]->shutdown = (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 */ if (cmd->funct) cmd->funct += gd->reloc_off; k++; } j++; } } relocated = 1;}#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ && !defined(BITBANGMII)struct tsec_private *get_priv_for_phy(unsigned char phyaddr){ int i; for (i = 0; i < MAXCONTROLLERS; i++) { if (privlist[i]->phyaddr == phyaddr) return privlist[i]; } return NULL;}/* * Read a MII PHY register. * * Returns: * 0 on success */static int tsec_miiphy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value){ unsigned short ret; struct tsec_private *priv = get_priv_for_phy(addr); if (NULL == priv) { printf("Can't read PHY at address %d\n", addr); return -1; } ret = (unsigned short)read_phy_reg(priv, reg); *value = ret; return 0;}/* * Write a MII PHY register. * * Returns: * 0 on success */static int tsec_miiphy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value){ struct tsec_private *priv = get_priv_for_phy(addr); if (NULL == priv) { printf("Can't write PHY at address %d\n", addr); return -1; } write_phy_reg(priv, reg, value); return 0;}#endif#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 inttsec_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 ? */#endif /* CONFIG_TSEC_ENET */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -