t3_hw.c
来自「linux 内核源代码」· C语言 代码 · 共 2,149 行 · 第 1/5 页
C
2,149 行
} if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */ ctl |= BMCR_ANENABLE; return mdio_write(phy, 0, MII_BMCR, ctl);}static const struct adapter_info t3_adap_info[] = { {2, 0, 0, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, 0, &mi1_mdio_ops, "Chelsio PE9000"}, {2, 0, 0, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, 0, &mi1_mdio_ops, "Chelsio T302"}, {1, 0, 0, 0, F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T310"}, {2, 0, 0, 0, F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T320"},};/* * Return the adapter_info structure with a given index. Out-of-range indices * return NULL. */const struct adapter_info *t3_get_adapter_info(unsigned int id){ return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL;}#define CAPS_1G (SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | \ SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII)#define CAPS_10G (SUPPORTED_10000baseT_Full | SUPPORTED_AUI)static const struct port_type_info port_types[] = { {NULL}, {t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE, "10GBASE-XR"}, {t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T"}, {NULL, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T"}, {t3_xaui_direct_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, {NULL, CAPS_10G, "10GBASE-KX4"}, {t3_qt2045_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, {t3_ael1006_phy_prep, CAPS_10G | SUPPORTED_FIBRE, "10GBASE-SR"}, {NULL, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"},};#undef CAPS_1G#undef CAPS_10G#define VPD_ENTRY(name, len) \ u8 name##_kword[2]; u8 name##_len; u8 name##_data[len]/* * Partial EEPROM Vital Product Data structure. Includes only the ID and * VPD-R sections. */struct t3_vpd { u8 id_tag; u8 id_len[2]; u8 id_data[16]; u8 vpdr_tag; u8 vpdr_len[2]; VPD_ENTRY(pn, 16); /* part number */ VPD_ENTRY(ec, 16); /* EC level */ VPD_ENTRY(sn, SERNUM_LEN); /* serial number */ VPD_ENTRY(na, 12); /* MAC address base */ VPD_ENTRY(cclk, 6); /* core clock */ VPD_ENTRY(mclk, 6); /* mem clock */ VPD_ENTRY(uclk, 6); /* uP clk */ VPD_ENTRY(mdc, 6); /* MDIO clk */ VPD_ENTRY(mt, 2); /* mem timing */ VPD_ENTRY(xaui0cfg, 6); /* XAUI0 config */ VPD_ENTRY(xaui1cfg, 6); /* XAUI1 config */ VPD_ENTRY(port0, 2); /* PHY0 complex */ VPD_ENTRY(port1, 2); /* PHY1 complex */ VPD_ENTRY(port2, 2); /* PHY2 complex */ VPD_ENTRY(port3, 2); /* PHY3 complex */ VPD_ENTRY(rv, 1); /* csum */ u32 pad; /* for multiple-of-4 sizing and alignment */};#define EEPROM_MAX_POLL 4#define EEPROM_STAT_ADDR 0x4000#define VPD_BASE 0xc00/** * t3_seeprom_read - read a VPD EEPROM location * @adapter: adapter to read * @addr: EEPROM address * @data: where to store the read data * * Read a 32-bit word from a location in VPD EEPROM using the card's PCI * VPD ROM capability. A zero is written to the flag bit when the * addres is written to the control register. The hardware device will * set the flag to 1 when 4 bytes have been read into the data register. */int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data){ u16 val; int attempts = EEPROM_MAX_POLL; unsigned int base = adapter->params.pci.vpd_cap_addr; if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3)) return -EINVAL; pci_write_config_word(adapter->pdev, base + PCI_VPD_ADDR, addr); do { udelay(10); pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val); } while (!(val & PCI_VPD_ADDR_F) && --attempts); if (!(val & PCI_VPD_ADDR_F)) { CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr); return -EIO; } pci_read_config_dword(adapter->pdev, base + PCI_VPD_DATA, data); *data = le32_to_cpu(*data); return 0;}/** * t3_seeprom_write - write a VPD EEPROM location * @adapter: adapter to write * @addr: EEPROM address * @data: value to write * * Write a 32-bit word to a location in VPD EEPROM using the card's PCI * VPD ROM capability. */int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data){ u16 val; int attempts = EEPROM_MAX_POLL; unsigned int base = adapter->params.pci.vpd_cap_addr; if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3)) return -EINVAL; pci_write_config_dword(adapter->pdev, base + PCI_VPD_DATA, cpu_to_le32(data)); pci_write_config_word(adapter->pdev,base + PCI_VPD_ADDR, addr | PCI_VPD_ADDR_F); do { msleep(1); pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val); } while ((val & PCI_VPD_ADDR_F) && --attempts); if (val & PCI_VPD_ADDR_F) { CH_ERR(adapter, "write to EEPROM address 0x%x failed\n", addr); return -EIO; } return 0;}/** * t3_seeprom_wp - enable/disable EEPROM write protection * @adapter: the adapter * @enable: 1 to enable write protection, 0 to disable it * * Enables or disables write protection on the serial EEPROM. */int t3_seeprom_wp(struct adapter *adapter, int enable){ return t3_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0);}/* * Convert a character holding a hex digit to a number. */static unsigned int hex2int(unsigned char c){ return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10;}/** * get_vpd_params - read VPD parameters from VPD EEPROM * @adapter: adapter to read * @p: where to store the parameters * * Reads card parameters stored in VPD EEPROM. */static int get_vpd_params(struct adapter *adapter, struct vpd_params *p){ int i, addr, ret; struct t3_vpd vpd; /* * Card information is normally at VPD_BASE but some early cards had * it at 0. */ ret = t3_seeprom_read(adapter, VPD_BASE, (u32 *)&vpd); if (ret) return ret; addr = vpd.id_tag == 0x82 ? VPD_BASE : 0; for (i = 0; i < sizeof(vpd); i += 4) { ret = t3_seeprom_read(adapter, addr + i, (u32 *)((u8 *)&vpd + i)); if (ret) return ret; } p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10); p->mclk = simple_strtoul(vpd.mclk_data, NULL, 10); p->uclk = simple_strtoul(vpd.uclk_data, NULL, 10); p->mdc = simple_strtoul(vpd.mdc_data, NULL, 10); p->mem_timing = simple_strtoul(vpd.mt_data, NULL, 10); memcpy(p->sn, vpd.sn_data, SERNUM_LEN); /* Old eeproms didn't have port information */ if (adapter->params.rev == 0 && !vpd.port0_data[0]) { p->port_type[0] = uses_xaui(adapter) ? 1 : 2; p->port_type[1] = uses_xaui(adapter) ? 6 : 2; } else { p->port_type[0] = hex2int(vpd.port0_data[0]); p->port_type[1] = hex2int(vpd.port1_data[0]); p->xauicfg[0] = simple_strtoul(vpd.xaui0cfg_data, NULL, 16); p->xauicfg[1] = simple_strtoul(vpd.xaui1cfg_data, NULL, 16); } for (i = 0; i < 6; i++) p->eth_base[i] = hex2int(vpd.na_data[2 * i]) * 16 + hex2int(vpd.na_data[2 * i + 1]); return 0;}/* serial flash and firmware constants */enum { SF_ATTEMPTS = 5, /* max retries for SF1 operations */ SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ SF_SIZE = SF_SEC_SIZE * 8, /* serial flash size */ /* flash command opcodes */ SF_PROG_PAGE = 2, /* program page */ SF_WR_DISABLE = 4, /* disable writes */ SF_RD_STATUS = 5, /* read status register */ SF_WR_ENABLE = 6, /* enable writes */ SF_RD_DATA_FAST = 0xb, /* read flash */ SF_ERASE_SECTOR = 0xd8, /* erase sector */ FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */ FW_MIN_SIZE = 8 /* at least version and csum */};/** * sf1_read - read data from the serial flash * @adapter: the adapter * @byte_cnt: number of bytes to read * @cont: whether another operation will be chained * @valp: where to store the read data * * Reads up to 4 bytes of data from the serial flash. The location of * the read needs to be specified prior to calling this by issuing the * appropriate commands to the serial flash. */static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont, u32 *valp){ int ret; if (!byte_cnt || byte_cnt > 4) return -EINVAL; if (t3_read_reg(adapter, A_SF_OP) & F_BUSY) return -EBUSY; t3_write_reg(adapter, A_SF_OP, V_CONT(cont) | V_BYTECNT(byte_cnt - 1)); ret = t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10); if (!ret) *valp = t3_read_reg(adapter, A_SF_DATA); return ret;}/** * sf1_write - write data to the serial flash * @adapter: the adapter * @byte_cnt: number of bytes to write * @cont: whether another operation will be chained * @val: value to write * * Writes up to 4 bytes of data to the serial flash. The location of * the write needs to be specified prior to calling this by issuing the * appropriate commands to the serial flash. */static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont, u32 val){ if (!byte_cnt || byte_cnt > 4) return -EINVAL; if (t3_read_reg(adapter, A_SF_OP) & F_BUSY) return -EBUSY; t3_write_reg(adapter, A_SF_DATA, val); t3_write_reg(adapter, A_SF_OP, V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1)); return t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10);}/** * flash_wait_op - wait for a flash operation to complete * @adapter: the adapter * @attempts: max number of polls of the status register * @delay: delay between polls in ms * * Wait for a flash operation to complete by polling the status register. */static int flash_wait_op(struct adapter *adapter, int attempts, int delay){ int ret; u32 status; while (1) { if ((ret = sf1_write(adapter, 1, 1, SF_RD_STATUS)) != 0 || (ret = sf1_read(adapter, 1, 0, &status)) != 0) return ret; if (!(status & 1)) return 0; if (--attempts == 0) return -EAGAIN; if (delay) msleep(delay); }}/** * t3_read_flash - read words from serial flash * @adapter: the adapter * @addr: the start address for the read * @nwords: how many 32-bit words to read * @data: where to store the read data * @byte_oriented: whether to store data as bytes or as words * * Read the specified number of 32-bit words from the serial flash. * If @byte_oriented is set the read data is stored as a byte array * (i.e., big-endian), otherwise as 32-bit words in the platform's * natural endianess. */int t3_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords, u32 *data, int byte_oriented){ int ret; if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3)) return -EINVAL; addr = swab32(addr) | SF_RD_DATA_FAST; if ((ret = sf1_write(adapter, 4, 1, addr)) != 0 || (ret = sf1_read(adapter, 1, 1, data)) != 0) return ret; for (; nwords; nwords--, data++) { ret = sf1_read(adapter, 4, nwords > 1, data); if (ret) return ret; if (byte_oriented) *data = htonl(*data); } return 0;}/** * t3_write_flash - write up to a page of data to the serial flash * @adapter: the adapter * @addr: the start address to write * @n: length of data to write * @data: the data to write * * Writes up to a page of data (256 bytes) to the serial flash starting * at the given address. */static int t3_write_flash(struct adapter *adapter, unsigned int addr, unsigned int n, const u8 *data){ int ret; u32 buf[64]; unsigned int i, c, left, val, offset = addr & 0xff; if (addr + n > SF_SIZE || offset + n > 256) return -EINVAL; val = swab32(addr) | SF_PROG_PAGE; if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 || (ret = sf1_write(adapter, 4, 1, val)) != 0) return ret; for (left = n; left; left -= c) { c = min(left, 4U); for (val = 0, i = 0; i < c; ++i) val = (val << 8) + *data++; ret = sf1_write(adapter, c, c != left, val); if (ret) return ret; } if ((ret = flash_wait_op(adapter, 5, 1)) != 0) return ret; /* Read the page to verify the write succeeded */ ret = t3_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1); if (ret) return ret; if (memcmp(data - n, (u8 *) buf + offset, n)) return -EIO; return 0;}/** * t3_get_tp_version - read the tp sram version * @adapter: the adapter * @vers: where to place the version * * Reads the protocol sram version from sram. */int t3_get_tp_version(struct adapter *adapter, u32 *vers){ int ret;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?