diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-09-01 07:47:16 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-09-03 09:53:45 -0400 |
commit | 4a5b504d0c582db80813b70359b616ea30e91743 (patch) | |
tree | c3b10e411914a42c21d2a525e26eb440e37c6651 /drivers/net/sfc | |
parent | 4d566063a799231b99d9a21128634ea78b89ab72 (diff) |
sfc: Export boot configuration in EEPROM through ethtool
Extend the SPI device setup code to support this.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/ethtool.c | 52 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 358 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_hwdefs.h | 35 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 7 | ||||
-rw-r--r-- | drivers/net/sfc/spi.h | 89 |
5 files changed, 446 insertions, 95 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 6142c3a394bf..72a2eb2e3a19 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "ethtool.h" | 17 | #include "ethtool.h" |
18 | #include "falcon.h" | 18 | #include "falcon.h" |
19 | #include "gmii.h" | 19 | #include "gmii.h" |
20 | #include "spi.h" | ||
20 | #include "mac.h" | 21 | #include "mac.h" |
21 | 22 | ||
22 | const char *efx_loopback_mode_names[] = { | 23 | const char *efx_loopback_mode_names[] = { |
@@ -171,6 +172,11 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { | |||
171 | /* Number of ethtool statistics */ | 172 | /* Number of ethtool statistics */ |
172 | #define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats) | 173 | #define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats) |
173 | 174 | ||
175 | /* EEPROM range with gPXE configuration */ | ||
176 | #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB | ||
177 | #define EFX_ETHTOOL_EEPROM_MIN 0x100U | ||
178 | #define EFX_ETHTOOL_EEPROM_MAX 0x400U | ||
179 | |||
174 | /************************************************************************** | 180 | /************************************************************************** |
175 | * | 181 | * |
176 | * Ethtool operations | 182 | * Ethtool operations |
@@ -532,6 +538,49 @@ static u32 efx_ethtool_get_link(struct net_device *net_dev) | |||
532 | return efx->link_up; | 538 | return efx->link_up; |
533 | } | 539 | } |
534 | 540 | ||
541 | static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) | ||
542 | { | ||
543 | struct efx_nic *efx = netdev_priv(net_dev); | ||
544 | struct efx_spi_device *spi = efx->spi_eeprom; | ||
545 | |||
546 | if (!spi) | ||
547 | return 0; | ||
548 | return min(spi->size, EFX_ETHTOOL_EEPROM_MAX) - | ||
549 | min(spi->size, EFX_ETHTOOL_EEPROM_MIN); | ||
550 | } | ||
551 | |||
552 | static int efx_ethtool_get_eeprom(struct net_device *net_dev, | ||
553 | struct ethtool_eeprom *eeprom, u8 *buf) | ||
554 | { | ||
555 | struct efx_nic *efx = netdev_priv(net_dev); | ||
556 | struct efx_spi_device *spi = efx->spi_eeprom; | ||
557 | size_t len; | ||
558 | int rc; | ||
559 | |||
560 | rc = falcon_spi_read(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN, | ||
561 | eeprom->len, &len, buf); | ||
562 | eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC; | ||
563 | eeprom->len = len; | ||
564 | return rc; | ||
565 | } | ||
566 | |||
567 | static int efx_ethtool_set_eeprom(struct net_device *net_dev, | ||
568 | struct ethtool_eeprom *eeprom, u8 *buf) | ||
569 | { | ||
570 | struct efx_nic *efx = netdev_priv(net_dev); | ||
571 | struct efx_spi_device *spi = efx->spi_eeprom; | ||
572 | size_t len; | ||
573 | int rc; | ||
574 | |||
575 | if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC) | ||
576 | return -EINVAL; | ||
577 | |||
578 | rc = falcon_spi_write(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN, | ||
579 | eeprom->len, &len, buf); | ||
580 | eeprom->len = len; | ||
581 | return rc; | ||
582 | } | ||
583 | |||
535 | static int efx_ethtool_get_coalesce(struct net_device *net_dev, | 584 | static int efx_ethtool_get_coalesce(struct net_device *net_dev, |
536 | struct ethtool_coalesce *coalesce) | 585 | struct ethtool_coalesce *coalesce) |
537 | { | 586 | { |
@@ -653,6 +702,9 @@ struct ethtool_ops efx_ethtool_ops = { | |||
653 | .get_drvinfo = efx_ethtool_get_drvinfo, | 702 | .get_drvinfo = efx_ethtool_get_drvinfo, |
654 | .nway_reset = efx_ethtool_nway_reset, | 703 | .nway_reset = efx_ethtool_nway_reset, |
655 | .get_link = efx_ethtool_get_link, | 704 | .get_link = efx_ethtool_get_link, |
705 | .get_eeprom_len = efx_ethtool_get_eeprom_len, | ||
706 | .get_eeprom = efx_ethtool_get_eeprom, | ||
707 | .set_eeprom = efx_ethtool_set_eeprom, | ||
656 | .get_coalesce = efx_ethtool_get_coalesce, | 708 | .get_coalesce = efx_ethtool_get_coalesce, |
657 | .set_coalesce = efx_ethtool_set_coalesce, | 709 | .set_coalesce = efx_ethtool_set_coalesce, |
658 | .get_pauseparam = efx_ethtool_get_pauseparam, | 710 | .get_pauseparam = efx_ethtool_get_pauseparam, |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 9a13e5c8c9f3..30176390481c 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -1620,64 +1620,195 @@ void falcon_fini_interrupt(struct efx_nic *efx) | |||
1620 | /* Wait for SPI command completion */ | 1620 | /* Wait for SPI command completion */ |
1621 | static int falcon_spi_wait(struct efx_nic *efx) | 1621 | static int falcon_spi_wait(struct efx_nic *efx) |
1622 | { | 1622 | { |
1623 | unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10); | ||
1623 | efx_oword_t reg; | 1624 | efx_oword_t reg; |
1624 | int cmd_en, timer_active; | 1625 | bool cmd_en, timer_active; |
1625 | int count; | ||
1626 | 1626 | ||
1627 | count = 0; | 1627 | for (;;) { |
1628 | do { | ||
1629 | falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); | 1628 | falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); |
1630 | cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN); | 1629 | cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN); |
1631 | timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE); | 1630 | timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE); |
1632 | if (!cmd_en && !timer_active) | 1631 | if (!cmd_en && !timer_active) |
1633 | return 0; | 1632 | return 0; |
1634 | udelay(10); | 1633 | if (time_after_eq(jiffies, timeout)) { |
1635 | } while (++count < 10000); /* wait upto 100msec */ | 1634 | EFX_ERR(efx, "timed out waiting for SPI\n"); |
1636 | EFX_ERR(efx, "timed out waiting for SPI\n"); | 1635 | return -ETIMEDOUT; |
1637 | return -ETIMEDOUT; | 1636 | } |
1637 | cpu_relax(); | ||
1638 | } | ||
1638 | } | 1639 | } |
1639 | 1640 | ||
1640 | static int | 1641 | static int falcon_spi_cmd(const struct efx_spi_device *spi, |
1641 | falcon_spi_read(struct efx_nic *efx, int device_id, unsigned int command, | 1642 | unsigned int command, int address, |
1642 | unsigned int address, unsigned int addr_len, | 1643 | const void *in, void *out, unsigned int len) |
1643 | void *data, unsigned int len) | ||
1644 | { | 1644 | { |
1645 | struct efx_nic *efx = spi->efx; | ||
1646 | bool addressed = (address >= 0); | ||
1647 | bool reading = (out != NULL); | ||
1645 | efx_oword_t reg; | 1648 | efx_oword_t reg; |
1646 | int rc; | 1649 | int rc; |
1647 | 1650 | ||
1648 | BUG_ON(len > FALCON_SPI_MAX_LEN); | 1651 | /* Input validation */ |
1652 | if (len > FALCON_SPI_MAX_LEN) | ||
1653 | return -EINVAL; | ||
1649 | 1654 | ||
1650 | /* Check SPI not currently being accessed */ | 1655 | /* Check SPI not currently being accessed */ |
1651 | rc = falcon_spi_wait(efx); | 1656 | rc = falcon_spi_wait(efx); |
1652 | if (rc) | 1657 | if (rc) |
1653 | return rc; | 1658 | return rc; |
1654 | 1659 | ||
1655 | /* Program address register */ | 1660 | /* Program address register, if we have an address */ |
1656 | EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address); | 1661 | if (addressed) { |
1657 | falcon_write(efx, ®, EE_SPI_HADR_REG_KER); | 1662 | EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address); |
1663 | falcon_write(efx, ®, EE_SPI_HADR_REG_KER); | ||
1664 | } | ||
1665 | |||
1666 | /* Program data register, if we have data */ | ||
1667 | if (in != NULL) { | ||
1668 | memcpy(®, in, len); | ||
1669 | falcon_write(efx, ®, EE_SPI_HDATA_REG_KER); | ||
1670 | } | ||
1658 | 1671 | ||
1659 | /* Issue read command */ | 1672 | /* Issue read/write command */ |
1660 | EFX_POPULATE_OWORD_7(reg, | 1673 | EFX_POPULATE_OWORD_7(reg, |
1661 | EE_SPI_HCMD_CMD_EN, 1, | 1674 | EE_SPI_HCMD_CMD_EN, 1, |
1662 | EE_SPI_HCMD_SF_SEL, device_id, | 1675 | EE_SPI_HCMD_SF_SEL, spi->device_id, |
1663 | EE_SPI_HCMD_DABCNT, len, | 1676 | EE_SPI_HCMD_DABCNT, len, |
1664 | EE_SPI_HCMD_READ, EE_SPI_READ, | 1677 | EE_SPI_HCMD_READ, reading, |
1665 | EE_SPI_HCMD_DUBCNT, 0, | 1678 | EE_SPI_HCMD_DUBCNT, 0, |
1666 | EE_SPI_HCMD_ADBCNT, addr_len, | 1679 | EE_SPI_HCMD_ADBCNT, |
1680 | (addressed ? spi->addr_len : 0), | ||
1667 | EE_SPI_HCMD_ENC, command); | 1681 | EE_SPI_HCMD_ENC, command); |
1668 | falcon_write(efx, ®, EE_SPI_HCMD_REG_KER); | 1682 | falcon_write(efx, ®, EE_SPI_HCMD_REG_KER); |
1669 | 1683 | ||
1670 | /* Wait for read to complete */ | 1684 | /* Wait for read/write to complete */ |
1671 | rc = falcon_spi_wait(efx); | 1685 | rc = falcon_spi_wait(efx); |
1672 | if (rc) | 1686 | if (rc) |
1673 | return rc; | 1687 | return rc; |
1674 | 1688 | ||
1675 | /* Read data */ | 1689 | /* Read data */ |
1676 | falcon_read(efx, ®, EE_SPI_HDATA_REG_KER); | 1690 | if (out != NULL) { |
1677 | memcpy(data, ®, len); | 1691 | falcon_read(efx, ®, EE_SPI_HDATA_REG_KER); |
1692 | memcpy(out, ®, len); | ||
1693 | } | ||
1694 | |||
1678 | return 0; | 1695 | return 0; |
1679 | } | 1696 | } |
1680 | 1697 | ||
1698 | static unsigned int | ||
1699 | falcon_spi_write_limit(const struct efx_spi_device *spi, unsigned int start) | ||
1700 | { | ||
1701 | return min(FALCON_SPI_MAX_LEN, | ||
1702 | (spi->block_size - (start & (spi->block_size - 1)))); | ||
1703 | } | ||
1704 | |||
1705 | static inline u8 | ||
1706 | efx_spi_munge_command(const struct efx_spi_device *spi, | ||
1707 | const u8 command, const unsigned int address) | ||
1708 | { | ||
1709 | return command | (((address >> 8) & spi->munge_address) << 3); | ||
1710 | } | ||
1711 | |||
1712 | |||
1713 | static int falcon_spi_fast_wait(const struct efx_spi_device *spi) | ||
1714 | { | ||
1715 | u8 status; | ||
1716 | int i, rc; | ||
1717 | |||
1718 | /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */ | ||
1719 | for (i = 0; i < 50; i++) { | ||
1720 | udelay(20); | ||
1721 | |||
1722 | rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, | ||
1723 | &status, sizeof(status)); | ||
1724 | if (rc) | ||
1725 | return rc; | ||
1726 | if (!(status & SPI_STATUS_NRDY)) | ||
1727 | return 0; | ||
1728 | } | ||
1729 | EFX_ERR(spi->efx, | ||
1730 | "timed out waiting for device %d last status=0x%02x\n", | ||
1731 | spi->device_id, status); | ||
1732 | return -ETIMEDOUT; | ||
1733 | } | ||
1734 | |||
1735 | int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, | ||
1736 | size_t len, size_t *retlen, u8 *buffer) | ||
1737 | { | ||
1738 | unsigned int command, block_len, pos = 0; | ||
1739 | int rc = 0; | ||
1740 | |||
1741 | while (pos < len) { | ||
1742 | block_len = min((unsigned int)len - pos, | ||
1743 | FALCON_SPI_MAX_LEN); | ||
1744 | |||
1745 | command = efx_spi_munge_command(spi, SPI_READ, start + pos); | ||
1746 | rc = falcon_spi_cmd(spi, command, start + pos, NULL, | ||
1747 | buffer + pos, block_len); | ||
1748 | if (rc) | ||
1749 | break; | ||
1750 | pos += block_len; | ||
1751 | |||
1752 | /* Avoid locking up the system */ | ||
1753 | cond_resched(); | ||
1754 | if (signal_pending(current)) { | ||
1755 | rc = -EINTR; | ||
1756 | break; | ||
1757 | } | ||
1758 | } | ||
1759 | |||
1760 | if (retlen) | ||
1761 | *retlen = pos; | ||
1762 | return rc; | ||
1763 | } | ||
1764 | |||
1765 | int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, | ||
1766 | size_t len, size_t *retlen, const u8 *buffer) | ||
1767 | { | ||
1768 | u8 verify_buffer[FALCON_SPI_MAX_LEN]; | ||
1769 | unsigned int command, block_len, pos = 0; | ||
1770 | int rc = 0; | ||
1771 | |||
1772 | while (pos < len) { | ||
1773 | rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0); | ||
1774 | if (rc) | ||
1775 | break; | ||
1776 | |||
1777 | block_len = min((unsigned int)len - pos, | ||
1778 | falcon_spi_write_limit(spi, start + pos)); | ||
1779 | command = efx_spi_munge_command(spi, SPI_WRITE, start + pos); | ||
1780 | rc = falcon_spi_cmd(spi, command, start + pos, | ||
1781 | buffer + pos, NULL, block_len); | ||
1782 | if (rc) | ||
1783 | break; | ||
1784 | |||
1785 | rc = falcon_spi_fast_wait(spi); | ||
1786 | if (rc) | ||
1787 | break; | ||
1788 | |||
1789 | command = efx_spi_munge_command(spi, SPI_READ, start + pos); | ||
1790 | rc = falcon_spi_cmd(spi, command, start + pos, | ||
1791 | NULL, verify_buffer, block_len); | ||
1792 | if (memcmp(verify_buffer, buffer + pos, block_len)) { | ||
1793 | rc = -EIO; | ||
1794 | break; | ||
1795 | } | ||
1796 | |||
1797 | pos += block_len; | ||
1798 | |||
1799 | /* Avoid locking up the system */ | ||
1800 | cond_resched(); | ||
1801 | if (signal_pending(current)) { | ||
1802 | rc = -EINTR; | ||
1803 | break; | ||
1804 | } | ||
1805 | } | ||
1806 | |||
1807 | if (retlen) | ||
1808 | *retlen = pos; | ||
1809 | return rc; | ||
1810 | } | ||
1811 | |||
1681 | /************************************************************************** | 1812 | /************************************************************************** |
1682 | * | 1813 | * |
1683 | * MAC wrapper | 1814 | * MAC wrapper |
@@ -2251,40 +2382,66 @@ static int falcon_reset_sram(struct efx_nic *efx) | |||
2251 | return -ETIMEDOUT; | 2382 | return -ETIMEDOUT; |
2252 | } | 2383 | } |
2253 | 2384 | ||
2385 | static int falcon_spi_device_init(struct efx_nic *efx, | ||
2386 | struct efx_spi_device **spi_device_ret, | ||
2387 | unsigned int device_id, u32 device_type) | ||
2388 | { | ||
2389 | struct efx_spi_device *spi_device; | ||
2390 | |||
2391 | if (device_type != 0) { | ||
2392 | spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL); | ||
2393 | if (!spi_device) | ||
2394 | return -ENOMEM; | ||
2395 | spi_device->device_id = device_id; | ||
2396 | spi_device->size = | ||
2397 | 1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE); | ||
2398 | spi_device->addr_len = | ||
2399 | SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN); | ||
2400 | spi_device->munge_address = (spi_device->size == 1 << 9 && | ||
2401 | spi_device->addr_len == 1); | ||
2402 | spi_device->block_size = | ||
2403 | 1 << SPI_DEV_TYPE_FIELD(device_type, | ||
2404 | SPI_DEV_TYPE_BLOCK_SIZE); | ||
2405 | |||
2406 | spi_device->efx = efx; | ||
2407 | } else { | ||
2408 | spi_device = NULL; | ||
2409 | } | ||
2410 | |||
2411 | kfree(*spi_device_ret); | ||
2412 | *spi_device_ret = spi_device; | ||
2413 | return 0; | ||
2414 | } | ||
2415 | |||
2416 | |||
2417 | static void falcon_remove_spi_devices(struct efx_nic *efx) | ||
2418 | { | ||
2419 | kfree(efx->spi_eeprom); | ||
2420 | efx->spi_eeprom = NULL; | ||
2421 | kfree(efx->spi_flash); | ||
2422 | efx->spi_flash = NULL; | ||
2423 | } | ||
2424 | |||
2254 | /* Extract non-volatile configuration */ | 2425 | /* Extract non-volatile configuration */ |
2255 | static int falcon_probe_nvconfig(struct efx_nic *efx) | 2426 | static int falcon_probe_nvconfig(struct efx_nic *efx) |
2256 | { | 2427 | { |
2257 | struct falcon_nvconfig *nvconfig; | 2428 | struct falcon_nvconfig *nvconfig; |
2258 | efx_oword_t nic_stat; | 2429 | struct efx_spi_device *spi; |
2259 | int device_id; | ||
2260 | unsigned addr_len; | ||
2261 | size_t offset, len; | ||
2262 | int magic_num, struct_ver, board_rev; | 2430 | int magic_num, struct_ver, board_rev; |
2263 | int rc; | 2431 | int rc; |
2264 | 2432 | ||
2265 | /* Find the boot device. */ | ||
2266 | falcon_read(efx, &nic_stat, NIC_STAT_REG); | ||
2267 | if (EFX_OWORD_FIELD(nic_stat, SF_PRST)) { | ||
2268 | device_id = EE_SPI_FLASH; | ||
2269 | addr_len = 3; | ||
2270 | } else if (EFX_OWORD_FIELD(nic_stat, EE_PRST)) { | ||
2271 | device_id = EE_SPI_EEPROM; | ||
2272 | addr_len = 2; | ||
2273 | } else { | ||
2274 | return -ENODEV; | ||
2275 | } | ||
2276 | |||
2277 | nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL); | 2433 | nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL); |
2434 | if (!nvconfig) | ||
2435 | return -ENOMEM; | ||
2278 | 2436 | ||
2279 | /* Read the whole configuration structure into memory. */ | 2437 | /* Read the whole configuration structure into memory. */ |
2280 | for (offset = 0; offset < sizeof(*nvconfig); offset += len) { | 2438 | spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom; |
2281 | len = min(sizeof(*nvconfig) - offset, | 2439 | rc = falcon_spi_read(spi, NVCONFIG_BASE, sizeof(*nvconfig), |
2282 | (size_t) FALCON_SPI_MAX_LEN); | 2440 | NULL, (char *)nvconfig); |
2283 | rc = falcon_spi_read(efx, device_id, SPI_READ, | 2441 | if (rc) { |
2284 | NVCONFIG_BASE + offset, addr_len, | 2442 | EFX_ERR(efx, "Failed to read %s\n", efx->spi_flash ? "flash" : |
2285 | (char *)nvconfig + offset, len); | 2443 | "EEPROM"); |
2286 | if (rc) | 2444 | goto fail1; |
2287 | goto out; | ||
2288 | } | 2445 | } |
2289 | 2446 | ||
2290 | /* Read the MAC addresses */ | 2447 | /* Read the MAC addresses */ |
@@ -2302,17 +2459,38 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) | |||
2302 | board_rev = 0; | 2459 | board_rev = 0; |
2303 | } else { | 2460 | } else { |
2304 | struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2; | 2461 | struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2; |
2462 | struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; | ||
2305 | 2463 | ||
2306 | efx->phy_type = v2->port0_phy_type; | 2464 | efx->phy_type = v2->port0_phy_type; |
2307 | efx->mii.phy_id = v2->port0_phy_addr; | 2465 | efx->mii.phy_id = v2->port0_phy_addr; |
2308 | board_rev = le16_to_cpu(v2->board_revision); | 2466 | board_rev = le16_to_cpu(v2->board_revision); |
2467 | |||
2468 | if (struct_ver >= 3) { | ||
2469 | __le32 fl = v3->spi_device_type[EE_SPI_FLASH]; | ||
2470 | __le32 ee = v3->spi_device_type[EE_SPI_EEPROM]; | ||
2471 | rc = falcon_spi_device_init(efx, &efx->spi_flash, | ||
2472 | EE_SPI_FLASH, | ||
2473 | le32_to_cpu(fl)); | ||
2474 | if (rc) | ||
2475 | goto fail2; | ||
2476 | rc = falcon_spi_device_init(efx, &efx->spi_eeprom, | ||
2477 | EE_SPI_EEPROM, | ||
2478 | le32_to_cpu(ee)); | ||
2479 | if (rc) | ||
2480 | goto fail2; | ||
2481 | } | ||
2309 | } | 2482 | } |
2310 | 2483 | ||
2311 | EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); | 2484 | EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); |
2312 | 2485 | ||
2313 | efx_set_board_info(efx, board_rev); | 2486 | efx_set_board_info(efx, board_rev); |
2314 | 2487 | ||
2315 | out: | 2488 | kfree(nvconfig); |
2489 | return 0; | ||
2490 | |||
2491 | fail2: | ||
2492 | falcon_remove_spi_devices(efx); | ||
2493 | fail1: | ||
2316 | kfree(nvconfig); | 2494 | kfree(nvconfig); |
2317 | return rc; | 2495 | return rc; |
2318 | } | 2496 | } |
@@ -2363,6 +2541,86 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) | |||
2363 | return 0; | 2541 | return 0; |
2364 | } | 2542 | } |
2365 | 2543 | ||
2544 | /* Probe all SPI devices on the NIC */ | ||
2545 | static void falcon_probe_spi_devices(struct efx_nic *efx) | ||
2546 | { | ||
2547 | efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg; | ||
2548 | bool has_flash, has_eeprom, boot_is_external; | ||
2549 | |||
2550 | falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER); | ||
2551 | falcon_read(efx, &nic_stat, NIC_STAT_REG); | ||
2552 | falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); | ||
2553 | |||
2554 | has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST); | ||
2555 | has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST); | ||
2556 | boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE); | ||
2557 | |||
2558 | if (has_flash) { | ||
2559 | /* Default flash SPI device: Atmel AT25F1024 | ||
2560 | * 128 KB, 24-bit address, 32 KB erase block, | ||
2561 | * 256 B write block | ||
2562 | */ | ||
2563 | u32 flash_device_type = | ||
2564 | (17 << SPI_DEV_TYPE_SIZE_LBN) | ||
2565 | | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN) | ||
2566 | | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN) | ||
2567 | | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN) | ||
2568 | | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN); | ||
2569 | |||
2570 | falcon_spi_device_init(efx, &efx->spi_flash, | ||
2571 | EE_SPI_FLASH, flash_device_type); | ||
2572 | |||
2573 | if (!boot_is_external) { | ||
2574 | /* Disable VPD and set clock dividers to safe | ||
2575 | * values for initial programming. | ||
2576 | */ | ||
2577 | EFX_LOG(efx, "Booted from internal ASIC settings;" | ||
2578 | " setting SPI config\n"); | ||
2579 | EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0, | ||
2580 | /* 125 MHz / 7 ~= 20 MHz */ | ||
2581 | EE_SF_CLOCK_DIV, 7, | ||
2582 | /* 125 MHz / 63 ~= 2 MHz */ | ||
2583 | EE_EE_CLOCK_DIV, 63); | ||
2584 | falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); | ||
2585 | } | ||
2586 | } | ||
2587 | |||
2588 | if (has_eeprom) { | ||
2589 | u32 eeprom_device_type; | ||
2590 | |||
2591 | /* If it has no flash, it must have a large EEPROM | ||
2592 | * for chip config; otherwise check whether 9-bit | ||
2593 | * addressing is used for VPD configuration | ||
2594 | */ | ||
2595 | if (has_flash && | ||
2596 | (!boot_is_external || | ||
2597 | EFX_OWORD_FIELD(ee_vpd_cfg, EE_VPD_EN_AD9_MODE))) { | ||
2598 | /* Default SPI device: Atmel AT25040 or similar | ||
2599 | * 512 B, 9-bit address, 8 B write block | ||
2600 | */ | ||
2601 | eeprom_device_type = | ||
2602 | (9 << SPI_DEV_TYPE_SIZE_LBN) | ||
2603 | | (1 << SPI_DEV_TYPE_ADDR_LEN_LBN) | ||
2604 | | (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN); | ||
2605 | } else { | ||
2606 | /* "Large" SPI device: Atmel AT25640 or similar | ||
2607 | * 8 KB, 16-bit address, 32 B write block | ||
2608 | */ | ||
2609 | eeprom_device_type = | ||
2610 | (13 << SPI_DEV_TYPE_SIZE_LBN) | ||
2611 | | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN) | ||
2612 | | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN); | ||
2613 | } | ||
2614 | |||
2615 | falcon_spi_device_init(efx, &efx->spi_eeprom, | ||
2616 | EE_SPI_EEPROM, eeprom_device_type); | ||
2617 | } | ||
2618 | |||
2619 | EFX_LOG(efx, "flash is %s, EEPROM is %s\n", | ||
2620 | (has_flash ? "present" : "absent"), | ||
2621 | (has_eeprom ? "present" : "absent")); | ||
2622 | } | ||
2623 | |||
2366 | int falcon_probe_nic(struct efx_nic *efx) | 2624 | int falcon_probe_nic(struct efx_nic *efx) |
2367 | { | 2625 | { |
2368 | struct falcon_nic_data *nic_data; | 2626 | struct falcon_nic_data *nic_data; |
@@ -2413,6 +2671,8 @@ int falcon_probe_nic(struct efx_nic *efx) | |||
2413 | (unsigned long long)efx->irq_status.dma_addr, | 2671 | (unsigned long long)efx->irq_status.dma_addr, |
2414 | efx->irq_status.addr, virt_to_phys(efx->irq_status.addr)); | 2672 | efx->irq_status.addr, virt_to_phys(efx->irq_status.addr)); |
2415 | 2673 | ||
2674 | falcon_probe_spi_devices(efx); | ||
2675 | |||
2416 | /* Read in the non-volatile configuration */ | 2676 | /* Read in the non-volatile configuration */ |
2417 | rc = falcon_probe_nvconfig(efx); | 2677 | rc = falcon_probe_nvconfig(efx); |
2418 | if (rc) | 2678 | if (rc) |
@@ -2432,6 +2692,7 @@ int falcon_probe_nic(struct efx_nic *efx) | |||
2432 | return 0; | 2692 | return 0; |
2433 | 2693 | ||
2434 | fail5: | 2694 | fail5: |
2695 | falcon_remove_spi_devices(efx); | ||
2435 | falcon_free_buffer(efx, &efx->irq_status); | 2696 | falcon_free_buffer(efx, &efx->irq_status); |
2436 | fail4: | 2697 | fail4: |
2437 | fail3: | 2698 | fail3: |
@@ -2608,6 +2869,7 @@ void falcon_remove_nic(struct efx_nic *efx) | |||
2608 | rc = i2c_del_adapter(&efx->i2c_adap); | 2869 | rc = i2c_del_adapter(&efx->i2c_adap); |
2609 | BUG_ON(rc); | 2870 | BUG_ON(rc); |
2610 | 2871 | ||
2872 | falcon_remove_spi_devices(efx); | ||
2611 | falcon_free_buffer(efx, &efx->irq_status); | 2873 | falcon_free_buffer(efx, &efx->irq_status); |
2612 | 2874 | ||
2613 | falcon_reset_hw(efx, RESET_TYPE_ALL); | 2875 | falcon_reset_hw(efx, RESET_TYPE_ALL); |
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index 6d003114eeab..626735e73429 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h | |||
@@ -92,6 +92,17 @@ | |||
92 | /* SPI host data register */ | 92 | /* SPI host data register */ |
93 | #define EE_SPI_HDATA_REG_KER 0x0120 | 93 | #define EE_SPI_HDATA_REG_KER 0x0120 |
94 | 94 | ||
95 | /* SPI/VPD config register */ | ||
96 | #define EE_VPD_CFG_REG_KER 0x0140 | ||
97 | #define EE_VPD_EN_LBN 0 | ||
98 | #define EE_VPD_EN_WIDTH 1 | ||
99 | #define EE_VPD_EN_AD9_MODE_LBN 1 | ||
100 | #define EE_VPD_EN_AD9_MODE_WIDTH 1 | ||
101 | #define EE_EE_CLOCK_DIV_LBN 112 | ||
102 | #define EE_EE_CLOCK_DIV_WIDTH 7 | ||
103 | #define EE_SF_CLOCK_DIV_LBN 120 | ||
104 | #define EE_SF_CLOCK_DIV_WIDTH 7 | ||
105 | |||
95 | /* PCIE CORE ACCESS REG */ | 106 | /* PCIE CORE ACCESS REG */ |
96 | #define PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT 0x68 | 107 | #define PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT 0x68 |
97 | #define PCIE_CORE_ADDR_PCIE_LINK_CTRL_STAT 0x70 | 108 | #define PCIE_CORE_ADDR_PCIE_LINK_CTRL_STAT 0x70 |
@@ -115,6 +126,9 @@ | |||
115 | #define STRAP_PCIE_LBN 0 | 126 | #define STRAP_PCIE_LBN 0 |
116 | #define STRAP_PCIE_WIDTH 1 | 127 | #define STRAP_PCIE_WIDTH 1 |
117 | 128 | ||
129 | #define BOOTED_USING_NVDEVICE_LBN 3 | ||
130 | #define BOOTED_USING_NVDEVICE_WIDTH 1 | ||
131 | |||
118 | /* GPIO control register */ | 132 | /* GPIO control register */ |
119 | #define GPIO_CTL_REG_KER 0x0210 | 133 | #define GPIO_CTL_REG_KER 0x0210 |
120 | #define GPIO_OUTPUTS_LBN (16) | 134 | #define GPIO_OUTPUTS_LBN (16) |
@@ -1127,6 +1141,25 @@ struct falcon_nvconfig_board_v2 { | |||
1127 | __le16 board_revision; | 1141 | __le16 board_revision; |
1128 | } __packed; | 1142 | } __packed; |
1129 | 1143 | ||
1144 | /* Board configuration v3 extra information */ | ||
1145 | struct falcon_nvconfig_board_v3 { | ||
1146 | __le32 spi_device_type[2]; | ||
1147 | } __packed; | ||
1148 | |||
1149 | /* Bit numbers for spi_device_type */ | ||
1150 | #define SPI_DEV_TYPE_SIZE_LBN 0 | ||
1151 | #define SPI_DEV_TYPE_SIZE_WIDTH 5 | ||
1152 | #define SPI_DEV_TYPE_ADDR_LEN_LBN 6 | ||
1153 | #define SPI_DEV_TYPE_ADDR_LEN_WIDTH 2 | ||
1154 | #define SPI_DEV_TYPE_ERASE_CMD_LBN 8 | ||
1155 | #define SPI_DEV_TYPE_ERASE_CMD_WIDTH 8 | ||
1156 | #define SPI_DEV_TYPE_ERASE_SIZE_LBN 16 | ||
1157 | #define SPI_DEV_TYPE_ERASE_SIZE_WIDTH 5 | ||
1158 | #define SPI_DEV_TYPE_BLOCK_SIZE_LBN 24 | ||
1159 | #define SPI_DEV_TYPE_BLOCK_SIZE_WIDTH 5 | ||
1160 | #define SPI_DEV_TYPE_FIELD(type, field) \ | ||
1161 | (((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(field)) | ||
1162 | |||
1130 | #define NVCONFIG_BASE 0x300 | 1163 | #define NVCONFIG_BASE 0x300 |
1131 | #define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C | 1164 | #define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C |
1132 | struct falcon_nvconfig { | 1165 | struct falcon_nvconfig { |
@@ -1144,6 +1177,8 @@ struct falcon_nvconfig { | |||
1144 | __le16 board_struct_ver; | 1177 | __le16 board_struct_ver; |
1145 | __le16 board_checksum; | 1178 | __le16 board_checksum; |
1146 | struct falcon_nvconfig_board_v2 board_v2; | 1179 | struct falcon_nvconfig_board_v2 board_v2; |
1180 | efx_oword_t ee_base_page_reg; /* 0x3B0 */ | ||
1181 | struct falcon_nvconfig_board_v3 board_v3; | ||
1147 | } __packed; | 1182 | } __packed; |
1148 | 1183 | ||
1149 | #endif /* EFX_FALCON_HWDEFS_H */ | 1184 | #endif /* EFX_FALCON_HWDEFS_H */ |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 1b92186bec5a..390275710ef4 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -638,6 +638,10 @@ union efx_multicast_hash { | |||
638 | * This register is written with the SMP processor ID whenever an | 638 | * This register is written with the SMP processor ID whenever an |
639 | * interrupt is handled. It is used by falcon_test_interrupt() | 639 | * interrupt is handled. It is used by falcon_test_interrupt() |
640 | * to verify that an interrupt has occurred. | 640 | * to verify that an interrupt has occurred. |
641 | * @spi_flash: SPI flash device | ||
642 | * This field will be %NULL if no flash device is present. | ||
643 | * @spi_eeprom: SPI EEPROM device | ||
644 | * This field will be %NULL if no EEPROM device is present. | ||
641 | * @n_rx_nodesc_drop_cnt: RX no descriptor drop count | 645 | * @n_rx_nodesc_drop_cnt: RX no descriptor drop count |
642 | * @nic_data: Hardware dependant state | 646 | * @nic_data: Hardware dependant state |
643 | * @mac_lock: MAC access lock. Protects @port_enabled, efx_monitor() and | 647 | * @mac_lock: MAC access lock. Protects @port_enabled, efx_monitor() and |
@@ -709,6 +713,9 @@ struct efx_nic { | |||
709 | struct efx_buffer irq_status; | 713 | struct efx_buffer irq_status; |
710 | volatile signed int last_irq_cpu; | 714 | volatile signed int last_irq_cpu; |
711 | 715 | ||
716 | struct efx_spi_device *spi_flash; | ||
717 | struct efx_spi_device *spi_eeprom; | ||
718 | |||
712 | unsigned n_rx_nodesc_drop_cnt; | 719 | unsigned n_rx_nodesc_drop_cnt; |
713 | 720 | ||
714 | struct falcon_nic_data *nic_data; | 721 | struct falcon_nic_data *nic_data; |
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h index 34412f3d41c9..feef61942377 100644 --- a/drivers/net/sfc/spi.h +++ b/drivers/net/sfc/spi.h | |||
@@ -19,53 +19,48 @@ | |||
19 | * | 19 | * |
20 | *************************************************************************/ | 20 | *************************************************************************/ |
21 | 21 | ||
22 | /* | 22 | #define SPI_WRSR 0x01 /* Write status register */ |
23 | * Commands common to all known devices. | 23 | #define SPI_WRITE 0x02 /* Write data to memory array */ |
24 | * | 24 | #define SPI_READ 0x03 /* Read data from memory array */ |
25 | #define SPI_WRDI 0x04 /* Reset write enable latch */ | ||
26 | #define SPI_RDSR 0x05 /* Read status register */ | ||
27 | #define SPI_WREN 0x06 /* Set write enable latch */ | ||
28 | |||
29 | #define SPI_STATUS_WPEN 0x80 /* Write-protect pin enabled */ | ||
30 | #define SPI_STATUS_BP2 0x10 /* Block protection bit 2 */ | ||
31 | #define SPI_STATUS_BP1 0x08 /* Block protection bit 1 */ | ||
32 | #define SPI_STATUS_BP0 0x04 /* Block protection bit 0 */ | ||
33 | #define SPI_STATUS_WEN 0x02 /* State of the write enable latch */ | ||
34 | #define SPI_STATUS_NRDY 0x01 /* Device busy flag */ | ||
35 | |||
36 | /** | ||
37 | * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device | ||
38 | * @efx: The Efx controller that owns this device | ||
39 | * @device_id: Controller's id for the device | ||
40 | * @size: Size (in bytes) | ||
41 | * @addr_len: Number of address bytes in read/write commands | ||
42 | * @munge_address: Flag whether addresses should be munged. | ||
43 | * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) | ||
44 | * use bit 3 of the command byte as address bit A8, rather | ||
45 | * than having a two-byte address. If this flag is set, then | ||
46 | * commands should be munged in this way. | ||
47 | * @block_size: Write block size (in bytes). | ||
48 | * Write commands are limited to blocks with this size and alignment. | ||
49 | * @read: Read function for the device | ||
50 | * @write: Write function for the device | ||
25 | */ | 51 | */ |
26 | 52 | struct efx_spi_device { | |
27 | /* Write status register */ | 53 | struct efx_nic *efx; |
28 | #define SPI_WRSR 0x01 | 54 | int device_id; |
29 | 55 | unsigned int size; | |
30 | /* Write data to memory array */ | 56 | unsigned int addr_len; |
31 | #define SPI_WRITE 0x02 | 57 | unsigned int munge_address:1; |
32 | 58 | unsigned int block_size; | |
33 | /* Read data from memory array */ | 59 | }; |
34 | #define SPI_READ 0x03 | 60 | |
35 | 61 | int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, | |
36 | /* Reset write enable latch */ | 62 | size_t len, size_t *retlen, u8 *buffer); |
37 | #define SPI_WRDI 0x04 | 63 | int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, |
38 | 64 | size_t len, size_t *retlen, const u8 *buffer); | |
39 | /* Read status register */ | ||
40 | #define SPI_RDSR 0x05 | ||
41 | |||
42 | /* Set write enable latch */ | ||
43 | #define SPI_WREN 0x06 | ||
44 | |||
45 | /* SST: Enable write to status register */ | ||
46 | #define SPI_SST_EWSR 0x50 | ||
47 | |||
48 | /* | ||
49 | * Status register bits. Not all bits are supported on all devices. | ||
50 | * | ||
51 | */ | ||
52 | |||
53 | /* Write-protect pin enabled */ | ||
54 | #define SPI_STATUS_WPEN 0x80 | ||
55 | |||
56 | /* Block protection bit 2 */ | ||
57 | #define SPI_STATUS_BP2 0x10 | ||
58 | |||
59 | /* Block protection bit 1 */ | ||
60 | #define SPI_STATUS_BP1 0x08 | ||
61 | |||
62 | /* Block protection bit 0 */ | ||
63 | #define SPI_STATUS_BP0 0x04 | ||
64 | |||
65 | /* State of the write enable latch */ | ||
66 | #define SPI_STATUS_WEN 0x02 | ||
67 | |||
68 | /* Device busy flag */ | ||
69 | #define SPI_STATUS_NRDY 0x01 | ||
70 | 65 | ||
71 | #endif /* EFX_SPI_H */ | 66 | #endif /* EFX_SPI_H */ |