#include <linux/seq_file.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
+#include <linux/mii.h>
#include "net_driver.h"
#include "bitfield.h"
#include "efx.h"
#include "mac.h"
-#include "gmii.h"
#include "spi.h"
#include "falcon.h"
#include "falcon_hwdefs.h"
#define RX_DC_ENTRIES_ORDER 2
#define RX_DC_BASE 0x100000
+static const unsigned int
+/* "Large" EEPROM device: Atmel AT25640 or similar
+ * 8 KB, 16-bit address, 32 B write block */
+large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN)
+ | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)),
+/* Default flash device: Atmel AT25F1024
+ * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
+default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN)
+ | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
+ | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
+ | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN));
+
/* RX FIFO XOFF watermark
*
* When the amount of the RX FIFO increases used increases past this
/* Max number of internal errors. After this resets will not be performed */
#define FALCON_MAX_INT_ERRORS 4
-/* Maximum period that we wait for flush events. If the flush event
- * doesn't arrive in this period of time then we check if the queue
- * was disabled anyway. */
-#define FALCON_FLUSH_TIMEOUT 10 /* 10ms */
+/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times
+ */
+#define FALCON_FLUSH_INTERVAL 10
+#define FALCON_FLUSH_POLL_COUNT 100
/**************************************************************************
*
efx_oword_t tx_desc_ptr;
struct efx_nic *efx = tx_queue->efx;
+ tx_queue->flushed = false;
+
/* Pin TX descriptor ring */
falcon_init_special_buffer(efx, &tx_queue->txd);
}
}
-static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
+static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- struct efx_channel *channel = &efx->channel[0];
efx_oword_t tx_flush_descq;
- unsigned int read_ptr, i;
/* Post a flush command */
EFX_POPULATE_OWORD_2(tx_flush_descq,
TX_FLUSH_DESCQ_CMD, 1,
TX_FLUSH_DESCQ, tx_queue->queue);
falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER);
- msleep(FALCON_FLUSH_TIMEOUT);
-
- if (EFX_WORKAROUND_7803(efx))
- return 0;
-
- /* Look for a flush completed event */
- read_ptr = channel->eventq_read_ptr;
- for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
- efx_qword_t *event = falcon_event(channel, read_ptr);
- int ev_code, ev_sub_code, ev_queue;
- if (!falcon_event_present(event))
- break;
-
- ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
- ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
- ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID);
- if ((ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) &&
- (ev_queue == tx_queue->queue)) {
- EFX_LOG(efx, "tx queue %d flush command succesful\n",
- tx_queue->queue);
- return 0;
- }
-
- read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
- }
-
- if (EFX_WORKAROUND_11557(efx)) {
- efx_oword_t reg;
- bool enabled;
-
- falcon_read_table(efx, ®, efx->type->txd_ptr_tbl_base,
- tx_queue->queue);
- enabled = EFX_OWORD_FIELD(reg, TX_DESCQ_EN);
- if (!enabled) {
- EFX_LOG(efx, "tx queue %d disabled without a "
- "flush event seen\n", tx_queue->queue);
- return 0;
- }
- }
-
- EFX_ERR(efx, "tx queue %d flush command timed out\n", tx_queue->queue);
- return -ETIMEDOUT;
}
void falcon_fini_tx(struct efx_tx_queue *tx_queue)
struct efx_nic *efx = tx_queue->efx;
efx_oword_t tx_desc_ptr;
- /* Stop the hardware using the queue */
- if (falcon_flush_tx_queue(tx_queue))
- EFX_ERR(efx, "failed to flush tx queue %d\n", tx_queue->queue);
+ /* The queue should have been flushed */
+ WARN_ON(!tx_queue->flushed);
/* Remove TX descriptor ring from card */
EFX_ZERO_OWORD(tx_desc_ptr);
rx_queue->queue, rx_queue->rxd.index,
rx_queue->rxd.index + rx_queue->rxd.entries - 1);
+ rx_queue->flushed = false;
+
/* Pin RX descriptor ring */
falcon_init_special_buffer(efx, &rx_queue->rxd);
rx_queue->queue);
}
-static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
+static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- struct efx_channel *channel = &efx->channel[0];
- unsigned int read_ptr, i;
efx_oword_t rx_flush_descq;
/* Post a flush command */
RX_FLUSH_DESCQ_CMD, 1,
RX_FLUSH_DESCQ, rx_queue->queue);
falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER);
- msleep(FALCON_FLUSH_TIMEOUT);
-
- if (EFX_WORKAROUND_7803(efx))
- return 0;
-
- /* Look for a flush completed event */
- read_ptr = channel->eventq_read_ptr;
- for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
- efx_qword_t *event = falcon_event(channel, read_ptr);
- int ev_code, ev_sub_code, ev_queue;
- bool ev_failed;
- if (!falcon_event_present(event))
- break;
-
- ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
- ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
- ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID);
- ev_failed = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_FLUSH_FAIL);
-
- if ((ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) &&
- (ev_queue == rx_queue->queue)) {
- if (ev_failed) {
- EFX_INFO(efx, "rx queue %d flush command "
- "failed\n", rx_queue->queue);
- return -EAGAIN;
- } else {
- EFX_LOG(efx, "rx queue %d flush command "
- "succesful\n", rx_queue->queue);
- return 0;
- }
- }
-
- read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
- }
-
- if (EFX_WORKAROUND_11557(efx)) {
- efx_oword_t reg;
- bool enabled;
-
- falcon_read_table(efx, ®, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
- enabled = EFX_OWORD_FIELD(reg, RX_DESCQ_EN);
- if (!enabled) {
- EFX_LOG(efx, "rx queue %d disabled without a "
- "flush event seen\n", rx_queue->queue);
- return 0;
- }
- }
-
- EFX_ERR(efx, "rx queue %d flush command timed out\n", rx_queue->queue);
- return -ETIMEDOUT;
}
void falcon_fini_rx(struct efx_rx_queue *rx_queue)
{
efx_oword_t rx_desc_ptr;
struct efx_nic *efx = rx_queue->efx;
- int i, rc;
- /* Try and flush the rx queue. This may need to be repeated */
- for (i = 0; i < 5; i++) {
- rc = falcon_flush_rx_queue(rx_queue);
- if (rc == -EAGAIN)
- continue;
- break;
- }
- if (rc) {
- EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue);
- efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
- }
+ /* The queue should already have been flushed */
+ WARN_ON(!rx_queue->flushed);
/* Remove RX descriptor ring from card */
EFX_ZERO_OWORD(rx_desc_ptr);
rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
- /* Count errors that are not in MAC stats. */
+ /* Count errors that are not in MAC stats. Ignore expected
+ * checksum errors during self-test. */
if (rx_ev_frm_trunc)
++rx_queue->channel->n_rx_frm_trunc;
else if (rx_ev_tobe_disc)
++rx_queue->channel->n_rx_tobe_disc;
- else if (rx_ev_ip_hdr_chksum_err)
- ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
- else if (rx_ev_tcp_udp_chksum_err)
- ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+ else if (!efx->loopback_selftest) {
+ if (rx_ev_ip_hdr_chksum_err)
+ ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
+ else if (rx_ev_tcp_udp_chksum_err)
+ ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+ }
if (rx_ev_ip_frag_err)
++rx_queue->channel->n_rx_ip_frag_err;
rx_ev_pause_frm ? " [PAUSE]" : "");
}
#endif
-
- if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
- efx->phy_type == PHY_TYPE_10XPRESS))
- tenxpress_crc_err(efx);
}
/* Handle receive events that are not in-order. */
efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
- bool is_phy_event = false, handled = false;
+ bool handled = false;
- /* Check for interrupt on either port. Some boards have a
- * single PHY wired to the interrupt line for port 1. */
if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
- EFX_QWORD_FIELD(*event, XG_PHY_INTR))
- is_phy_event = true;
+ EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
+ EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
+ efx->phy_op->clear_interrupt(efx);
+ queue_work(efx->workqueue, &efx->phy_work);
+ handled = true;
+ }
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
- EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0))
- is_phy_event = true;
-
- if (is_phy_event) {
- efx->phy_op->clear_interrupt(efx);
- queue_work(efx->workqueue, &efx->reconfigure_work);
+ EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
+ queue_work(efx->workqueue, &efx->mac_work);
handled = true;
}
falcon_generate_event(channel, &test_event);
}
+void falcon_sim_phy_event(struct efx_nic *efx)
+{
+ efx_qword_t phy_event;
+
+ EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE);
+ if (EFX_IS10G(efx))
+ EFX_SET_OWORD_FIELD(phy_event, XG_PHY_INTR, 1);
+ else
+ EFX_SET_OWORD_FIELD(phy_event, G_PHY0_INTR, 1);
+
+ falcon_generate_event(&efx->channel[0], &phy_event);
+}
+
+/**************************************************************************
+ *
+ * Flush handling
+ *
+ **************************************************************************/
+
+
+static void falcon_poll_flush_events(struct efx_nic *efx)
+{
+ struct efx_channel *channel = &efx->channel[0];
+ struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue *rx_queue;
+ unsigned int read_ptr, i;
+
+ read_ptr = channel->eventq_read_ptr;
+ for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
+ efx_qword_t *event = falcon_event(channel, read_ptr);
+ int ev_code, ev_sub_code, ev_queue;
+ bool ev_failed;
+ if (!falcon_event_present(event))
+ break;
+
+ ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
+ if (ev_code != DRIVER_EV_DECODE)
+ continue;
+
+ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
+ switch (ev_sub_code) {
+ case TX_DESCQ_FLS_DONE_EV_DECODE:
+ ev_queue = EFX_QWORD_FIELD(*event,
+ DRIVER_EV_TX_DESCQ_ID);
+ if (ev_queue < EFX_TX_QUEUE_COUNT) {
+ tx_queue = efx->tx_queue + ev_queue;
+ tx_queue->flushed = true;
+ }
+ break;
+ case RX_DESCQ_FLS_DONE_EV_DECODE:
+ ev_queue = EFX_QWORD_FIELD(*event,
+ DRIVER_EV_RX_DESCQ_ID);
+ ev_failed = EFX_QWORD_FIELD(*event,
+ DRIVER_EV_RX_FLUSH_FAIL);
+ if (ev_queue < efx->n_rx_queues) {
+ rx_queue = efx->rx_queue + ev_queue;
+
+ /* retry the rx flush */
+ if (ev_failed)
+ falcon_flush_rx_queue(rx_queue);
+ else
+ rx_queue->flushed = true;
+ }
+ break;
+ }
+
+ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
+ }
+}
+
+/* Handle tx and rx flushes at the same time, since they run in
+ * parallel in the hardware and there's no reason for us to
+ * serialise them */
+int falcon_flush_queues(struct efx_nic *efx)
+{
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+ int i;
+ bool outstanding;
+
+ /* Issue flush requests */
+ efx_for_each_tx_queue(tx_queue, efx) {
+ tx_queue->flushed = false;
+ falcon_flush_tx_queue(tx_queue);
+ }
+ efx_for_each_rx_queue(rx_queue, efx) {
+ rx_queue->flushed = false;
+ falcon_flush_rx_queue(rx_queue);
+ }
+
+ /* Poll the evq looking for flush completions. Since we're not pushing
+ * any more rx or tx descriptors at this point, we're in no danger of
+ * overflowing the evq whilst we wait */
+ for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) {
+ msleep(FALCON_FLUSH_INTERVAL);
+ falcon_poll_flush_events(efx);
+
+ /* Check if every queue has been succesfully flushed */
+ outstanding = false;
+ efx_for_each_tx_queue(tx_queue, efx)
+ outstanding |= !tx_queue->flushed;
+ efx_for_each_rx_queue(rx_queue, efx)
+ outstanding |= !rx_queue->flushed;
+ if (!outstanding)
+ return 0;
+ }
+
+ /* Mark the queues as all flushed. We're going to return failure
+ * leading to a reset, or fake up success anyway. "flushed" now
+ * indicates that we tried to flush. */
+ efx_for_each_tx_queue(tx_queue, efx) {
+ if (!tx_queue->flushed)
+ EFX_ERR(efx, "tx queue %d flush command timed out\n",
+ tx_queue->queue);
+ tx_queue->flushed = true;
+ }
+ efx_for_each_rx_queue(rx_queue, efx) {
+ if (!rx_queue->flushed)
+ EFX_ERR(efx, "rx queue %d flush command timed out\n",
+ rx_queue->queue);
+ rx_queue->flushed = true;
+ }
+
+ if (EFX_WORKAROUND_7803(efx))
+ return 0;
+
+ return -ETIMEDOUT;
+}
/**************************************************************************
*
EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg));
}
- /* Disable DMA bus mastering on both devices */
- pci_disable_device(efx->pci_dev);
+ /* Disable both devices */
+ pci_clear_master(efx->pci_dev);
if (FALCON_IS_DUAL_FUNC(efx))
- pci_disable_device(nic_data->pci_dev2);
+ pci_clear_master(nic_data->pci_dev2);
+ falcon_disable_interrupts(efx);
if (++n_int_errors < FALCON_MAX_INT_ERRORS) {
EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n");
efx_for_each_channel(channel, efx) {
rc = request_irq(channel->irq, falcon_msi_interrupt,
IRQF_PROBE_SHARED, /* Not shared */
- efx->name, channel);
+ channel->name, channel);
if (rc) {
EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
goto fail2;
#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
+static int falcon_spi_poll(struct efx_nic *efx)
+{
+ efx_oword_t reg;
+ falcon_read(efx, ®, EE_SPI_HCMD_REG_KER);
+ return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
+}
+
/* Wait for SPI command completion */
static int falcon_spi_wait(struct efx_nic *efx)
{
- unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10);
- efx_oword_t reg;
- bool cmd_en, timer_active;
+ /* Most commands will finish quickly, so we start polling at
+ * very short intervals. Sometimes the command may have to
+ * wait for VPD or expansion ROM access outside of our
+ * control, so we allow up to 100 ms. */
+ unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10);
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ if (!falcon_spi_poll(efx))
+ return 0;
+ udelay(10);
+ }
for (;;) {
- falcon_read(efx, ®, EE_SPI_HCMD_REG_KER);
- cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
- timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
- if (!cmd_en && !timer_active)
+ if (!falcon_spi_poll(efx))
return 0;
if (time_after_eq(jiffies, timeout)) {
EFX_ERR(efx, "timed out waiting for SPI\n");
return -ETIMEDOUT;
}
- cpu_relax();
+ schedule_timeout_uninterruptible(1);
}
}
-static int falcon_spi_cmd(const struct efx_spi_device *spi,
- unsigned int command, int address,
- const void *in, void *out, unsigned int len)
+int falcon_spi_cmd(const struct efx_spi_device *spi,
+ unsigned int command, int address,
+ const void *in, void *out, size_t len)
{
struct efx_nic *efx = spi->efx;
bool addressed = (address >= 0);
/* Input validation */
if (len > FALCON_SPI_MAX_LEN)
return -EINVAL;
+ BUG_ON(!mutex_is_locked(&efx->spi_lock));
- /* Check SPI not currently being accessed */
- rc = falcon_spi_wait(efx);
+ /* Check that previous command is not still running */
+ rc = falcon_spi_poll(efx);
if (rc)
return rc;
return 0;
}
-static unsigned int
-falcon_spi_write_limit(const struct efx_spi_device *spi, unsigned int start)
+static size_t
+falcon_spi_write_limit(const struct efx_spi_device *spi, size_t start)
{
return min(FALCON_SPI_MAX_LEN,
(spi->block_size - (start & (spi->block_size - 1))));
return command | (((address >> 8) & spi->munge_address) << 3);
}
-
-static int falcon_spi_fast_wait(const struct efx_spi_device *spi)
+/* Wait up to 10 ms for buffered write completion */
+int falcon_spi_wait_write(const struct efx_spi_device *spi)
{
+ struct efx_nic *efx = spi->efx;
+ unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100);
u8 status;
- int i, rc;
-
- /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */
- for (i = 0; i < 50; i++) {
- udelay(20);
+ int rc;
+ for (;;) {
rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
&status, sizeof(status));
if (rc)
return rc;
if (!(status & SPI_STATUS_NRDY))
return 0;
+ if (time_after_eq(jiffies, timeout)) {
+ EFX_ERR(efx, "SPI write timeout on device %d"
+ " last status=0x%02x\n",
+ spi->device_id, status);
+ return -ETIMEDOUT;
+ }
+ schedule_timeout_uninterruptible(1);
}
- EFX_ERR(spi->efx,
- "timed out waiting for device %d last status=0x%02x\n",
- spi->device_id, status);
- return -ETIMEDOUT;
}
int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
size_t len, size_t *retlen, u8 *buffer)
{
- unsigned int command, block_len, pos = 0;
+ size_t block_len, pos = 0;
+ unsigned int command;
int rc = 0;
while (pos < len) {
- block_len = min((unsigned int)len - pos,
- FALCON_SPI_MAX_LEN);
+ block_len = min(len - pos, FALCON_SPI_MAX_LEN);
command = efx_spi_munge_command(spi, SPI_READ, start + pos);
rc = falcon_spi_cmd(spi, command, start + pos, NULL,
size_t len, size_t *retlen, const u8 *buffer)
{
u8 verify_buffer[FALCON_SPI_MAX_LEN];
- unsigned int command, block_len, pos = 0;
+ size_t block_len, pos = 0;
+ unsigned int command;
int rc = 0;
while (pos < len) {
if (rc)
break;
- block_len = min((unsigned int)len - pos,
+ block_len = min(len - pos,
falcon_spi_write_limit(spi, start + pos));
command = efx_spi_munge_command(spi, SPI_WRITE, start + pos);
rc = falcon_spi_cmd(spi, command, start + pos,
if (rc)
break;
- rc = falcon_spi_fast_wait(spi);
+ rc = falcon_spi_wait_write(spi);
if (rc)
break;
*
**************************************************************************
*/
-void falcon_drain_tx_fifo(struct efx_nic *efx)
+
+static int falcon_reset_macs(struct efx_nic *efx)
{
- efx_oword_t temp;
+ efx_oword_t reg;
int count;
- if ((falcon_rev(efx) < FALCON_REV_B0) ||
- (efx->loopback_mode != LOOPBACK_NONE))
- return;
+ if (falcon_rev(efx) < FALCON_REV_B0) {
+ /* It's not safe to use GLB_CTL_REG to reset the
+ * macs, so instead use the internal MAC resets
+ */
+ if (!EFX_IS10G(efx)) {
+ EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1);
+ falcon_write(efx, ®, GM_CFG1_REG);
+ udelay(1000);
+
+ EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0);
+ falcon_write(efx, ®, GM_CFG1_REG);
+ udelay(1000);
+ return 0;
+ } else {
+ EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1);
+ falcon_write(efx, ®, XM_GLB_CFG_REG);
+
+ for (count = 0; count < 10000; count++) {
+ falcon_read(efx, ®, XM_GLB_CFG_REG);
+ if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0)
+ return 0;
+ udelay(10);
+ }
- falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
- /* There is no point in draining more than once */
- if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
- return;
+ EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
+ return -ETIMEDOUT;
+ }
+ }
/* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */
- spin_lock(&efx->stats_lock);
+ efx_stats_disable(efx);
- EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1);
- falcon_write(efx, &temp, MAC0_CTRL_REG_KER);
+ falcon_read(efx, ®, MAC0_CTRL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
+ falcon_write(efx, ®, MAC0_CTRL_REG_KER);
- /* Reset the MAC and EM block. */
- falcon_read(efx, &temp, GLB_CTL_REG_KER);
- EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1);
- EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1);
- EFX_SET_OWORD_FIELD(temp, RST_EM, 1);
- falcon_write(efx, &temp, GLB_CTL_REG_KER);
+ falcon_read(efx, ®, GLB_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1);
+ EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1);
+ EFX_SET_OWORD_FIELD(reg, RST_EM, 1);
+ falcon_write(efx, ®, GLB_CTL_REG_KER);
count = 0;
while (1) {
- falcon_read(efx, &temp, GLB_CTL_REG_KER);
- if (!EFX_OWORD_FIELD(temp, RST_XGTX) &&
- !EFX_OWORD_FIELD(temp, RST_XGRX) &&
- !EFX_OWORD_FIELD(temp, RST_EM)) {
+ falcon_read(efx, ®, GLB_CTL_REG_KER);
+ if (!EFX_OWORD_FIELD(reg, RST_XGTX) &&
+ !EFX_OWORD_FIELD(reg, RST_XGRX) &&
+ !EFX_OWORD_FIELD(reg, RST_EM)) {
EFX_LOG(efx, "Completed MAC reset after %d loops\n",
count);
break;
udelay(10);
}
- spin_unlock(&efx->stats_lock);
+ efx_stats_enable(efx);
/* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */
- if (efx->link_up && EFX_WORKAROUND_5147(efx))
+ if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
falcon_reset_xaui(efx);
+
+ return 0;
+}
+
+void falcon_drain_tx_fifo(struct efx_nic *efx)
+{
+ efx_oword_t reg;
+
+ if ((falcon_rev(efx) < FALCON_REV_B0) ||
+ (efx->loopback_mode != LOOPBACK_NONE))
+ return;
+
+ falcon_read(efx, ®, MAC0_CTRL_REG_KER);
+ /* There is no point in draining more than once */
+ if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0))
+ return;
+
+ falcon_reset_macs(efx);
}
void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
{
- efx_oword_t temp;
+ efx_oword_t reg;
if (falcon_rev(efx) < FALCON_REV_B0)
return;
/* Isolate the MAC -> RX */
- falcon_read(efx, &temp, RX_CFG_REG_KER);
- EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0);
- falcon_write(efx, &temp, RX_CFG_REG_KER);
+ falcon_read(efx, ®, RX_CFG_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0);
+ falcon_write(efx, ®, RX_CFG_REG_KER);
if (!efx->link_up)
falcon_drain_tx_fifo(efx);
int link_speed;
bool tx_fc;
- if (efx->link_options & GM_LPA_10000)
- link_speed = 0x3;
- else if (efx->link_options & GM_LPA_1000)
- link_speed = 0x2;
- else if (efx->link_options & GM_LPA_100)
- link_speed = 0x1;
- else
- link_speed = 0x0;
+ switch (efx->link_speed) {
+ case 10000: link_speed = 3; break;
+ case 1000: link_speed = 2; break;
+ case 100: link_speed = 1; break;
+ default: link_speed = 0; break;
+ }
/* MAC_LINK_STATUS controls MAC backpressure but doesn't work
* as advertised. Disable to ensure packets are not
* indefinitely held and TX queue can be flushed at any point
/* Transmission of pause frames when RX crosses the threshold is
* covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
* Action on receipt of pause frames is controller by XM_DIS_FCNTL */
- tx_fc = !!(efx->flow_control & EFX_FC_TX);
+ tx_fc = !!(efx->link_fc & EFX_FC_TX);
falcon_read(efx, ®, RX_CFG_REG_KER);
EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
/* Wait for transfer to complete */
for (i = 0; i < 400; i++) {
- if (*(volatile u32 *)dma_done == FALCON_STATS_DONE)
+ if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) {
+ rmb(); /* Ensure the stats are valid. */
return 0;
+ }
udelay(10);
}
efx_dword_t md_stat;
int count;
- for (count = 0; count < 1000; count++) { /* wait upto 10ms */
+ /* wait upto 50ms - taken max from datasheet */
+ for (count = 0; count < 5000; count++) {
falcon_readl(efx, &md_stat, MD_STAT_REG_KER);
if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) {
if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 ||
static int falcon_probe_phy(struct efx_nic *efx)
{
switch (efx->phy_type) {
- case PHY_TYPE_10XPRESS:
- efx->phy_op = &falcon_tenxpress_phy_ops;
+ case PHY_TYPE_SFX7101:
+ efx->phy_op = &falcon_sfx7101_phy_ops;
+ break;
+ case PHY_TYPE_SFT9001A:
+ case PHY_TYPE_SFT9001B:
+ efx->phy_op = &falcon_sft9001_phy_ops;
break;
- case PHY_TYPE_XFP:
+ case PHY_TYPE_QT2022C2:
efx->phy_op = &falcon_xfp_phy_ops;
break;
default:
return -1;
}
- efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks;
+ if (efx->phy_op->macs & EFX_XMAC)
+ efx->loopback_modes |= ((1 << LOOPBACK_XGMII) |
+ (1 << LOOPBACK_XGXS) |
+ (1 << LOOPBACK_XAUI));
+ if (efx->phy_op->macs & EFX_GMAC)
+ efx->loopback_modes |= (1 << LOOPBACK_GMAC);
+ efx->loopback_modes |= efx->phy_op->loopbacks;
+
return 0;
}
+int falcon_switch_mac(struct efx_nic *efx)
+{
+ struct efx_mac_operations *old_mac_op = efx->mac_op;
+ efx_oword_t nic_stat;
+ unsigned strap_val;
+ int rc = 0;
+
+ /* Don't try to fetch MAC stats while we're switching MACs */
+ efx_stats_disable(efx);
+
+ /* Internal loopbacks override the phy speed setting */
+ if (efx->loopback_mode == LOOPBACK_GMAC) {
+ efx->link_speed = 1000;
+ efx->link_fd = true;
+ } else if (LOOPBACK_INTERNAL(efx)) {
+ efx->link_speed = 10000;
+ efx->link_fd = true;
+ }
+
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
+ efx->mac_op = (EFX_IS10G(efx) ?
+ &falcon_xmac_operations : &falcon_gmac_operations);
+
+ /* Always push the NIC_STAT_REG setting even if the mac hasn't
+ * changed, because this function is run post online reset */
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+ strap_val = EFX_IS10G(efx) ? 5 : 3;
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
+ EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1);
+ EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val);
+ falcon_write(efx, &nic_stat, NIC_STAT_REG);
+ } else {
+ /* Falcon A1 does not support 1G/10G speed switching
+ * and must not be used with a PHY that does. */
+ BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val);
+ }
+
+ if (old_mac_op == efx->mac_op)
+ goto out;
+
+ EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
+ /* Not all macs support a mac-level link state */
+ efx->mac_up = true;
+
+ rc = falcon_reset_macs(efx);
+out:
+ efx_stats_enable(efx);
+ return rc;
+}
+
/* This call is responsible for hooking in the MAC and PHY operations */
int falcon_probe_port(struct efx_nic *efx)
{
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
if (falcon_rev(efx) >= FALCON_REV_B0)
- efx->flow_control = EFX_FC_RX | EFX_FC_TX;
+ efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
else
- efx->flow_control = EFX_FC_RX;
+ efx->wanted_fc = EFX_FC_RX;
/* Allocate buffer for stats */
rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
falcon_write(efx, &mc_hash->oword[1], MAC_MCAST_HASH_REG1_KER);
}
+
+/**************************************************************************
+ *
+ * Falcon test code
+ *
+ **************************************************************************/
+
+int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
+{
+ struct falcon_nvconfig *nvconfig;
+ struct efx_spi_device *spi;
+ void *region;
+ int rc, magic_num, struct_ver;
+ __le16 *word, *limit;
+ u32 csum;
+
+ spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
+ if (!spi)
+ return -EINVAL;
+
+ region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
+ if (!region)
+ return -ENOMEM;
+ nvconfig = region + NVCONFIG_OFFSET;
+
+ mutex_lock(&efx->spi_lock);
+ rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region);
+ mutex_unlock(&efx->spi_lock);
+ if (rc) {
+ EFX_ERR(efx, "Failed to read %s\n",
+ efx->spi_flash ? "flash" : "EEPROM");
+ rc = -EIO;
+ goto out;
+ }
+
+ magic_num = le16_to_cpu(nvconfig->board_magic_num);
+ struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
+
+ rc = -EINVAL;
+ if (magic_num != NVCONFIG_BOARD_MAGIC_NUM) {
+ EFX_ERR(efx, "NVRAM bad magic 0x%x\n", magic_num);
+ goto out;
+ }
+ if (struct_ver < 2) {
+ EFX_ERR(efx, "NVRAM has ancient version 0x%x\n", struct_ver);
+ goto out;
+ } else if (struct_ver < 4) {
+ word = &nvconfig->board_magic_num;
+ limit = (__le16 *) (nvconfig + 1);
+ } else {
+ word = region;
+ limit = region + FALCON_NVCONFIG_END;
+ }
+ for (csum = 0; word < limit; ++word)
+ csum += le16_to_cpu(*word);
+
+ if (~csum & 0xffff) {
+ EFX_ERR(efx, "NVRAM has incorrect checksum\n");
+ goto out;
+ }
+
+ rc = 0;
+ if (nvconfig_out)
+ memcpy(nvconfig_out, nvconfig, sizeof(*nvconfig));
+
+ out:
+ kfree(region);
+ return rc;
+}
+
+/* Registers tested in the falcon register test */
+static struct {
+ unsigned address;
+ efx_oword_t mask;
+} efx_test_registers[] = {
+ { ADR_REGION_REG_KER,
+ EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) },
+ { RX_CFG_REG_KER,
+ EFX_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) },
+ { TX_CFG_REG_KER,
+ EFX_OWORD32(0x7FFF0037, 0x00000000, 0x00000000, 0x00000000) },
+ { TX_CFG2_REG_KER,
+ EFX_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) },
+ { MAC0_CTRL_REG_KER,
+ EFX_OWORD32(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000) },
+ { SRM_TX_DC_CFG_REG_KER,
+ EFX_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) },
+ { RX_DC_CFG_REG_KER,
+ EFX_OWORD32(0x0000000F, 0x00000000, 0x00000000, 0x00000000) },
+ { RX_DC_PF_WM_REG_KER,
+ EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
+ { DP_CTRL_REG,
+ EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
+ { GM_CFG2_REG,
+ EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) },
+ { GMF_CFG0_REG,
+ EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_GLB_CFG_REG,
+ EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_TX_CFG_REG,
+ EFX_OWORD32(0x00080164, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_RX_CFG_REG,
+ EFX_OWORD32(0x07100A0C, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_RX_PARAM_REG,
+ EFX_OWORD32(0x00001FF8, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_FC_REG,
+ EFX_OWORD32(0xFFFF0001, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_ADR_LO_REG,
+ EFX_OWORD32(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000) },
+ { XX_SD_CTL_REG,
+ EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) },
+};
+
+static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
+ const efx_oword_t *mask)
+{
+ return ((a->u64[0] ^ b->u64[0]) & mask->u64[0]) ||
+ ((a->u64[1] ^ b->u64[1]) & mask->u64[1]);
+}
+
+int falcon_test_registers(struct efx_nic *efx)
+{
+ unsigned address = 0, i, j;
+ efx_oword_t mask, imask, original, reg, buf;
+
+ /* Falcon should be in loopback to isolate the XMAC from the PHY */
+ WARN_ON(!LOOPBACK_INTERNAL(efx));
+
+ for (i = 0; i < ARRAY_SIZE(efx_test_registers); ++i) {
+ address = efx_test_registers[i].address;
+ mask = imask = efx_test_registers[i].mask;
+ EFX_INVERT_OWORD(imask);
+
+ falcon_read(efx, &original, address);
+
+ /* bit sweep on and off */
+ for (j = 0; j < 128; j++) {
+ if (!EFX_EXTRACT_OWORD32(mask, j, j))
+ continue;
+
+ /* Test this testable bit can be set in isolation */
+ EFX_AND_OWORD(reg, original, mask);
+ EFX_SET_OWORD32(reg, j, j, 1);
+
+ falcon_write(efx, ®, address);
+ falcon_read(efx, &buf, address);
+
+ if (efx_masked_compare_oword(®, &buf, &mask))
+ goto fail;
+
+ /* Test this testable bit can be cleared in isolation */
+ EFX_OR_OWORD(reg, original, mask);
+ EFX_SET_OWORD32(reg, j, j, 0);
+
+ falcon_write(efx, ®, address);
+ falcon_read(efx, &buf, address);
+
+ if (efx_masked_compare_oword(®, &buf, &mask))
+ goto fail;
+ }
+
+ falcon_write(efx, &original, address);
+ }
+
+ return 0;
+
+fail:
+ EFX_ERR(efx, "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT
+ " at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg),
+ EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask));
+ return -EIO;
+}
+
/**************************************************************************
*
* Device reset
struct efx_spi_device *spi_device;
if (device_type != 0) {
- spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL);
+ spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL);
if (!spi_device)
return -ENOMEM;
spi_device->device_id = device_id;
SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN);
spi_device->munge_address = (spi_device->size == 1 << 9 &&
spi_device->addr_len == 1);
+ spi_device->erase_command =
+ SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ERASE_CMD);
+ spi_device->erase_size =
+ 1 << SPI_DEV_TYPE_FIELD(device_type,
+ SPI_DEV_TYPE_ERASE_SIZE);
spi_device->block_size =
1 << SPI_DEV_TYPE_FIELD(device_type,
SPI_DEV_TYPE_BLOCK_SIZE);
static int falcon_probe_nvconfig(struct efx_nic *efx)
{
struct falcon_nvconfig *nvconfig;
- struct efx_spi_device *spi;
- int magic_num, struct_ver, board_rev;
+ int board_rev;
int rc;
nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
if (!nvconfig)
return -ENOMEM;
- /* Read the whole configuration structure into memory. */
- spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
- rc = falcon_spi_read(spi, NVCONFIG_BASE, sizeof(*nvconfig),
- NULL, (char *)nvconfig);
- if (rc) {
- EFX_ERR(efx, "Failed to read %s\n", efx->spi_flash ? "flash" :
- "EEPROM");
- goto fail1;
- }
-
- /* Read the MAC addresses */
- memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
-
- /* Read the board configuration. */
- magic_num = le16_to_cpu(nvconfig->board_magic_num);
- struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
-
- if (magic_num != NVCONFIG_BOARD_MAGIC_NUM || struct_ver < 2) {
- EFX_ERR(efx, "Non volatile memory bad magic=%x ver=%x "
- "therefore using defaults\n", magic_num, struct_ver);
+ rc = falcon_read_nvram(efx, nvconfig);
+ if (rc == -EINVAL) {
+ EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
efx->phy_type = PHY_TYPE_NONE;
efx->mii.phy_id = PHY_ADDR_INVALID;
board_rev = 0;
+ rc = 0;
+ } else if (rc) {
+ goto fail1;
} else {
struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2;
struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
efx->mii.phy_id = v2->port0_phy_addr;
board_rev = le16_to_cpu(v2->board_revision);
- if (struct_ver >= 3) {
+ if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
__le32 fl = v3->spi_device_type[EE_SPI_FLASH];
__le32 ee = v3->spi_device_type[EE_SPI_EEPROM];
rc = falcon_spi_device_init(efx, &efx->spi_flash,
}
}
+ /* Read the MAC addresses */
+ memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
+
EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id);
efx_set_board_info(efx, board_rev);
static int falcon_probe_nic_variant(struct efx_nic *efx)
{
efx_oword_t altera_build;
+ efx_oword_t nic_stat;
falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
if (EFX_OWORD_FIELD(altera_build, VER_ALL)) {
return -ENODEV;
}
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+
switch (falcon_rev(efx)) {
case FALCON_REV_A0:
case 0xff:
EFX_ERR(efx, "Falcon rev A0 not supported\n");
return -ENODEV;
- case FALCON_REV_A1:{
- efx_oword_t nic_stat;
-
- falcon_read(efx, &nic_stat, NIC_STAT_REG);
-
+ case FALCON_REV_A1:
if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) {
EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
return -ENODEV;
}
- if (!EFX_OWORD_FIELD(nic_stat, STRAP_10G)) {
- EFX_ERR(efx, "1G mode not supported\n");
- return -ENODEV;
- }
break;
- }
case FALCON_REV_B0:
break;
return -ENODEV;
}
+ /* Initial assumed speed */
+ efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000;
+
return 0;
}
static void falcon_probe_spi_devices(struct efx_nic *efx)
{
efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
- bool has_flash, has_eeprom, boot_is_external;
+ int boot_dev;
falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER);
falcon_read(efx, &nic_stat, NIC_STAT_REG);
falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
- has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST);
- has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST);
- boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE);
-
- if (has_flash) {
- /* Default flash SPI device: Atmel AT25F1024
- * 128 KB, 24-bit address, 32 KB erase block,
- * 256 B write block
- */
- u32 flash_device_type =
- (17 << SPI_DEV_TYPE_SIZE_LBN)
- | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
- | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
- | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
-
- falcon_spi_device_init(efx, &efx->spi_flash,
- EE_SPI_FLASH, flash_device_type);
-
- if (!boot_is_external) {
- /* Disable VPD and set clock dividers to safe
- * values for initial programming.
- */
- EFX_LOG(efx, "Booted from internal ASIC settings;"
- " setting SPI config\n");
- EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
- /* 125 MHz / 7 ~= 20 MHz */
- EE_SF_CLOCK_DIV, 7,
- /* 125 MHz / 63 ~= 2 MHz */
- EE_EE_CLOCK_DIV, 63);
- falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
- }
- }
-
- if (has_eeprom) {
- u32 eeprom_device_type;
-
- /* If it has no flash, it must have a large EEPROM
- * for chip config; otherwise check whether 9-bit
- * addressing is used for VPD configuration
- */
- if (has_flash &&
- (!boot_is_external ||
- EFX_OWORD_FIELD(ee_vpd_cfg, EE_VPD_EN_AD9_MODE))) {
- /* Default SPI device: Atmel AT25040 or similar
- * 512 B, 9-bit address, 8 B write block
- */
- eeprom_device_type =
- (9 << SPI_DEV_TYPE_SIZE_LBN)
- | (1 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
- } else {
- /* "Large" SPI device: Atmel AT25640 or similar
- * 8 KB, 16-bit address, 32 B write block
- */
- eeprom_device_type =
- (13 << SPI_DEV_TYPE_SIZE_LBN)
- | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
- }
-
- falcon_spi_device_init(efx, &efx->spi_eeprom,
- EE_SPI_EEPROM, eeprom_device_type);
+ if (EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE)) {
+ boot_dev = (EFX_OWORD_FIELD(nic_stat, SF_PRST) ?
+ EE_SPI_FLASH : EE_SPI_EEPROM);
+ EFX_LOG(efx, "Booted from %s\n",
+ boot_dev == EE_SPI_FLASH ? "flash" : "EEPROM");
+ } else {
+ /* Disable VPD and set clock dividers to safe
+ * values for initial programming. */
+ boot_dev = -1;
+ EFX_LOG(efx, "Booted from internal ASIC settings;"
+ " setting SPI config\n");
+ EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
+ /* 125 MHz / 7 ~= 20 MHz */
+ EE_SF_CLOCK_DIV, 7,
+ /* 125 MHz / 63 ~= 2 MHz */
+ EE_EE_CLOCK_DIV, 63);
+ falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
}
- EFX_LOG(efx, "flash is %s, EEPROM is %s\n",
- (has_flash ? "present" : "absent"),
- (has_eeprom ? "present" : "absent"));
+ if (boot_dev == EE_SPI_FLASH)
+ falcon_spi_device_init(efx, &efx->spi_flash, EE_SPI_FLASH,
+ default_flash_type);
+ if (boot_dev == EE_SPI_EEPROM)
+ falcon_spi_device_init(efx, &efx->spi_eeprom, EE_SPI_EEPROM,
+ large_eeprom_type);
}
int falcon_probe_nic(struct efx_nic *efx)
/* Allocate storage for hardware specific data */
nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
+ if (!nic_data)
+ return -ENOMEM;
efx->nic_data = nic_data;
/* Determine number of ports etc. */
goto fail5;
/* Initialise I2C adapter */
- efx->i2c_adap.owner = THIS_MODULE;
+ efx->i2c_adap.owner = THIS_MODULE;
nic_data->i2c_data = falcon_i2c_bit_operations;
nic_data->i2c_data.data = efx;
- efx->i2c_adap.algo_data = &nic_data->i2c_data;
+ efx->i2c_adap.algo_data = &nic_data->i2c_data;
efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
rc = i2c_bit_add_bus(&efx->i2c_adap);
unsigned thresh;
int rc;
- /* Set up the address region register. This is only needed
- * for the B0 FPGA, but since we are just pushing in the
- * reset defaults this may as well be unconditional. */
- EFX_POPULATE_OWORD_4(temp, ADR_REGION0, 0,
- ADR_REGION1, (1 << 16),
- ADR_REGION2, (2 << 16),
- ADR_REGION3, (3 << 16));
- falcon_write(efx, &temp, ADR_REGION_REG_KER);
-
/* Use on-chip SRAM */
falcon_read(efx, &temp, NIC_STAT_REG);
EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
falcon_write(efx, &temp, NIC_STAT_REG);
+ /* Set the source of the GMAC clock */
+ if (falcon_rev(efx) == FALCON_REV_B0) {
+ falcon_read(efx, &temp, GPIO_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true);
+ falcon_write(efx, &temp, GPIO_CTL_REG_KER);
+ }
+
/* Set buffer table mode */
EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL);
falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER);