Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v6.13.7.
   1/*****************************************************************************
   2 *                                                                           *
   3 * File: subr.c                                                              *
   4 * $Revision: 1.27 $                                                         *
   5 * $Date: 2005/06/22 01:08:36 $                                              *
   6 * Description:                                                              *
   7 *  Various subroutines (intr,pio,etc.) used by Chelsio 10G Ethernet driver. *
   8 *  part of the Chelsio 10Gb Ethernet Driver.                                *
   9 *                                                                           *
  10 * This program is free software; you can redistribute it and/or modify      *
  11 * it under the terms of the GNU General Public License, version 2, as       *
  12 * published by the Free Software Foundation.                                *
  13 *                                                                           *
  14 * You should have received a copy of the GNU General Public License along   *
  15 * with this program; if not, write to the Free Software Foundation, Inc.,   *
  16 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 *
  17 *                                                                           *
  18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
  20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
  21 *                                                                           *
  22 * http://www.chelsio.com                                                    *
  23 *                                                                           *
  24 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
  25 * All rights reserved.                                                      *
  26 *                                                                           *
  27 * Maintainers: maintainers@chelsio.com                                      *
  28 *                                                                           *
  29 * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
  30 *          Tina Yang               <tainay@chelsio.com>                     *
  31 *          Felix Marti             <felix@chelsio.com>                      *
  32 *          Scott Bardone           <sbardone@chelsio.com>                   *
  33 *          Kurt Ottaway            <kottaway@chelsio.com>                   *
  34 *          Frank DiMambro          <frank@chelsio.com>                      *
  35 *                                                                           *
  36 * History:                                                                  *
  37 *                                                                           *
  38 ****************************************************************************/
  39
  40#include "common.h"
  41#include "elmer0.h"
  42#include "regs.h"
  43#include "gmac.h"
  44#include "cphy.h"
  45#include "sge.h"
  46#include "tp.h"
  47#include "espi.h"
  48
  49/**
  50 *	t1_wait_op_done - wait until an operation is completed
  51 *	@adapter: the adapter performing the operation
  52 *	@reg: the register to check for completion
  53 *	@mask: a single-bit field within @reg that indicates completion
  54 *	@polarity: the value of the field when the operation is completed
  55 *	@attempts: number of check iterations
  56 *      @delay: delay in usecs between iterations
  57 *
  58 *	Wait until an operation is completed by checking a bit in a register
  59 *	up to @attempts times.  Returns %0 if the operation completes and %1
  60 *	otherwise.
  61 */
  62static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
  63			   int attempts, int delay)
  64{
  65	while (1) {
  66		u32 val = readl(adapter->regs + reg) & mask;
  67
  68		if (!!val == polarity)
  69			return 0;
  70		if (--attempts == 0)
  71			return 1;
  72		if (delay)
  73			udelay(delay);
  74	}
  75}
  76
  77#define TPI_ATTEMPTS 50
  78
  79/*
  80 * Write a register over the TPI interface (unlocked and locked versions).
  81 */
  82int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
  83{
  84	int tpi_busy;
  85
  86	writel(addr, adapter->regs + A_TPI_ADDR);
  87	writel(value, adapter->regs + A_TPI_WR_DATA);
  88	writel(F_TPIWR, adapter->regs + A_TPI_CSR);
  89
  90	tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
  91				   TPI_ATTEMPTS, 3);
  92	if (tpi_busy)
  93		pr_alert("%s: TPI write to 0x%x failed\n",
  94			 adapter->name, addr);
  95	return tpi_busy;
  96}
  97
  98int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
  99{
 100	int ret;
 101
 102	spin_lock(&adapter->tpi_lock);
 103	ret = __t1_tpi_write(adapter, addr, value);
 104	spin_unlock(&adapter->tpi_lock);
 105	return ret;
 106}
 107
 108/*
 109 * Read a register over the TPI interface (unlocked and locked versions).
 110 */
 111int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
 112{
 113	int tpi_busy;
 114
 115	writel(addr, adapter->regs + A_TPI_ADDR);
 116	writel(0, adapter->regs + A_TPI_CSR);
 117
 118	tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
 119				   TPI_ATTEMPTS, 3);
 120	if (tpi_busy)
 121		pr_alert("%s: TPI read from 0x%x failed\n",
 122			 adapter->name, addr);
 123	else
 124		*valp = readl(adapter->regs + A_TPI_RD_DATA);
 125	return tpi_busy;
 126}
 127
 128int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
 129{
 130	int ret;
 131
 132	spin_lock(&adapter->tpi_lock);
 133	ret = __t1_tpi_read(adapter, addr, valp);
 134	spin_unlock(&adapter->tpi_lock);
 135	return ret;
 136}
 137
 138/*
 139 * Set a TPI parameter.
 140 */
 141static void t1_tpi_par(adapter_t *adapter, u32 value)
 142{
 143	writel(V_TPIPAR(value), adapter->regs + A_TPI_PAR);
 144}
 145
 146/*
 147 * Called when a port's link settings change to propagate the new values to the
 148 * associated PHY and MAC.  After performing the common tasks it invokes an
 149 * OS-specific handler.
 150 */
 151void t1_link_changed(adapter_t *adapter, int port_id)
 152{
 153	int link_ok, speed, duplex, fc;
 154	struct cphy *phy = adapter->port[port_id].phy;
 155	struct link_config *lc = &adapter->port[port_id].link_config;
 156
 157	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
 158
 159	lc->speed = speed < 0 ? SPEED_INVALID : speed;
 160	lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
 161	if (!(lc->requested_fc & PAUSE_AUTONEG))
 162		fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
 163
 164	if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
 165		/* Set MAC speed, duplex, and flow control to match PHY. */
 166		struct cmac *mac = adapter->port[port_id].mac;
 167
 168		mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
 169		lc->fc = (unsigned char)fc;
 170	}
 171	t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc);
 172}
 173
 174static int t1_pci_intr_handler(adapter_t *adapter)
 175{
 176	u32 pcix_cause;
 177
 178	pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
 179
 180	if (pcix_cause) {
 181		pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
 182				       pcix_cause);
 183		t1_fatal_err(adapter);    /* PCI errors are fatal */
 184	}
 185	return 0;
 186}
 187
 188#ifdef CONFIG_CHELSIO_T1_1G
 189#include "fpga_defs.h"
 190
 191/*
 192 * PHY interrupt handler for FPGA boards.
 193 */
 194static int fpga_phy_intr_handler(adapter_t *adapter)
 195{
 196	int p;
 197	u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
 198
 199	for_each_port(adapter, p)
 200		if (cause & (1 << p)) {
 201			struct cphy *phy = adapter->port[p].phy;
 202			int phy_cause = phy->ops->interrupt_handler(phy);
 203
 204			if (phy_cause & cphy_cause_link_change)
 205				t1_link_changed(adapter, p);
 206		}
 207	writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
 208	return 0;
 209}
 210
 211/*
 212 * Slow path interrupt handler for FPGAs.
 213 */
 214static int fpga_slow_intr(adapter_t *adapter)
 215{
 216	u32 cause = readl(adapter->regs + A_PL_CAUSE);
 217
 218	cause &= ~F_PL_INTR_SGE_DATA;
 219	if (cause & F_PL_INTR_SGE_ERR)
 220		t1_sge_intr_error_handler(adapter->sge);
 221
 222	if (cause & FPGA_PCIX_INTERRUPT_GMAC)
 223		fpga_phy_intr_handler(adapter);
 224
 225	if (cause & FPGA_PCIX_INTERRUPT_TP) {
 226		/*
 227		 * FPGA doesn't support MC4 interrupts and it requires
 228		 * this odd layer of indirection for MC5.
 229		 */
 230		u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
 231
 232		/* Clear TP interrupt */
 233		writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
 234	}
 235	if (cause & FPGA_PCIX_INTERRUPT_PCIX)
 236		t1_pci_intr_handler(adapter);
 237
 238	/* Clear the interrupts just processed. */
 239	if (cause)
 240		writel(cause, adapter->regs + A_PL_CAUSE);
 241
 242	return cause != 0;
 243}
 244#endif
 245
 246/*
 247 * Wait until Elmer's MI1 interface is ready for new operations.
 248 */
 249static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
 250{
 251	int attempts = 100, busy;
 252
 253	do {
 254		u32 val;
 255
 256		__t1_tpi_read(adapter, mi1_reg, &val);
 257		busy = val & F_MI1_OP_BUSY;
 258		if (busy)
 259			udelay(10);
 260	} while (busy && --attempts);
 261	if (busy)
 262		pr_alert("%s: MDIO operation timed out\n", adapter->name);
 263	return busy;
 264}
 265
 266/*
 267 * MI1 MDIO initialization.
 268 */
 269static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
 270{
 271	u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
 272	u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
 273		V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
 274
 275	if (!(bi->caps & SUPPORTED_10000baseT_Full))
 276		val |= V_MI1_SOF(1);
 277	t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
 278}
 279
 280#if defined(CONFIG_CHELSIO_T1_1G)
 281/*
 282 * Elmer MI1 MDIO read/write operations.
 283 */
 284static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr,
 285			 u16 reg_addr)
 286{
 287	struct adapter *adapter = dev->ml_priv;
 288	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
 289	unsigned int val;
 290
 291	spin_lock(&adapter->tpi_lock);
 292	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 293	__t1_tpi_write(adapter,
 294			A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
 295	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 296	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
 297	spin_unlock(&adapter->tpi_lock);
 298	return val;
 299}
 300
 301static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
 302			  u16 reg_addr, u16 val)
 303{
 304	struct adapter *adapter = dev->ml_priv;
 305	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
 306
 307	spin_lock(&adapter->tpi_lock);
 308	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 309	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
 310	__t1_tpi_write(adapter,
 311			A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_WRITE);
 312	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 313	spin_unlock(&adapter->tpi_lock);
 314	return 0;
 315}
 316
 317static const struct mdio_ops mi1_mdio_ops = {
 318	.init = mi1_mdio_init,
 319	.read = mi1_mdio_read,
 320	.write = mi1_mdio_write,
 321	.mode_support = MDIO_SUPPORTS_C22
 322};
 323
 324#endif
 325
 326static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
 327			     u16 reg_addr)
 328{
 329	struct adapter *adapter = dev->ml_priv;
 330	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
 331	unsigned int val;
 332
 333	spin_lock(&adapter->tpi_lock);
 334
 335	/* Write the address we want. */
 336	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 337	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
 338	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
 339		       MI1_OP_INDIRECT_ADDRESS);
 340	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 341
 342	/* Write the operation we want. */
 343	__t1_tpi_write(adapter,
 344			A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
 345	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 346
 347	/* Read the data. */
 348	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
 349	spin_unlock(&adapter->tpi_lock);
 350	return val;
 351}
 352
 353static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr,
 354			      int mmd_addr, u16 reg_addr, u16 val)
 355{
 356	struct adapter *adapter = dev->ml_priv;
 357	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
 358
 359	spin_lock(&adapter->tpi_lock);
 360
 361	/* Write the address we want. */
 362	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 363	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
 364	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
 365		       MI1_OP_INDIRECT_ADDRESS);
 366	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 367
 368	/* Write the data. */
 369	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
 370	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
 371	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 372	spin_unlock(&adapter->tpi_lock);
 373	return 0;
 374}
 375
 376static const struct mdio_ops mi1_mdio_ext_ops = {
 377	.init = mi1_mdio_init,
 378	.read = mi1_mdio_ext_read,
 379	.write = mi1_mdio_ext_write,
 380	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
 381};
 382
 383enum {
 384	CH_BRD_T110_1CU,
 385	CH_BRD_N110_1F,
 386	CH_BRD_N210_1F,
 387	CH_BRD_T210_1F,
 388	CH_BRD_T210_1CU,
 389	CH_BRD_N204_4CU,
 390};
 391
 392static const struct board_info t1_board[] = {
 393	{
 394		.board		= CHBT_BOARD_CHT110,
 395		.port_number	= 1,
 396		.caps		= SUPPORTED_10000baseT_Full,
 397		.chip_term	= CHBT_TERM_T1,
 398		.chip_mac	= CHBT_MAC_PM3393,
 399		.chip_phy	= CHBT_PHY_MY3126,
 400		.clock_core	= 125000000,
 401		.clock_mc3	= 150000000,
 402		.clock_mc4	= 125000000,
 403		.espi_nports	= 1,
 404		.clock_elmer0	= 44,
 405		.mdio_mdien	= 1,
 406		.mdio_mdiinv	= 1,
 407		.mdio_mdc	= 1,
 408		.mdio_phybaseaddr = 1,
 409		.gmac		= &t1_pm3393_ops,
 410		.gphy		= &t1_my3126_ops,
 411		.mdio_ops	= &mi1_mdio_ext_ops,
 412		.desc		= "Chelsio T110 1x10GBase-CX4 TOE",
 413	},
 414
 415	{
 416		.board		= CHBT_BOARD_N110,
 417		.port_number	= 1,
 418		.caps		= SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE,
 419		.chip_term	= CHBT_TERM_T1,
 420		.chip_mac	= CHBT_MAC_PM3393,
 421		.chip_phy	= CHBT_PHY_88X2010,
 422		.clock_core	= 125000000,
 423		.espi_nports	= 1,
 424		.clock_elmer0	= 44,
 425		.mdio_mdien	= 0,
 426		.mdio_mdiinv	= 0,
 427		.mdio_mdc	= 1,
 428		.mdio_phybaseaddr = 0,
 429		.gmac		= &t1_pm3393_ops,
 430		.gphy		= &t1_mv88x201x_ops,
 431		.mdio_ops	= &mi1_mdio_ext_ops,
 432		.desc		= "Chelsio N110 1x10GBaseX NIC",
 433	},
 434
 435	{
 436		.board		= CHBT_BOARD_N210,
 437		.port_number	= 1,
 438		.caps		= SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE,
 439		.chip_term	= CHBT_TERM_T2,
 440		.chip_mac	= CHBT_MAC_PM3393,
 441		.chip_phy	= CHBT_PHY_88X2010,
 442		.clock_core	= 125000000,
 443		.espi_nports	= 1,
 444		.clock_elmer0	= 44,
 445		.mdio_mdien	= 0,
 446		.mdio_mdiinv	= 0,
 447		.mdio_mdc	= 1,
 448		.mdio_phybaseaddr = 0,
 449		.gmac		= &t1_pm3393_ops,
 450		.gphy		= &t1_mv88x201x_ops,
 451		.mdio_ops	= &mi1_mdio_ext_ops,
 452		.desc		= "Chelsio N210 1x10GBaseX NIC",
 453	},
 454
 455	{
 456		.board		= CHBT_BOARD_CHT210,
 457		.port_number	= 1,
 458		.caps		= SUPPORTED_10000baseT_Full,
 459		.chip_term	= CHBT_TERM_T2,
 460		.chip_mac	= CHBT_MAC_PM3393,
 461		.chip_phy	= CHBT_PHY_88X2010,
 462		.clock_core	= 125000000,
 463		.clock_mc3	= 133000000,
 464		.clock_mc4	= 125000000,
 465		.espi_nports	= 1,
 466		.clock_elmer0	= 44,
 467		.mdio_mdien	= 0,
 468		.mdio_mdiinv	= 0,
 469		.mdio_mdc	= 1,
 470		.mdio_phybaseaddr = 0,
 471		.gmac		= &t1_pm3393_ops,
 472		.gphy		= &t1_mv88x201x_ops,
 473		.mdio_ops	= &mi1_mdio_ext_ops,
 474		.desc		= "Chelsio T210 1x10GBaseX TOE",
 475	},
 476
 477	{
 478		.board		= CHBT_BOARD_CHT210,
 479		.port_number	= 1,
 480		.caps		= SUPPORTED_10000baseT_Full,
 481		.chip_term	= CHBT_TERM_T2,
 482		.chip_mac	= CHBT_MAC_PM3393,
 483		.chip_phy	= CHBT_PHY_MY3126,
 484		.clock_core	= 125000000,
 485		.clock_mc3	= 133000000,
 486		.clock_mc4	= 125000000,
 487		.espi_nports	= 1,
 488		.clock_elmer0	= 44,
 489		.mdio_mdien	= 1,
 490		.mdio_mdiinv	= 1,
 491		.mdio_mdc	= 1,
 492		.mdio_phybaseaddr = 1,
 493		.gmac		= &t1_pm3393_ops,
 494		.gphy		= &t1_my3126_ops,
 495		.mdio_ops	= &mi1_mdio_ext_ops,
 496		.desc		= "Chelsio T210 1x10GBase-CX4 TOE",
 497	},
 498
 499#ifdef CONFIG_CHELSIO_T1_1G
 500	{
 501		.board		= CHBT_BOARD_CHN204,
 502		.port_number	= 4,
 503		.caps		= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full
 504				| SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full
 505				| SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
 506				  SUPPORTED_PAUSE | SUPPORTED_TP,
 507		.chip_term	= CHBT_TERM_T2,
 508		.chip_mac	= CHBT_MAC_VSC7321,
 509		.chip_phy	= CHBT_PHY_88E1111,
 510		.clock_core	= 100000000,
 511		.espi_nports	= 4,
 512		.clock_elmer0	= 44,
 513		.mdio_mdien	= 0,
 514		.mdio_mdiinv	= 0,
 515		.mdio_mdc	= 0,
 516		.mdio_phybaseaddr = 4,
 517		.gmac		= &t1_vsc7326_ops,
 518		.gphy		= &t1_mv88e1xxx_ops,
 519		.mdio_ops	= &mi1_mdio_ops,
 520		.desc		= "Chelsio N204 4x100/1000BaseT NIC",
 521	},
 522#endif
 523
 524};
 525
 526DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = {
 527	CH_DEVICE(8, 0, CH_BRD_T110_1CU),
 528	CH_DEVICE(8, 1, CH_BRD_T110_1CU),
 529	CH_DEVICE(7, 0, CH_BRD_N110_1F),
 530	CH_DEVICE(10, 1, CH_BRD_N210_1F),
 531	CH_DEVICE(11, 1, CH_BRD_T210_1F),
 532	CH_DEVICE(14, 1, CH_BRD_T210_1CU),
 533	CH_DEVICE(16, 1, CH_BRD_N204_4CU),
 534	{ 0 }
 535};
 536
 537MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
 538
 539/*
 540 * Return the board_info structure with a given index.  Out-of-range indices
 541 * return NULL.
 542 */
 543const struct board_info *t1_get_board_info(unsigned int board_id)
 544{
 545	return board_id < ARRAY_SIZE(t1_board) ? &t1_board[board_id] : NULL;
 546}
 547
 548struct chelsio_vpd_t {
 549	u32 format_version;
 550	u8 serial_number[16];
 551	u8 mac_base_address[6];
 552	u8 pad[2];           /* make multiple-of-4 size requirement explicit */
 553};
 554
 555#define EEPROMSIZE        (8 * 1024)
 556#define EEPROM_MAX_POLL   4
 557
 558/*
 559 * Read SEEPROM. A zero is written to the flag register when the address is
 560 * written to the Control register. The hardware device will set the flag to a
 561 * one when 4B have been transferred to the Data register.
 562 */
 563int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data)
 564{
 565	int i = EEPROM_MAX_POLL;
 566	u16 val;
 567	u32 v;
 568
 569	if (addr >= EEPROMSIZE || (addr & 3))
 570		return -EINVAL;
 571
 572	pci_write_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, (u16)addr);
 573	do {
 574		udelay(50);
 575		pci_read_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, &val);
 576	} while (!(val & F_VPD_OP_FLAG) && --i);
 577
 578	if (!(val & F_VPD_OP_FLAG)) {
 579		pr_err("%s: reading EEPROM address 0x%x failed\n",
 580		       adapter->name, addr);
 581		return -EIO;
 582	}
 583	pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, &v);
 584	*data = cpu_to_le32(v);
 585	return 0;
 586}
 587
 588static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
 589{
 590	int addr, ret = 0;
 591
 592	for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
 593		ret = t1_seeprom_read(adapter, addr,
 594				      (__le32 *)((u8 *)vpd + addr));
 595
 596	return ret;
 597}
 598
 599/*
 600 * Read a port's MAC address from the VPD ROM.
 601 */
 602static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
 603{
 604	struct chelsio_vpd_t vpd;
 605
 606	if (t1_eeprom_vpd_get(adapter, &vpd))
 607		return 1;
 608	memcpy(mac_addr, vpd.mac_base_address, 5);
 609	mac_addr[5] = vpd.mac_base_address[5] + index;
 610	return 0;
 611}
 612
 613/*
 614 * Set up the MAC/PHY according to the requested link settings.
 615 *
 616 * If the PHY can auto-negotiate first decide what to advertise, then
 617 * enable/disable auto-negotiation as desired and reset.
 618 *
 619 * If the PHY does not auto-negotiate we just reset it.
 620 *
 621 * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
 622 * otherwise do it later based on the outcome of auto-negotiation.
 623 */
 624int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
 625{
 626	unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
 627
 628	if (lc->supported & SUPPORTED_Autoneg) {
 629		lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
 630		if (fc) {
 631			if (fc == ((PAUSE_RX | PAUSE_TX) &
 632				   (mac->adapter->params.nports < 2)))
 633				lc->advertising |= ADVERTISED_PAUSE;
 634			else {
 635				lc->advertising |= ADVERTISED_ASYM_PAUSE;
 636				if (fc == PAUSE_RX)
 637					lc->advertising |= ADVERTISED_PAUSE;
 638			}
 639		}
 640		phy->ops->advertise(phy, lc->advertising);
 641
 642		if (lc->autoneg == AUTONEG_DISABLE) {
 643			lc->speed = lc->requested_speed;
 644			lc->duplex = lc->requested_duplex;
 645			lc->fc = (unsigned char)fc;
 646			mac->ops->set_speed_duplex_fc(mac, lc->speed,
 647						      lc->duplex, fc);
 648			/* Also disables autoneg */
 649			phy->state = PHY_AUTONEG_RDY;
 650			phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
 651			phy->ops->reset(phy, 0);
 652		} else {
 653			phy->state = PHY_AUTONEG_EN;
 654			phy->ops->autoneg_enable(phy); /* also resets PHY */
 655		}
 656	} else {
 657		phy->state = PHY_AUTONEG_RDY;
 658		mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
 659		lc->fc = (unsigned char)fc;
 660		phy->ops->reset(phy, 0);
 661	}
 662	return 0;
 663}
 664
 665/*
 666 * External interrupt handler for boards using elmer0.
 667 */
 668int t1_elmer0_ext_intr_handler(adapter_t *adapter)
 669{
 670	struct cphy *phy;
 671	int phy_cause;
 672	u32 cause;
 673
 674	t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
 675
 676	switch (board_info(adapter)->board) {
 677#ifdef CONFIG_CHELSIO_T1_1G
 678	case CHBT_BOARD_CHT204:
 679	case CHBT_BOARD_CHT204E:
 680	case CHBT_BOARD_CHN204:
 681	case CHBT_BOARD_CHT204V: {
 682		int i, port_bit;
 683		for_each_port(adapter, i) {
 684			port_bit = i + 1;
 685			if (!(cause & (1 << port_bit)))
 686				continue;
 687
 688			phy = adapter->port[i].phy;
 689			phy_cause = phy->ops->interrupt_handler(phy);
 690			if (phy_cause & cphy_cause_link_change)
 691				t1_link_changed(adapter, i);
 692		}
 693		break;
 694	}
 695	case CHBT_BOARD_CHT101:
 696		if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */
 697			phy = adapter->port[0].phy;
 698			phy_cause = phy->ops->interrupt_handler(phy);
 699			if (phy_cause & cphy_cause_link_change)
 700				t1_link_changed(adapter, 0);
 701		}
 702		break;
 703	case CHBT_BOARD_7500: {
 704		int p;
 705		/*
 706		 * Elmer0's interrupt cause isn't useful here because there is
 707		 * only one bit that can be set for all 4 ports.  This means
 708		 * we are forced to check every PHY's interrupt status
 709		 * register to see who initiated the interrupt.
 710		 */
 711		for_each_port(adapter, p) {
 712			phy = adapter->port[p].phy;
 713			phy_cause = phy->ops->interrupt_handler(phy);
 714			if (phy_cause & cphy_cause_link_change)
 715			    t1_link_changed(adapter, p);
 716		}
 717		break;
 718	}
 719#endif
 720	case CHBT_BOARD_CHT210:
 721	case CHBT_BOARD_N210:
 722	case CHBT_BOARD_N110:
 723		if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
 724			phy = adapter->port[0].phy;
 725			phy_cause = phy->ops->interrupt_handler(phy);
 726			if (phy_cause & cphy_cause_link_change)
 727				t1_link_changed(adapter, 0);
 728		}
 729		break;
 730	case CHBT_BOARD_8000:
 731	case CHBT_BOARD_CHT110:
 732		if (netif_msg_intr(adapter))
 733			dev_dbg(&adapter->pdev->dev,
 734				"External interrupt cause 0x%x\n", cause);
 735		if (cause & ELMER0_GP_BIT1) {        /* PMC3393 INTB */
 736			struct cmac *mac = adapter->port[0].mac;
 737
 738			mac->ops->interrupt_handler(mac);
 739		}
 740		if (cause & ELMER0_GP_BIT5) {        /* XPAK MOD_DETECT */
 741			u32 mod_detect;
 742
 743			t1_tpi_read(adapter,
 744					A_ELMER0_GPI_STAT, &mod_detect);
 745			if (netif_msg_link(adapter))
 746				dev_info(&adapter->pdev->dev, "XPAK %s\n",
 747					 mod_detect ? "removed" : "inserted");
 748		}
 749		break;
 750	}
 751	t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
 752	return 0;
 753}
 754
 755/* Enables all interrupts. */
 756void t1_interrupts_enable(adapter_t *adapter)
 757{
 758	unsigned int i;
 759
 760	adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP;
 761
 762	t1_sge_intr_enable(adapter->sge);
 763	t1_tp_intr_enable(adapter->tp);
 764	if (adapter->espi) {
 765		adapter->slow_intr_mask |= F_PL_INTR_ESPI;
 766		t1_espi_intr_enable(adapter->espi);
 767	}
 768
 769	/* Enable MAC/PHY interrupts for each port. */
 770	for_each_port(adapter, i) {
 771		adapter->port[i].mac->ops->interrupt_enable(adapter->port[i].mac);
 772		adapter->port[i].phy->ops->interrupt_enable(adapter->port[i].phy);
 773	}
 774
 775	/* Enable PCIX & external chip interrupts on ASIC boards. */
 776	if (t1_is_asic(adapter)) {
 777		u32 pl_intr = readl(adapter->regs + A_PL_ENABLE);
 778
 779		/* PCI-X interrupts */
 780		pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
 781				       0xffffffff);
 782
 783		adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
 784		pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
 785		writel(pl_intr, adapter->regs + A_PL_ENABLE);
 786	}
 787}
 788
 789/* Disables all interrupts. */
 790void t1_interrupts_disable(adapter_t* adapter)
 791{
 792	unsigned int i;
 793
 794	t1_sge_intr_disable(adapter->sge);
 795	t1_tp_intr_disable(adapter->tp);
 796	if (adapter->espi)
 797		t1_espi_intr_disable(adapter->espi);
 798
 799	/* Disable MAC/PHY interrupts for each port. */
 800	for_each_port(adapter, i) {
 801		adapter->port[i].mac->ops->interrupt_disable(adapter->port[i].mac);
 802		adapter->port[i].phy->ops->interrupt_disable(adapter->port[i].phy);
 803	}
 804
 805	/* Disable PCIX & external chip interrupts. */
 806	if (t1_is_asic(adapter))
 807		writel(0, adapter->regs + A_PL_ENABLE);
 808
 809	/* PCI-X interrupts */
 810	pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
 811
 812	adapter->slow_intr_mask = 0;
 813}
 814
 815/* Clears all interrupts */
 816void t1_interrupts_clear(adapter_t* adapter)
 817{
 818	unsigned int i;
 819
 820	t1_sge_intr_clear(adapter->sge);
 821	t1_tp_intr_clear(adapter->tp);
 822	if (adapter->espi)
 823		t1_espi_intr_clear(adapter->espi);
 824
 825	/* Clear MAC/PHY interrupts for each port. */
 826	for_each_port(adapter, i) {
 827		adapter->port[i].mac->ops->interrupt_clear(adapter->port[i].mac);
 828		adapter->port[i].phy->ops->interrupt_clear(adapter->port[i].phy);
 829	}
 830
 831	/* Enable interrupts for external devices. */
 832	if (t1_is_asic(adapter)) {
 833		u32 pl_intr = readl(adapter->regs + A_PL_CAUSE);
 834
 835		writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
 836		       adapter->regs + A_PL_CAUSE);
 837	}
 838
 839	/* PCI-X interrupts */
 840	pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
 841}
 842
 843/*
 844 * Slow path interrupt handler for ASICs.
 845 */
 846static int asic_slow_intr(adapter_t *adapter)
 847{
 848	u32 cause = readl(adapter->regs + A_PL_CAUSE);
 849
 850	cause &= adapter->slow_intr_mask;
 851	if (!cause)
 852		return 0;
 853	if (cause & F_PL_INTR_SGE_ERR)
 854		t1_sge_intr_error_handler(adapter->sge);
 855	if (cause & F_PL_INTR_TP)
 856		t1_tp_intr_handler(adapter->tp);
 857	if (cause & F_PL_INTR_ESPI)
 858		t1_espi_intr_handler(adapter->espi);
 859	if (cause & F_PL_INTR_PCIX)
 860		t1_pci_intr_handler(adapter);
 861	if (cause & F_PL_INTR_EXT)
 862		t1_elmer0_ext_intr(adapter);
 863
 864	/* Clear the interrupts just processed. */
 865	writel(cause, adapter->regs + A_PL_CAUSE);
 866	readl(adapter->regs + A_PL_CAUSE); /* flush writes */
 867	return 1;
 868}
 869
 870int t1_slow_intr_handler(adapter_t *adapter)
 871{
 872#ifdef CONFIG_CHELSIO_T1_1G
 873	if (!t1_is_asic(adapter))
 874		return fpga_slow_intr(adapter);
 875#endif
 876	return asic_slow_intr(adapter);
 877}
 878
 879/* Power sequencing is a work-around for Intel's XPAKs. */
 880static void power_sequence_xpak(adapter_t* adapter)
 881{
 882	u32 mod_detect;
 883	u32 gpo;
 884
 885	/* Check for XPAK */
 886	t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect);
 887	if (!(ELMER0_GP_BIT5 & mod_detect)) {
 888		/* XPAK is present */
 889		t1_tpi_read(adapter, A_ELMER0_GPO, &gpo);
 890		gpo |= ELMER0_GP_BIT18;
 891		t1_tpi_write(adapter, A_ELMER0_GPO, gpo);
 892	}
 893}
 894
 895int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
 896			       struct adapter_params *p)
 897{
 898	p->chip_version = bi->chip_term;
 899	p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
 900	if (p->chip_version == CHBT_TERM_T1 ||
 901	    p->chip_version == CHBT_TERM_T2 ||
 902	    p->chip_version == CHBT_TERM_FPGA) {
 903		u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
 904
 905		val = G_TP_PC_REV(val);
 906		if (val == 2)
 907			p->chip_revision = TERM_T1B;
 908		else if (val == 3)
 909			p->chip_revision = TERM_T2;
 910		else
 911			return -1;
 912	} else
 913		return -1;
 914	return 0;
 915}
 916
 917/*
 918 * Enable board components other than the Chelsio chip, such as external MAC
 919 * and PHY.
 920 */
 921static int board_init(adapter_t *adapter, const struct board_info *bi)
 922{
 923	switch (bi->board) {
 924	case CHBT_BOARD_8000:
 925	case CHBT_BOARD_N110:
 926	case CHBT_BOARD_N210:
 927	case CHBT_BOARD_CHT210:
 928		t1_tpi_par(adapter, 0xf);
 929		t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
 930		break;
 931	case CHBT_BOARD_CHT110:
 932		t1_tpi_par(adapter, 0xf);
 933		t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800);
 934
 935		/* TBD XXX Might not need.  This fixes a problem
 936		 *         described in the Intel SR XPAK errata.
 937		 */
 938		power_sequence_xpak(adapter);
 939		break;
 940#ifdef CONFIG_CHELSIO_T1_1G
 941	case CHBT_BOARD_CHT204E:
 942		/* add config space write here */
 943	case CHBT_BOARD_CHT204:
 944	case CHBT_BOARD_CHT204V:
 945	case CHBT_BOARD_CHN204:
 946		t1_tpi_par(adapter, 0xf);
 947		t1_tpi_write(adapter, A_ELMER0_GPO, 0x804);
 948		break;
 949	case CHBT_BOARD_CHT101:
 950	case CHBT_BOARD_7500:
 951		t1_tpi_par(adapter, 0xf);
 952		t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804);
 953		break;
 954#endif
 955	}
 956	return 0;
 957}
 958
 959/*
 960 * Initialize and configure the Terminator HW modules.  Note that external
 961 * MAC and PHYs are initialized separately.
 962 */
 963int t1_init_hw_modules(adapter_t *adapter)
 964{
 965	int err = -EIO;
 966	const struct board_info *bi = board_info(adapter);
 967
 968	if (!bi->clock_mc4) {
 969		u32 val = readl(adapter->regs + A_MC4_CFG);
 970
 971		writel(val | F_READY | F_MC4_SLOW, adapter->regs + A_MC4_CFG);
 972		writel(F_M_BUS_ENABLE | F_TCAM_RESET,
 973		       adapter->regs + A_MC5_CONFIG);
 974	}
 975
 976	if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
 977					  bi->espi_nports))
 978		goto out_err;
 979
 980	if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core))
 981		goto out_err;
 982
 983	err = t1_sge_configure(adapter->sge, &adapter->params.sge);
 984	if (err)
 985		goto out_err;
 986
 987	err = 0;
 988out_err:
 989	return err;
 990}
 991
 992/*
 993 * Determine a card's PCI mode.
 994 */
 995static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
 996{
 997	static const unsigned short speed_map[] = { 33, 66, 100, 133 };
 998	u32 pci_mode;
 999
1000	pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
1001	p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
1002	p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
1003	p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
1004}
1005
1006/*
1007 * Release the structures holding the SW per-Terminator-HW-module state.
1008 */
1009void t1_free_sw_modules(adapter_t *adapter)
1010{
1011	unsigned int i;
1012
1013	for_each_port(adapter, i) {
1014		struct cmac *mac = adapter->port[i].mac;
1015		struct cphy *phy = adapter->port[i].phy;
1016
1017		if (mac)
1018			mac->ops->destroy(mac);
1019		if (phy)
1020			phy->ops->destroy(phy);
1021	}
1022
1023	if (adapter->sge)
1024		t1_sge_destroy(adapter->sge);
1025	if (adapter->tp)
1026		t1_tp_destroy(adapter->tp);
1027	if (adapter->espi)
1028		t1_espi_destroy(adapter->espi);
1029}
1030
1031static void __devinit init_link_config(struct link_config *lc,
1032				       const struct board_info *bi)
1033{
1034	lc->supported = bi->caps;
1035	lc->requested_speed = lc->speed = SPEED_INVALID;
1036	lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
1037	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
1038	if (lc->supported & SUPPORTED_Autoneg) {
1039		lc->advertising = lc->supported;
1040		lc->autoneg = AUTONEG_ENABLE;
1041		lc->requested_fc |= PAUSE_AUTONEG;
1042	} else {
1043		lc->advertising = 0;
1044		lc->autoneg = AUTONEG_DISABLE;
1045	}
1046}
1047
1048/*
1049 * Allocate and initialize the data structures that hold the SW state of
1050 * the Terminator HW modules.
1051 */
1052int __devinit t1_init_sw_modules(adapter_t *adapter,
1053				 const struct board_info *bi)
1054{
1055	unsigned int i;
1056
1057	adapter->params.brd_info = bi;
1058	adapter->params.nports = bi->port_number;
1059	adapter->params.stats_update_period = bi->gmac->stats_update_period;
1060
1061	adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
1062	if (!adapter->sge) {
1063		pr_err("%s: SGE initialization failed\n",
1064		       adapter->name);
1065		goto error;
1066	}
1067
1068	if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
1069		pr_err("%s: ESPI initialization failed\n",
1070		       adapter->name);
1071		goto error;
1072	}
1073
1074	adapter->tp = t1_tp_create(adapter, &adapter->params.tp);
1075	if (!adapter->tp) {
1076		pr_err("%s: TP initialization failed\n",
1077		       adapter->name);
1078		goto error;
1079	}
1080
1081	board_init(adapter, bi);
1082	bi->mdio_ops->init(adapter, bi);
1083	if (bi->gphy->reset)
1084		bi->gphy->reset(adapter);
1085	if (bi->gmac->reset)
1086		bi->gmac->reset(adapter);
1087
1088	for_each_port(adapter, i) {
1089		u8 hw_addr[6];
1090		struct cmac *mac;
1091		int phy_addr = bi->mdio_phybaseaddr + i;
1092
1093		adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev,
1094							phy_addr, bi->mdio_ops);
1095		if (!adapter->port[i].phy) {
1096			pr_err("%s: PHY %d initialization failed\n",
1097			       adapter->name, i);
1098			goto error;
1099		}
1100
1101		adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
1102		if (!mac) {
1103			pr_err("%s: MAC %d initialization failed\n",
1104			       adapter->name, i);
1105			goto error;
1106		}
1107
1108		/*
1109		 * Get the port's MAC addresses either from the EEPROM if one
1110		 * exists or the one hardcoded in the MAC.
1111		 */
1112		if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY)
1113			mac->ops->macaddress_get(mac, hw_addr);
1114		else if (vpd_macaddress_get(adapter, i, hw_addr)) {
1115			pr_err("%s: could not read MAC address from VPD ROM\n",
1116			       adapter->port[i].dev->name);
1117			goto error;
1118		}
1119		memcpy(adapter->port[i].dev->dev_addr, hw_addr, ETH_ALEN);
1120		init_link_config(&adapter->port[i].link_config, bi);
1121	}
1122
1123	get_pci_mode(adapter, &adapter->params.pci);
1124	t1_interrupts_clear(adapter);
1125	return 0;
1126
1127error:
1128	t1_free_sw_modules(adapter);
1129	return -1;
1130}