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}
1131