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 + -
显示快捷键?