static u32 get_phy_productid(struct ti_lynx *lynx) { u32 id = 0; sel_phy_reg_page(lynx, 1); id |= (get_phy_reg(lynx, 13) << 16); id |= (get_phy_reg(lynx, 14) << 8); id |= get_phy_reg(lynx, 15); PRINT(KERN_INFO, lynx->id, "PHY product id 0x%06x", id); return id; }
static u32 get_phy_vendorid(struct ti_lynx *lynx) { u32 pvid = 0; sel_phy_reg_page(lynx, 1); pvid |= (get_phy_reg(lynx, 10) << 16); pvid |= (get_phy_reg(lynx, 11) << 8); pvid |= get_phy_reg(lynx, 12); PRINT(KERN_INFO, lynx->id, "PHY vendor id 0x%06x", pvid); return pvid; }
static quadlet_t generate_own_selfid(struct ti_lynx *lynx, struct hpsb_host *host) { quadlet_t lsid; char phyreg[7]; int i; phyreg[0] = lynx->phy_reg0; for (i = 1; i < 7; i++) { phyreg[i] = get_phy_reg(lynx, i); } /* FIXME? We assume a TSB21LV03A phy here. This code doesn't support more than 3 ports on the PHY anyway. */ lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22); lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */ lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */ if (!hpsb_disable_irm) lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */ /* lsid |= 1 << 11; *//* set contender (hack) */ lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */ for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */ if (phyreg[3 + i] & 0x4) { lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3) << (6 - i*2); } else {
/*********************************** * IEEE-1394 functionality section * ***********************************/ static int get_phy_reg(struct ti_lynx *lynx, int addr) { int retval; int i = 0; unsigned long flags; if (addr > 15) { PRINT(KERN_ERR, lynx->id, "%s: PHY register address %d out of range", __FUNCTION__, addr); return -1; } spin_lock_irqsave(&lynx->phy_reg_lock, flags); reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr)); do { retval = reg_read(lynx, LINK_PHY); if (i > 10000) { PRINT(KERN_ERR, lynx->id, "%s: runaway loop, aborting", __FUNCTION__); retval = -1; break; } i++; } while ((retval & 0xf00) != LINK_PHY_RADDR(addr)); reg_write(lynx, LINK_INT_STATUS, LINK_INT_PHY_REG_RCVD); spin_unlock_irqrestore(&lynx->phy_reg_lock, flags); if (retval != -1) { return retval & 0xff; } else { return -1; } } static int set_phy_reg(struct ti_lynx *lynx, int addr, int val) { unsigned long flags; if (addr > 15) { PRINT(KERN_ERR, lynx->id, "%s: PHY register address %d out of range", __FUNCTION__, addr); return -1; } if (val > 0xff) { PRINT(KERN_ERR, lynx->id, "%s: PHY register value %d out of range", __FUNCTION__, val); return -1; } spin_lock_irqsave(&lynx->phy_reg_lock, flags); reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(addr) | LINK_PHY_WDATA(val)); spin_unlock_irqrestore(&lynx->phy_reg_lock, flags); return 0; } static int sel_phy_reg_page(struct ti_lynx *lynx, int page) { int reg; if (page > 7) { PRINT(KERN_ERR, lynx->id, "%s: PHY page %d out of range", __FUNCTION__, page); return -1; } reg = get_phy_reg(lynx, 7); if (reg != -1) { reg &= 0x1f; reg |= (page << 5); set_phy_reg(lynx, 7, reg); return 0; } else { return -1; } } #if 0 /* not needed at this time */ static int sel_phy_reg_port(struct ti_lynx *lynx, int port) { int reg; if (port > 15) { PRINT(KERN_ERR, lynx->id, "%s: PHY port %d out of range", __FUNCTION__, port); return -1; } reg = get_phy_reg(lynx, 7); if (reg != -1) { reg &= 0xf0; reg |= port; set_phy_reg(lynx, 7, reg); return 0; } else { return -1; } }
static int sel_phy_reg_page(struct ti_lynx *lynx, int page) { int reg; if (page > 7) { PRINT(KERN_ERR, lynx->id, "%s: PHY page %d out of range", __FUNCTION__, page); return -1; } reg = get_phy_reg(lynx, 7); if (reg != -1) { reg &= 0x1f; reg |= (page << 5); set_phy_reg(lynx, 7, reg); return 0; } else { return -1; } }
int mdio_main(int argc, char *argv[]) #endif { int ret; int i; /* test related */ uint16_t phy_id; uint16_t reg_num; uint16_t val_in; uint16_t val_out; /*--- SETUP --------------------------------------------------------------*/ if (argc == 1) { printf("usage:\n"); printf("\n"); printf(" %s phy_id reg_no -- read register\n", argv[0]); printf(" %s phy_id reg_no value -- write register\n", argv[0]); printf("\n"); return -1; } initialize_socket(); if (argc == 4) /* Write to register */ { phy_id = strtol(argv[1], NULL, 16); reg_num = strtol(argv[2], NULL, 16); val_in = strtol(argv[3], NULL, 16); ret = set_phy_reg(phy_id, reg_num, val_in); if (ret != 0) { printf("%s() returned %d\n", "set_phy_reg", ret); } } else if (argc == 3) /* Read from register */ { phy_id = strtol(argv[1], NULL, 16); reg_num = strtol(argv[2], NULL, 16); ret = get_phy_reg(phy_id, reg_num, &val_out); if (ret != 0) { printf("%s() returned %d\n", "get_phy_reg", ret); } else { printf("0x%4x\n", val_out); } } else if (argc == 2) { phy_id = strtol(argv[1], NULL, 16); for (i = 0; i < 32; i++) { ret = get_phy_reg(phy_id, i, &val_out); printf("phy[%d][%d] = 0x%4x\n", phy_id, i, val_out); } } else { /* Read the PHY address */ phy_id = get_phy_id(); if (phy_id < 1) { /* failed (can not be negative) */ printf("getting phy id failed\n"); } else { printf("phy_id = %d\n", phy_id); } } return 0; }