18c2ecf20Sopenharmony_ci/*****************************************************************************
28c2ecf20Sopenharmony_ci *                                                                           *
38c2ecf20Sopenharmony_ci * File: espi.c                                                              *
48c2ecf20Sopenharmony_ci * $Revision: 1.14 $                                                         *
58c2ecf20Sopenharmony_ci * $Date: 2005/05/14 00:59:32 $                                              *
68c2ecf20Sopenharmony_ci * Description:                                                              *
78c2ecf20Sopenharmony_ci *  Ethernet SPI functionality.                                              *
88c2ecf20Sopenharmony_ci *  part of the Chelsio 10Gb Ethernet Driver.                                *
98c2ecf20Sopenharmony_ci *                                                                           *
108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify      *
118c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, version 2, as       *
128c2ecf20Sopenharmony_ci * published by the Free Software Foundation.                                *
138c2ecf20Sopenharmony_ci *                                                                           *
148c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License along   *
158c2ecf20Sopenharmony_ci * with this program; if not, see <http://www.gnu.org/licenses/>.            *
168c2ecf20Sopenharmony_ci *                                                                           *
178c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
188c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
198c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
208c2ecf20Sopenharmony_ci *                                                                           *
218c2ecf20Sopenharmony_ci * http://www.chelsio.com                                                    *
228c2ecf20Sopenharmony_ci *                                                                           *
238c2ecf20Sopenharmony_ci * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
248c2ecf20Sopenharmony_ci * All rights reserved.                                                      *
258c2ecf20Sopenharmony_ci *                                                                           *
268c2ecf20Sopenharmony_ci * Maintainers: maintainers@chelsio.com                                      *
278c2ecf20Sopenharmony_ci *                                                                           *
288c2ecf20Sopenharmony_ci * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
298c2ecf20Sopenharmony_ci *          Tina Yang               <tainay@chelsio.com>                     *
308c2ecf20Sopenharmony_ci *          Felix Marti             <felix@chelsio.com>                      *
318c2ecf20Sopenharmony_ci *          Scott Bardone           <sbardone@chelsio.com>                   *
328c2ecf20Sopenharmony_ci *          Kurt Ottaway            <kottaway@chelsio.com>                   *
338c2ecf20Sopenharmony_ci *          Frank DiMambro          <frank@chelsio.com>                      *
348c2ecf20Sopenharmony_ci *                                                                           *
358c2ecf20Sopenharmony_ci * History:                                                                  *
368c2ecf20Sopenharmony_ci *                                                                           *
378c2ecf20Sopenharmony_ci ****************************************************************************/
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include "common.h"
408c2ecf20Sopenharmony_ci#include "regs.h"
418c2ecf20Sopenharmony_ci#include "espi.h"
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistruct peespi {
448c2ecf20Sopenharmony_ci	adapter_t *adapter;
458c2ecf20Sopenharmony_ci	struct espi_intr_counts intr_cnt;
468c2ecf20Sopenharmony_ci	u32 misc_ctrl;
478c2ecf20Sopenharmony_ci	spinlock_t lock;
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define ESPI_INTR_MASK (F_DIP4ERR | F_RXDROP | F_TXDROP | F_RXOVERFLOW | \
518c2ecf20Sopenharmony_ci			F_RAMPARITYERR | F_DIP2PARITYERR)
528c2ecf20Sopenharmony_ci#define MON_MASK  (V_MONITORED_PORT_NUM(3) | F_MONITORED_DIRECTION \
538c2ecf20Sopenharmony_ci		   | F_MONITORED_INTERFACE)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define TRICN_CNFG 14
568c2ecf20Sopenharmony_ci#define TRICN_CMD_READ  0x11
578c2ecf20Sopenharmony_ci#define TRICN_CMD_WRITE 0x21
588c2ecf20Sopenharmony_ci#define TRICN_CMD_ATTEMPTS 10
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
618c2ecf20Sopenharmony_ci		       int ch_addr, int reg_offset, u32 wr_data)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	int busy, attempts = TRICN_CMD_ATTEMPTS;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	writel(V_WRITE_DATA(wr_data) |
668c2ecf20Sopenharmony_ci	       V_REGISTER_OFFSET(reg_offset) |
678c2ecf20Sopenharmony_ci	       V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
688c2ecf20Sopenharmony_ci	       V_BUNDLE_ADDR(bundle_addr) |
698c2ecf20Sopenharmony_ci	       V_SPI4_COMMAND(TRICN_CMD_WRITE),
708c2ecf20Sopenharmony_ci	       adapter->regs + A_ESPI_CMD_ADDR);
718c2ecf20Sopenharmony_ci	writel(0, adapter->regs + A_ESPI_GOSTAT);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	do {
748c2ecf20Sopenharmony_ci		busy = readl(adapter->regs + A_ESPI_GOSTAT) & F_ESPI_CMD_BUSY;
758c2ecf20Sopenharmony_ci	} while (busy && --attempts);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (busy)
788c2ecf20Sopenharmony_ci		pr_err("%s: TRICN write timed out\n", adapter->name);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	return busy;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic int tricn_init(adapter_t *adapter)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	int i, sme = 1;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (!(readl(adapter->regs + A_ESPI_RX_RESET)  & F_RX_CLK_STATUS)) {
888c2ecf20Sopenharmony_ci		pr_err("%s: ESPI clock not ready\n", adapter->name);
898c2ecf20Sopenharmony_ci		return -1;
908c2ecf20Sopenharmony_ci	}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	writel(F_ESPI_RX_CORE_RST, adapter->regs + A_ESPI_RX_RESET);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	if (sme) {
958c2ecf20Sopenharmony_ci		tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
968c2ecf20Sopenharmony_ci		tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
978c2ecf20Sopenharmony_ci		tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
988c2ecf20Sopenharmony_ci	}
998c2ecf20Sopenharmony_ci	for (i = 1; i <= 8; i++)
1008c2ecf20Sopenharmony_ci		tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
1018c2ecf20Sopenharmony_ci	for (i = 1; i <= 2; i++)
1028c2ecf20Sopenharmony_ci		tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
1038c2ecf20Sopenharmony_ci	for (i = 1; i <= 3; i++)
1048c2ecf20Sopenharmony_ci		tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
1058c2ecf20Sopenharmony_ci	tricn_write(adapter, 0, 2, 4, TRICN_CNFG, 0xf1);
1068c2ecf20Sopenharmony_ci	tricn_write(adapter, 0, 2, 5, TRICN_CNFG, 0xe1);
1078c2ecf20Sopenharmony_ci	tricn_write(adapter, 0, 2, 6, TRICN_CNFG, 0xf1);
1088c2ecf20Sopenharmony_ci	tricn_write(adapter, 0, 2, 7, TRICN_CNFG, 0x80);
1098c2ecf20Sopenharmony_ci	tricn_write(adapter, 0, 2, 8, TRICN_CNFG, 0xf1);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	writel(F_ESPI_RX_CORE_RST | F_ESPI_RX_LNK_RST,
1128c2ecf20Sopenharmony_ci	       adapter->regs + A_ESPI_RX_RESET);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	return 0;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_civoid t1_espi_intr_enable(struct peespi *espi)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	u32 enable, pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	/*
1228c2ecf20Sopenharmony_ci	 * Cannot enable ESPI interrupts on T1B because HW asserts the
1238c2ecf20Sopenharmony_ci	 * interrupt incorrectly, namely the driver gets ESPI interrupts
1248c2ecf20Sopenharmony_ci	 * but no data is actually dropped (can verify this reading the ESPI
1258c2ecf20Sopenharmony_ci	 * drop registers).  Also, once the ESPI interrupt is asserted it
1268c2ecf20Sopenharmony_ci	 * cannot be cleared (HW bug).
1278c2ecf20Sopenharmony_ci	 */
1288c2ecf20Sopenharmony_ci	enable = t1_is_T1B(espi->adapter) ? 0 : ESPI_INTR_MASK;
1298c2ecf20Sopenharmony_ci	writel(enable, espi->adapter->regs + A_ESPI_INTR_ENABLE);
1308c2ecf20Sopenharmony_ci	writel(pl_intr | F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_civoid t1_espi_intr_clear(struct peespi *espi)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
1368c2ecf20Sopenharmony_ci	writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS);
1378c2ecf20Sopenharmony_ci	writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_civoid t1_espi_intr_disable(struct peespi *espi)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	u32 pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	writel(0, espi->adapter->regs + A_ESPI_INTR_ENABLE);
1458c2ecf20Sopenharmony_ci	writel(pl_intr & ~F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ciint t1_espi_intr_handler(struct peespi *espi)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	if (status & F_DIP4ERR)
1538c2ecf20Sopenharmony_ci		espi->intr_cnt.DIP4_err++;
1548c2ecf20Sopenharmony_ci	if (status & F_RXDROP)
1558c2ecf20Sopenharmony_ci		espi->intr_cnt.rx_drops++;
1568c2ecf20Sopenharmony_ci	if (status & F_TXDROP)
1578c2ecf20Sopenharmony_ci		espi->intr_cnt.tx_drops++;
1588c2ecf20Sopenharmony_ci	if (status & F_RXOVERFLOW)
1598c2ecf20Sopenharmony_ci		espi->intr_cnt.rx_ovflw++;
1608c2ecf20Sopenharmony_ci	if (status & F_RAMPARITYERR)
1618c2ecf20Sopenharmony_ci		espi->intr_cnt.parity_err++;
1628c2ecf20Sopenharmony_ci	if (status & F_DIP2PARITYERR) {
1638c2ecf20Sopenharmony_ci		espi->intr_cnt.DIP2_parity_err++;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		/*
1668c2ecf20Sopenharmony_ci		 * Must read the error count to clear the interrupt
1678c2ecf20Sopenharmony_ci		 * that it causes.
1688c2ecf20Sopenharmony_ci		 */
1698c2ecf20Sopenharmony_ci		readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	/*
1738c2ecf20Sopenharmony_ci	 * For T1B we need to write 1 to clear ESPI interrupts.  For T2+ we
1748c2ecf20Sopenharmony_ci	 * write the status as is.
1758c2ecf20Sopenharmony_ci	 */
1768c2ecf20Sopenharmony_ci	if (status && t1_is_T1B(espi->adapter))
1778c2ecf20Sopenharmony_ci		status = 1;
1788c2ecf20Sopenharmony_ci	writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
1798c2ecf20Sopenharmony_ci	return 0;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ciconst struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	return &espi->intr_cnt;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic void espi_setup_for_pm3393(adapter_t *adapter)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
1928c2ecf20Sopenharmony_ci	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN1);
1938c2ecf20Sopenharmony_ci	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
1948c2ecf20Sopenharmony_ci	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN3);
1958c2ecf20Sopenharmony_ci	writel(0x100, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
1968c2ecf20Sopenharmony_ci	writel(wmark, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
1978c2ecf20Sopenharmony_ci	writel(3, adapter->regs + A_ESPI_CALENDAR_LENGTH);
1988c2ecf20Sopenharmony_ci	writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
1998c2ecf20Sopenharmony_ci	writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG);
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic void espi_setup_for_vsc7321(adapter_t *adapter)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
2058c2ecf20Sopenharmony_ci	writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1);
2068c2ecf20Sopenharmony_ci	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
2078c2ecf20Sopenharmony_ci	writel(0xa00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
2088c2ecf20Sopenharmony_ci	writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
2098c2ecf20Sopenharmony_ci	writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
2108c2ecf20Sopenharmony_ci	writel(V_RX_NPORTS(4) | V_TX_NPORTS(4), adapter->regs + A_PORT_CONFIG);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci/*
2168c2ecf20Sopenharmony_ci * Note that T1B requires at least 2 ports for IXF1010 due to a HW bug.
2178c2ecf20Sopenharmony_ci */
2188c2ecf20Sopenharmony_cistatic void espi_setup_for_ixf1010(adapter_t *adapter, int nports)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
2218c2ecf20Sopenharmony_ci	if (nports == 4) {
2228c2ecf20Sopenharmony_ci		if (is_T2(adapter)) {
2238c2ecf20Sopenharmony_ci			writel(0xf00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
2248c2ecf20Sopenharmony_ci			writel(0x3c0, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
2258c2ecf20Sopenharmony_ci		} else {
2268c2ecf20Sopenharmony_ci			writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
2278c2ecf20Sopenharmony_ci			writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
2288c2ecf20Sopenharmony_ci		}
2298c2ecf20Sopenharmony_ci	} else {
2308c2ecf20Sopenharmony_ci		writel(0x1fff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
2318c2ecf20Sopenharmony_ci		writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci	writel(V_RX_NPORTS(nports) | V_TX_NPORTS(nports), adapter->regs + A_PORT_CONFIG);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciint t1_espi_init(struct peespi *espi, int mac_type, int nports)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	u32 status_enable_extra = 0;
2408c2ecf20Sopenharmony_ci	adapter_t *adapter = espi->adapter;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* Disable ESPI training.  MACs that can handle it enable it below. */
2438c2ecf20Sopenharmony_ci	writel(0, adapter->regs + A_ESPI_TRAIN);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if (is_T2(adapter)) {
2468c2ecf20Sopenharmony_ci		writel(V_OUT_OF_SYNC_COUNT(4) |
2478c2ecf20Sopenharmony_ci		       V_DIP2_PARITY_ERR_THRES(3) |
2488c2ecf20Sopenharmony_ci		       V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL);
2498c2ecf20Sopenharmony_ci		writel(nports == 4 ? 0x200040 : 0x1000080,
2508c2ecf20Sopenharmony_ci		       adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
2518c2ecf20Sopenharmony_ci	} else
2528c2ecf20Sopenharmony_ci		writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (mac_type == CHBT_MAC_PM3393)
2558c2ecf20Sopenharmony_ci		espi_setup_for_pm3393(adapter);
2568c2ecf20Sopenharmony_ci	else if (mac_type == CHBT_MAC_VSC7321)
2578c2ecf20Sopenharmony_ci		espi_setup_for_vsc7321(adapter);
2588c2ecf20Sopenharmony_ci	else if (mac_type == CHBT_MAC_IXF1010) {
2598c2ecf20Sopenharmony_ci		status_enable_extra = F_INTEL1010MODE;
2608c2ecf20Sopenharmony_ci		espi_setup_for_ixf1010(adapter, nports);
2618c2ecf20Sopenharmony_ci	} else
2628c2ecf20Sopenharmony_ci		return -1;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	writel(status_enable_extra | F_RXSTATUSENABLE,
2658c2ecf20Sopenharmony_ci	       adapter->regs + A_ESPI_FIFO_STATUS_ENABLE);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (is_T2(adapter)) {
2688c2ecf20Sopenharmony_ci		tricn_init(adapter);
2698c2ecf20Sopenharmony_ci		/*
2708c2ecf20Sopenharmony_ci		 * Always position the control at the 1st port egress IN
2718c2ecf20Sopenharmony_ci		 * (sop,eop) counter to reduce PIOs for T/N210 workaround.
2728c2ecf20Sopenharmony_ci		 */
2738c2ecf20Sopenharmony_ci		espi->misc_ctrl = readl(adapter->regs + A_ESPI_MISC_CONTROL);
2748c2ecf20Sopenharmony_ci		espi->misc_ctrl &= ~MON_MASK;
2758c2ecf20Sopenharmony_ci		espi->misc_ctrl |= F_MONITORED_DIRECTION;
2768c2ecf20Sopenharmony_ci		if (adapter->params.nports == 1)
2778c2ecf20Sopenharmony_ci			espi->misc_ctrl |= F_MONITORED_INTERFACE;
2788c2ecf20Sopenharmony_ci		writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
2798c2ecf20Sopenharmony_ci		spin_lock_init(&espi->lock);
2808c2ecf20Sopenharmony_ci	}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	return 0;
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_civoid t1_espi_destroy(struct peespi *espi)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	kfree(espi);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistruct peespi *t1_espi_create(adapter_t *adapter)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	struct peespi *espi = kzalloc(sizeof(*espi), GFP_KERNEL);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (espi)
2958c2ecf20Sopenharmony_ci		espi->adapter = adapter;
2968c2ecf20Sopenharmony_ci	return espi;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci#if 0
3008c2ecf20Sopenharmony_civoid t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct peespi *espi = adapter->espi;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (!is_T2(adapter))
3058c2ecf20Sopenharmony_ci		return;
3068c2ecf20Sopenharmony_ci	spin_lock(&espi->lock);
3078c2ecf20Sopenharmony_ci	espi->misc_ctrl = (val & ~MON_MASK) |
3088c2ecf20Sopenharmony_ci			  (espi->misc_ctrl & MON_MASK);
3098c2ecf20Sopenharmony_ci	writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
3108c2ecf20Sopenharmony_ci	spin_unlock(&espi->lock);
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci#endif  /*  0  */
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ciu32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	struct peespi *espi = adapter->espi;
3178c2ecf20Sopenharmony_ci	u32 sel;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	if (!is_T2(adapter))
3208c2ecf20Sopenharmony_ci		return 0;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
3238c2ecf20Sopenharmony_ci	if (!wait) {
3248c2ecf20Sopenharmony_ci		if (!spin_trylock(&espi->lock))
3258c2ecf20Sopenharmony_ci			return 0;
3268c2ecf20Sopenharmony_ci	} else
3278c2ecf20Sopenharmony_ci		spin_lock(&espi->lock);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	if ((sel != (espi->misc_ctrl & MON_MASK))) {
3308c2ecf20Sopenharmony_ci		writel(((espi->misc_ctrl & ~MON_MASK) | sel),
3318c2ecf20Sopenharmony_ci		       adapter->regs + A_ESPI_MISC_CONTROL);
3328c2ecf20Sopenharmony_ci		sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
3338c2ecf20Sopenharmony_ci		writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
3348c2ecf20Sopenharmony_ci	} else
3358c2ecf20Sopenharmony_ci		sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
3368c2ecf20Sopenharmony_ci	spin_unlock(&espi->lock);
3378c2ecf20Sopenharmony_ci	return sel;
3388c2ecf20Sopenharmony_ci}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci/*
3418c2ecf20Sopenharmony_ci * This function is for T204 only.
3428c2ecf20Sopenharmony_ci * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in
3438c2ecf20Sopenharmony_ci * one shot, since there is no per port counter on the out side.
3448c2ecf20Sopenharmony_ci */
3458c2ecf20Sopenharmony_ciint t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	struct peespi *espi = adapter->espi;
3488c2ecf20Sopenharmony_ci	u8 i, nport = (u8)adapter->params.nports;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if (!wait) {
3518c2ecf20Sopenharmony_ci		if (!spin_trylock(&espi->lock))
3528c2ecf20Sopenharmony_ci			return -1;
3538c2ecf20Sopenharmony_ci	} else
3548c2ecf20Sopenharmony_ci		spin_lock(&espi->lock);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	if ((espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION) {
3578c2ecf20Sopenharmony_ci		espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) |
3588c2ecf20Sopenharmony_ci					F_MONITORED_DIRECTION;
3598c2ecf20Sopenharmony_ci		writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci	for (i = 0 ; i < nport; i++, valp++) {
3628c2ecf20Sopenharmony_ci		if (i) {
3638c2ecf20Sopenharmony_ci			writel(espi->misc_ctrl | V_MONITORED_PORT_NUM(i),
3648c2ecf20Sopenharmony_ci			       adapter->regs + A_ESPI_MISC_CONTROL);
3658c2ecf20Sopenharmony_ci		}
3668c2ecf20Sopenharmony_ci		*valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
3708c2ecf20Sopenharmony_ci	spin_unlock(&espi->lock);
3718c2ecf20Sopenharmony_ci	return 0;
3728c2ecf20Sopenharmony_ci}
373