/*****************************************************************************
* *
* File: espi.c *
- * $Revision: 1.9 $ *
- * $Date: 2005/03/23 07:41:27 $ *
+ * $Revision: 1.14 $ *
+ * $Date: 2005/05/14 00:59:32 $ *
* Description: *
* Ethernet SPI functionality. *
* part of the Chelsio 10Gb Ethernet Driver. *
{
int busy, attempts = TRICN_CMD_ATTEMPTS;
- t1_write_reg_4(adapter, A_ESPI_CMD_ADDR, V_WRITE_DATA(wr_data) |
- V_REGISTER_OFFSET(reg_offset) |
- V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
- V_BUNDLE_ADDR(bundle_addr) |
- V_SPI4_COMMAND(TRICN_CMD_WRITE));
- t1_write_reg_4(adapter, A_ESPI_GOSTAT, 0);
+ writel(V_WRITE_DATA(wr_data) |
+ V_REGISTER_OFFSET(reg_offset) |
+ V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
+ V_BUNDLE_ADDR(bundle_addr) |
+ V_SPI4_COMMAND(TRICN_CMD_WRITE),
+ adapter->regs + A_ESPI_CMD_ADDR);
+ writel(0, adapter->regs + A_ESPI_GOSTAT);
do {
- busy = t1_read_reg_4(adapter, A_ESPI_GOSTAT) & F_ESPI_CMD_BUSY;
+ busy = readl(adapter->regs + A_ESPI_GOSTAT) & F_ESPI_CMD_BUSY;
} while (busy && --attempts);
if (busy)
return busy;
}
-/* 1. Deassert rx_reset_core. */
-/* 2. Program TRICN_CNFG registers. */
-/* 3. Deassert rx_reset_link */
static int tricn_init(adapter_t *adapter)
{
- int i = 0;
- int sme = 1;
- int stat = 0;
- int timeout = 0;
- int is_ready = 0;
- int dynamic_deskew = 0;
+ int i, sme = 1;
- if (dynamic_deskew)
- sme = 0;
-
-
- /* 1 */
- timeout=1000;
- do {
- stat = t1_read_reg_4(adapter, A_ESPI_RX_RESET);
- is_ready = (stat & 0x4);
- timeout--;
- udelay(5);
- } while (!is_ready || (timeout==0));
- t1_write_reg_4(adapter, A_ESPI_RX_RESET, 0x2);
- if (timeout==0)
- {
- CH_ERR("ESPI : ERROR : Timeout tricn_init() \n");
- t1_fatal_err(adapter);
+ if (!(readl(adapter->regs + A_ESPI_RX_RESET) & F_RX_CLK_STATUS)) {
+ CH_ERR("%s: ESPI clock not ready\n", adapter->name);
+ return -1;
}
- /* 2 */
+ writel(F_ESPI_RX_CORE_RST, adapter->regs + A_ESPI_RX_RESET);
+
if (sme) {
tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
}
- for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
- for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
- for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
- for (i=4; i<= 4; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
- for (i=5; i<= 5; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
- for (i=6; i<= 6; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
- for (i=7; i<= 7; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0x80);
- for (i=8; i<= 8; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
-
- /* 3 */
- t1_write_reg_4(adapter, A_ESPI_RX_RESET, 0x3);
+ for (i = 1; i <= 8; i++)
+ tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
+ for (i = 1; i <= 2; i++)
+ tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
+ for (i = 1; i <= 3; i++)
+ tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
+ tricn_write(adapter, 0, 2, 4, TRICN_CNFG, 0xf1);
+ tricn_write(adapter, 0, 2, 5, TRICN_CNFG, 0xe1);
+ tricn_write(adapter, 0, 2, 6, TRICN_CNFG, 0xf1);
+ tricn_write(adapter, 0, 2, 7, TRICN_CNFG, 0x80);
+ tricn_write(adapter, 0, 2, 8, TRICN_CNFG, 0xf1);
+
+ writel(F_ESPI_RX_CORE_RST | F_ESPI_RX_LNK_RST,
+ adapter->regs + A_ESPI_RX_RESET);
return 0;
}
void t1_espi_intr_enable(struct peespi *espi)
{
- u32 enable, pl_intr = t1_read_reg_4(espi->adapter, A_PL_ENABLE);
+ u32 enable, pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
/*
* Cannot enable ESPI interrupts on T1B because HW asserts the
* cannot be cleared (HW bug).
*/
enable = t1_is_T1B(espi->adapter) ? 0 : ESPI_INTR_MASK;
- t1_write_reg_4(espi->adapter, A_ESPI_INTR_ENABLE, enable);
- t1_write_reg_4(espi->adapter, A_PL_ENABLE, pl_intr | F_PL_INTR_ESPI);
+ writel(enable, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ writel(pl_intr | F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
}
void t1_espi_intr_clear(struct peespi *espi)
{
- t1_write_reg_4(espi->adapter, A_ESPI_INTR_STATUS, 0xffffffff);
- t1_write_reg_4(espi->adapter, A_PL_CAUSE, F_PL_INTR_ESPI);
+ readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
+ writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS);
+ writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE);
}
void t1_espi_intr_disable(struct peespi *espi)
{
- u32 pl_intr = t1_read_reg_4(espi->adapter, A_PL_ENABLE);
+ u32 pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
- t1_write_reg_4(espi->adapter, A_ESPI_INTR_ENABLE, 0);
- t1_write_reg_4(espi->adapter, A_PL_ENABLE, pl_intr & ~F_PL_INTR_ESPI);
+ writel(0, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ writel(pl_intr & ~F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
}
int t1_espi_intr_handler(struct peespi *espi)
{
- u32 cnt;
- u32 status = t1_read_reg_4(espi->adapter, A_ESPI_INTR_STATUS);
+ u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
if (status & F_DIP4ERR)
espi->intr_cnt.DIP4_err++;
* Must read the error count to clear the interrupt
* that it causes.
*/
- cnt = t1_read_reg_4(espi->adapter, A_ESPI_DIP2_ERR_COUNT);
+ readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
}
/*
*/
if (status && t1_is_T1B(espi->adapter))
status = 1;
- t1_write_reg_4(espi->adapter, A_ESPI_INTR_STATUS, status);
+ writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
return 0;
}
+const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
+{
+ return &espi->intr_cnt;
+}
+
static void espi_setup_for_pm3393(adapter_t *adapter)
{
u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN0, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN1, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN2, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN3, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK, 0x100);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK, wmark);
- t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 3);
- t1_write_reg_4(adapter, A_ESPI_TRAIN, 0x08000008);
- t1_write_reg_4(adapter, A_PORT_CONFIG,
- V_RX_NPORTS(1) | V_TX_NPORTS(1));
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN1);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN3);
+ writel(0x100, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ writel(wmark, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(3, adapter->regs + A_ESPI_CALENDAR_LENGTH);
+ writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
+ writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG);
}
static void espi_setup_for_vsc7321(adapter_t *adapter)
{
- u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
-
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN0, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN1, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN2, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_SCH_TOKEN3, 0x1f4);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK, 0x100);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK, wmark);
- t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 3);
- t1_write_reg_4(adapter, A_ESPI_TRAIN, 0x08000008);
- t1_write_reg_4(adapter, A_PORT_CONFIG,
- V_RX_NPORTS(1) | V_TX_NPORTS(1));
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
+ writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
+ writel(0xa00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
+ writel(V_RX_NPORTS(4) | V_TX_NPORTS(4), adapter->regs + A_PORT_CONFIG);
+
+ writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
}
/*
*/
static void espi_setup_for_ixf1010(adapter_t *adapter, int nports)
{
- t1_write_reg_4(adapter, A_ESPI_CALENDAR_LENGTH, 1);
+ writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
if (nports == 4) {
if (is_T2(adapter)) {
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK,
- 0xf00);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK,
- 0x3c0);
+ writel(0xf00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x3c0, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
} else {
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK,
- 0x7ff);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK,
- 0x1ff);
+ writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
}
} else {
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK,
- 0x1fff);
- t1_write_reg_4(adapter, A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK,
- 0x7ff);
+ writel(0x1fff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
}
- t1_write_reg_4(adapter, A_PORT_CONFIG,
- V_RX_NPORTS(nports) | V_TX_NPORTS(nports));
+ writel(V_RX_NPORTS(nports) | V_TX_NPORTS(nports), adapter->regs + A_PORT_CONFIG);
+
}
-/* T2 Init part -- */
-/* 1. Set T_ESPI_MISCCTRL_ADDR */
-/* 2. Init ESPI registers. */
-/* 3. Init TriCN Hard Macro */
int t1_espi_init(struct peespi *espi, int mac_type, int nports)
{
u32 status_enable_extra = 0;
adapter_t *adapter = espi->adapter;
- u32 cnt;
- u32 status, burstval = 0x800100;
/* Disable ESPI training. MACs that can handle it enable it below. */
- t1_write_reg_4(adapter, A_ESPI_TRAIN, 0);
+ writel(0, adapter->regs + A_ESPI_TRAIN);
if (is_T2(adapter)) {
- t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
- V_OUT_OF_SYNC_COUNT(4) |
- V_DIP2_PARITY_ERR_THRES(3) | V_DIP4_THRES(1));
- if (nports == 4) {
- /* T204: maxburst1 = 0x40, maxburst2 = 0x20 */
- burstval = 0x200040;
- }
- }
- t1_write_reg_4(adapter, A_ESPI_MAXBURST1_MAXBURST2, burstval);
+ writel(V_OUT_OF_SYNC_COUNT(4) |
+ V_DIP2_PARITY_ERR_THRES(3) |
+ V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL);
+ writel(nports == 4 ? 0x200040 : 0x1000080,
+ adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
+ } else
+ writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
if (mac_type == CHBT_MAC_PM3393)
espi_setup_for_pm3393(adapter);
} else
return -1;
- /*
- * Make sure any pending interrupts from the SPI are
- * Cleared before enabling the interrupt.
- */
- t1_write_reg_4(espi->adapter, A_ESPI_INTR_ENABLE, ESPI_INTR_MASK);
- status = t1_read_reg_4(espi->adapter, A_ESPI_INTR_STATUS);
- if (status & F_DIP2PARITYERR) {
- cnt = t1_read_reg_4(espi->adapter, A_ESPI_DIP2_ERR_COUNT);
- }
-
- /*
- * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we
- * write the status as is.
- */
- if (status && t1_is_T1B(espi->adapter))
- status = 1;
- t1_write_reg_4(espi->adapter, A_ESPI_INTR_STATUS, status);
-
- t1_write_reg_4(adapter, A_ESPI_FIFO_STATUS_ENABLE,
- status_enable_extra | F_RXSTATUSENABLE);
+ writel(status_enable_extra | F_RXSTATUSENABLE,
+ adapter->regs + A_ESPI_FIFO_STATUS_ENABLE);
if (is_T2(adapter)) {
tricn_init(adapter);
* Always position the control at the 1st port egress IN
* (sop,eop) counter to reduce PIOs for T/N210 workaround.
*/
- espi->misc_ctrl = (t1_read_reg_4(adapter, A_ESPI_MISC_CONTROL)
- & ~MON_MASK) | (F_MONITORED_DIRECTION
- | F_MONITORED_INTERFACE);
- t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL, espi->misc_ctrl);
+ espi->misc_ctrl = readl(adapter->regs + A_ESPI_MISC_CONTROL);
+ espi->misc_ctrl &= ~MON_MASK;
+ espi->misc_ctrl |= F_MONITORED_DIRECTION;
+ if (adapter->params.nports == 1)
+ espi->misc_ctrl |= F_MONITORED_INTERFACE;
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
spin_lock_init(&espi->lock);
}
struct peespi *t1_espi_create(adapter_t *adapter)
{
- struct peespi *espi = kmalloc(sizeof(*espi), GFP_KERNEL);
-
- memset(espi, 0, sizeof(*espi));
+ struct peespi *espi = kzalloc(sizeof(*espi), GFP_KERNEL);
if (espi)
espi->adapter = adapter;
return espi;
}
+#if 0
void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
{
struct peespi *espi = adapter->espi;
spin_lock(&espi->lock);
espi->misc_ctrl = (val & ~MON_MASK) |
(espi->misc_ctrl & MON_MASK);
- t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL, espi->misc_ctrl);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
spin_unlock(&espi->lock);
}
+#endif /* 0 */
u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
{
if (!is_T2(adapter))
return 0;
+
sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
if (!wait) {
if (!spin_trylock(&espi->lock))
return 0;
- }
- else
+ } else
spin_lock(&espi->lock);
+
if ((sel != (espi->misc_ctrl & MON_MASK))) {
- t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
- ((espi->misc_ctrl & ~MON_MASK) | sel));
- sel = t1_read_reg_4(adapter, A_ESPI_SCH_TOKEN3);
- t1_write_reg_4(adapter, A_ESPI_MISC_CONTROL,
- espi->misc_ctrl);
- }
- else
- sel = t1_read_reg_4(adapter, A_ESPI_SCH_TOKEN3);
+ writel(((espi->misc_ctrl & ~MON_MASK) | sel),
+ adapter->regs + A_ESPI_MISC_CONTROL);
+ sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ } else
+ sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
spin_unlock(&espi->lock);
return sel;
}
+
+/*
+ * This function is for T204 only.
+ * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in
+ * one shot, since there is no per port counter on the out side.
+ */
+int t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait)
+{
+ struct peespi *espi = adapter->espi;
+ u8 i, nport = (u8)adapter->params.nports;
+
+ if (!wait) {
+ if (!spin_trylock(&espi->lock))
+ return -1;
+ } else
+ spin_lock(&espi->lock);
+
+ if ((espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION) {
+ espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) |
+ F_MONITORED_DIRECTION;
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ }
+ for (i = 0 ; i < nport; i++, valp++) {
+ if (i) {
+ writel(espi->misc_ctrl | V_MONITORED_PORT_NUM(i),
+ adapter->regs + A_ESPI_MISC_CONTROL);
+ }
+ *valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ }
+
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ spin_unlock(&espi->lock);
+ return 0;
+}