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