aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-11-04 15:34:28 -0500
committerJeff Garzik <jgarzik@redhat.com>2008-11-06 00:49:57 -0500
commitf41507245ef8b079685aba8da5b5b2b5e87e70bc (patch)
treebe8c8aee6a6fc3c69d946dcd3fe24306bf89775e /drivers
parent0a95f56323ce93dac354c1b2d54bf959a985cf7d (diff)
sfc: Expose flash region storing boot code as MTD
The boot code that appears as a PCI expansion ROM on the SFC4000 is stored in flash. Expose this as a standard MTD device to allow for in-place upgrades. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/Kconfig8
-rw-r--r--drivers/net/sfc/Makefile1
-rw-r--r--drivers/net/sfc/efx.c7
-rw-r--r--drivers/net/sfc/efx.h10
-rw-r--r--drivers/net/sfc/ethtool.c4
-rw-r--r--drivers/net/sfc/falcon.c17
-rw-r--r--drivers/net/sfc/mtd.c268
-rw-r--r--drivers/net/sfc/net_driver.h2
-rw-r--r--drivers/net/sfc/spi.h17
9 files changed, 327 insertions, 7 deletions
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig
index 3be13b592b4d..3e25fb38f739 100644
--- a/drivers/net/sfc/Kconfig
+++ b/drivers/net/sfc/Kconfig
@@ -12,3 +12,11 @@ config SFC
12 12
13 To compile this driver as a module, choose M here. The module 13 To compile this driver as a module, choose M here. The module
14 will be called sfc. 14 will be called sfc.
15config SFC_MTD
16 bool "Solarflare Solarstorm SFC4000 flash MTD support"
17 depends on SFC && MTD
18 default y
19 help
20 This exposes the on-board flash memory as an MTD device (e.g.
21 /dev/mtd1). This makes it possible to upload new boot code
22 to the NIC.
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index c8f5704c8fb1..e507daa4f0e8 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,5 +1,6 @@
1sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ 1sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \
2 selftest.o ethtool.o xfp_phy.o \ 2 selftest.o ethtool.o xfp_phy.o \
3 mdio_10g.o tenxpress.o boards.o sfe4001.o 3 mdio_10g.o tenxpress.o boards.o sfe4001.o
4sfc-$(CONFIG_SFC_MTD) += mtd.o
4 5
5obj-$(CONFIG_SFC) += sfc.o 6obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 5b05789f0b79..f9139377989f 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1459,6 +1459,7 @@ static int efx_netdev_event(struct notifier_block *this,
1459 struct efx_nic *efx = netdev_priv(net_dev); 1459 struct efx_nic *efx = netdev_priv(net_dev);
1460 1460
1461 strcpy(efx->name, net_dev->name); 1461 strcpy(efx->name, net_dev->name);
1462 efx_mtd_rename(efx);
1462 } 1463 }
1463 1464
1464 return NOTIFY_DONE; 1465 return NOTIFY_DONE;
@@ -1550,6 +1551,7 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
1550 1551
1551 efx_stop_all(efx); 1552 efx_stop_all(efx);
1552 mutex_lock(&efx->mac_lock); 1553 mutex_lock(&efx->mac_lock);
1554 mutex_lock(&efx->spi_lock);
1553 1555
1554 rc = falcon_xmac_get_settings(efx, ecmd); 1556 rc = falcon_xmac_get_settings(efx, ecmd);
1555 if (rc) 1557 if (rc)
@@ -1582,6 +1584,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
1582 EFX_ERR(efx, "could not restore PHY settings\n"); 1584 EFX_ERR(efx, "could not restore PHY settings\n");
1583 } 1585 }
1584 1586
1587 mutex_unlock(&efx->spi_lock);
1585 mutex_unlock(&efx->mac_lock); 1588 mutex_unlock(&efx->mac_lock);
1586 1589
1587 if (ok) { 1590 if (ok) {
@@ -1777,6 +1780,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
1777 memset(efx, 0, sizeof(*efx)); 1780 memset(efx, 0, sizeof(*efx));
1778 spin_lock_init(&efx->biu_lock); 1781 spin_lock_init(&efx->biu_lock);
1779 spin_lock_init(&efx->phy_lock); 1782 spin_lock_init(&efx->phy_lock);
1783 mutex_init(&efx->spi_lock);
1780 INIT_WORK(&efx->reset_work, efx_reset_work); 1784 INIT_WORK(&efx->reset_work, efx_reset_work);
1781 INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor); 1785 INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
1782 efx->pci_dev = pci_dev; 1786 efx->pci_dev = pci_dev;
@@ -1911,6 +1915,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
1911 if (!efx) 1915 if (!efx)
1912 return; 1916 return;
1913 1917
1918 efx_mtd_remove(efx);
1919
1914 /* Mark the NIC as fini, then stop the interface */ 1920 /* Mark the NIC as fini, then stop the interface */
1915 rtnl_lock(); 1921 rtnl_lock();
1916 efx->state = STATE_FINI; 1922 efx->state = STATE_FINI;
@@ -2077,6 +2083,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
2077 2083
2078 EFX_LOG(efx, "initialisation successful\n"); 2084 EFX_LOG(efx, "initialisation successful\n");
2079 2085
2086 efx_mtd_probe(efx); /* allowed to fail */
2080 return 0; 2087 return 0;
2081 2088
2082 fail5: 2089 fail5:
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index d02937b70eee..dd0d45b9e71f 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -58,6 +58,16 @@ extern int efx_port_dummy_op_int(struct efx_nic *efx);
58extern void efx_port_dummy_op_void(struct efx_nic *efx); 58extern void efx_port_dummy_op_void(struct efx_nic *efx);
59extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink); 59extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink);
60 60
61/* MTD */
62#ifdef CONFIG_SFC_MTD
63extern int efx_mtd_probe(struct efx_nic *efx);
64extern void efx_mtd_rename(struct efx_nic *efx);
65extern void efx_mtd_remove(struct efx_nic *efx);
66#else
67static inline int efx_mtd_probe(struct efx_nic *efx) { return 0; }
68static inline void efx_mtd_rename(struct efx_nic *efx) {}
69static inline void efx_mtd_remove(struct efx_nic *efx) {}
70#endif
61 71
62extern unsigned int efx_monitor_interval; 72extern unsigned int efx_monitor_interval;
63 73
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index df0579e386f7..abd8fcd6e62d 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -554,8 +554,10 @@ static int efx_ethtool_get_eeprom(struct net_device *net_dev,
554 size_t len; 554 size_t len;
555 int rc; 555 int rc;
556 556
557 mutex_lock(&efx->spi_lock);
557 rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, 558 rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
558 eeprom->len, &len, buf); 559 eeprom->len, &len, buf);
560 mutex_unlock(&efx->spi_lock);
559 eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC; 561 eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
560 eeprom->len = len; 562 eeprom->len = len;
561 return rc; 563 return rc;
@@ -572,8 +574,10 @@ static int efx_ethtool_set_eeprom(struct net_device *net_dev,
572 if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC) 574 if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
573 return -EINVAL; 575 return -EINVAL;
574 576
577 mutex_lock(&efx->spi_lock);
575 rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, 578 rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
576 eeprom->len, &len, buf); 579 eeprom->len, &len, buf);
580 mutex_unlock(&efx->spi_lock);
577 eeprom->len = len; 581 eeprom->len = len;
578 return rc; 582 return rc;
579} 583}
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 3f74ceff6a2e..71e0bed60616 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1628,9 +1628,9 @@ static int falcon_spi_wait(struct efx_nic *efx)
1628 } 1628 }
1629} 1629}
1630 1630
1631static int falcon_spi_cmd(const struct efx_spi_device *spi, 1631int falcon_spi_cmd(const struct efx_spi_device *spi,
1632 unsigned int command, int address, 1632 unsigned int command, int address,
1633 const void *in, void *out, unsigned int len) 1633 const void *in, void *out, unsigned int len)
1634{ 1634{
1635 struct efx_nic *efx = spi->efx; 1635 struct efx_nic *efx = spi->efx;
1636 bool addressed = (address >= 0); 1636 bool addressed = (address >= 0);
@@ -1641,6 +1641,7 @@ static int falcon_spi_cmd(const struct efx_spi_device *spi,
1641 /* Input validation */ 1641 /* Input validation */
1642 if (len > FALCON_SPI_MAX_LEN) 1642 if (len > FALCON_SPI_MAX_LEN)
1643 return -EINVAL; 1643 return -EINVAL;
1644 BUG_ON(!mutex_is_locked(&efx->spi_lock));
1644 1645
1645 /* Check SPI not currently being accessed */ 1646 /* Check SPI not currently being accessed */
1646 rc = falcon_spi_wait(efx); 1647 rc = falcon_spi_wait(efx);
@@ -1699,8 +1700,7 @@ efx_spi_munge_command(const struct efx_spi_device *spi,
1699 return command | (((address >> 8) & spi->munge_address) << 3); 1700 return command | (((address >> 8) & spi->munge_address) << 3);
1700} 1701}
1701 1702
1702 1703int falcon_spi_fast_wait(const struct efx_spi_device *spi)
1703static int falcon_spi_fast_wait(const struct efx_spi_device *spi)
1704{ 1704{
1705 u8 status; 1705 u8 status;
1706 int i, rc; 1706 int i, rc;
@@ -2259,7 +2259,9 @@ int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
2259 nvconfig = region + NVCONFIG_OFFSET; 2259 nvconfig = region + NVCONFIG_OFFSET;
2260 2260
2261 spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom; 2261 spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
2262 mutex_lock(&efx->spi_lock);
2262 rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region); 2263 rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region);
2264 mutex_unlock(&efx->spi_lock);
2263 if (rc) { 2265 if (rc) {
2264 EFX_ERR(efx, "Failed to read %s\n", 2266 EFX_ERR(efx, "Failed to read %s\n",
2265 efx->spi_flash ? "flash" : "EEPROM"); 2267 efx->spi_flash ? "flash" : "EEPROM");
@@ -2555,6 +2557,11 @@ static int falcon_spi_device_init(struct efx_nic *efx,
2555 SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN); 2557 SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN);
2556 spi_device->munge_address = (spi_device->size == 1 << 9 && 2558 spi_device->munge_address = (spi_device->size == 1 << 9 &&
2557 spi_device->addr_len == 1); 2559 spi_device->addr_len == 1);
2560 spi_device->erase_command =
2561 SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ERASE_CMD);
2562 spi_device->erase_size =
2563 1 << SPI_DEV_TYPE_FIELD(device_type,
2564 SPI_DEV_TYPE_ERASE_SIZE);
2558 spi_device->block_size = 2565 spi_device->block_size =
2559 1 << SPI_DEV_TYPE_FIELD(device_type, 2566 1 << SPI_DEV_TYPE_FIELD(device_type,
2560 SPI_DEV_TYPE_BLOCK_SIZE); 2567 SPI_DEV_TYPE_BLOCK_SIZE);
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c
new file mode 100644
index 000000000000..a1e6c2875fc0
--- /dev/null
+++ b/drivers/net/sfc/mtd.c
@@ -0,0 +1,268 @@
1/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2005-2006 Fen Systems Ltd.
4 * Copyright 2006-2008 Solarflare Communications Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation, incorporated herein by reference.
9 */
10
11#include <linux/module.h>
12#include <linux/mtd/mtd.h>
13#include <linux/delay.h>
14
15#define EFX_DRIVER_NAME "sfc_mtd"
16#include "net_driver.h"
17#include "spi.h"
18
19#define EFX_SPI_VERIFY_BUF_LEN 16
20
21struct efx_mtd {
22 const struct efx_spi_device *spi;
23 struct mtd_info mtd;
24 char name[IFNAMSIZ + 20];
25};
26
27/* SPI utilities */
28
29static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible)
30{
31 const struct efx_spi_device *spi = efx_mtd->spi;
32 struct efx_nic *efx = spi->efx;
33 u8 status;
34 int rc, i;
35
36 /* Wait up to 4s for flash/EEPROM to finish a slow operation. */
37 for (i = 0; i < 40; i++) {
38 __set_current_state(uninterruptible ?
39 TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
40 schedule_timeout(HZ / 10);
41 rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
42 &status, sizeof(status));
43 if (rc)
44 return rc;
45 if (!(status & SPI_STATUS_NRDY))
46 return 0;
47 if (signal_pending(current))
48 return -EINTR;
49 }
50 EFX_ERR(efx, "timed out waiting for %s\n", efx_mtd->name);
51 return -ETIMEDOUT;
52}
53
54static int efx_spi_unlock(const struct efx_spi_device *spi)
55{
56 const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
57 SPI_STATUS_BP0);
58 u8 status;
59 int rc;
60
61 rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status));
62 if (rc)
63 return rc;
64
65 if (!(status & unlock_mask))
66 return 0; /* already unlocked */
67
68 rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
69 if (rc)
70 return rc;
71 rc = falcon_spi_cmd(spi, SPI_SST_EWSR, -1, NULL, NULL, 0);
72 if (rc)
73 return rc;
74
75 status &= ~unlock_mask;
76 rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status));
77 if (rc)
78 return rc;
79 rc = falcon_spi_fast_wait(spi);
80 if (rc)
81 return rc;
82
83 return 0;
84}
85
86static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len)
87{
88 const struct efx_spi_device *spi = efx_mtd->spi;
89 unsigned pos, block_len;
90 u8 empty[EFX_SPI_VERIFY_BUF_LEN];
91 u8 buffer[EFX_SPI_VERIFY_BUF_LEN];
92 int rc;
93
94 if (len != spi->erase_size)
95 return -EINVAL;
96
97 if (spi->erase_command == 0)
98 return -EOPNOTSUPP;
99
100 rc = efx_spi_unlock(spi);
101 if (rc)
102 return rc;
103 rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
104 if (rc)
105 return rc;
106 rc = falcon_spi_cmd(spi, spi->erase_command, start, NULL, NULL, 0);
107 if (rc)
108 return rc;
109 rc = efx_spi_slow_wait(efx_mtd, false);
110
111 /* Verify the entire region has been wiped */
112 memset(empty, 0xff, sizeof(empty));
113 for (pos = 0; pos < len; pos += block_len) {
114 block_len = min(len - pos, sizeof(buffer));
115 rc = falcon_spi_read(spi, start + pos, block_len, NULL, buffer);
116 if (rc)
117 return rc;
118 if (memcmp(empty, buffer, block_len))
119 return -EIO;
120
121 /* Avoid locking up the system */
122 cond_resched();
123 if (signal_pending(current))
124 return -EINTR;
125 }
126
127 return rc;
128}
129
130/* MTD interface */
131
132static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len,
133 size_t *retlen, u8 *buffer)
134{
135 struct efx_mtd *efx_mtd = mtd->priv;
136 const struct efx_spi_device *spi = efx_mtd->spi;
137 struct efx_nic *efx = spi->efx;
138 int rc;
139
140 rc = mutex_lock_interruptible(&efx->spi_lock);
141 if (rc)
142 return rc;
143 rc = falcon_spi_read(spi, FALCON_FLASH_BOOTCODE_START + start,
144 len, retlen, buffer);
145 mutex_unlock(&efx->spi_lock);
146 return rc;
147}
148
149static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
150{
151 struct efx_mtd *efx_mtd = mtd->priv;
152 struct efx_nic *efx = efx_mtd->spi->efx;
153 int rc;
154
155 rc = mutex_lock_interruptible(&efx->spi_lock);
156 if (rc)
157 return rc;
158 rc = efx_spi_erase(efx_mtd, FALCON_FLASH_BOOTCODE_START + erase->addr,
159 erase->len);
160 mutex_unlock(&efx->spi_lock);
161
162 if (rc == 0) {
163 erase->state = MTD_ERASE_DONE;
164 } else {
165 erase->state = MTD_ERASE_FAILED;
166 erase->fail_addr = 0xffffffff;
167 }
168 mtd_erase_callback(erase);
169 return rc;
170}
171
172static int efx_mtd_write(struct mtd_info *mtd, loff_t start,
173 size_t len, size_t *retlen, const u8 *buffer)
174{
175 struct efx_mtd *efx_mtd = mtd->priv;
176 const struct efx_spi_device *spi = efx_mtd->spi;
177 struct efx_nic *efx = spi->efx;
178 int rc;
179
180 rc = mutex_lock_interruptible(&efx->spi_lock);
181 if (rc)
182 return rc;
183 rc = falcon_spi_write(spi, FALCON_FLASH_BOOTCODE_START + start,
184 len, retlen, buffer);
185 mutex_unlock(&efx->spi_lock);
186 return rc;
187}
188
189static void efx_mtd_sync(struct mtd_info *mtd)
190{
191 struct efx_mtd *efx_mtd = mtd->priv;
192 struct efx_nic *efx = efx_mtd->spi->efx;
193 int rc;
194
195 mutex_lock(&efx->spi_lock);
196 rc = efx_spi_slow_wait(efx_mtd, true);
197 mutex_unlock(&efx->spi_lock);
198
199 if (rc)
200 EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc);
201 return;
202}
203
204void efx_mtd_remove(struct efx_nic *efx)
205{
206 if (efx->spi_flash && efx->spi_flash->mtd) {
207 struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
208 int rc;
209
210 for (;;) {
211 rc = del_mtd_device(&efx_mtd->mtd);
212 if (rc != -EBUSY)
213 break;
214 ssleep(1);
215 }
216 WARN_ON(rc);
217 kfree(efx_mtd);
218 }
219}
220
221void efx_mtd_rename(struct efx_nic *efx)
222{
223 if (efx->spi_flash && efx->spi_flash->mtd) {
224 struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
225 snprintf(efx_mtd->name, sizeof(efx_mtd->name),
226 "%s sfc_flash_bootrom", efx->name);
227 }
228}
229
230int efx_mtd_probe(struct efx_nic *efx)
231{
232 struct efx_spi_device *spi = efx->spi_flash;
233 struct efx_mtd *efx_mtd;
234
235 if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START)
236 return -ENODEV;
237
238 efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL);
239 if (!efx_mtd)
240 return -ENOMEM;
241
242 efx_mtd->spi = spi;
243 spi->mtd = efx_mtd;
244
245 efx_mtd->mtd.type = MTD_NORFLASH;
246 efx_mtd->mtd.flags = MTD_CAP_NORFLASH;
247 efx_mtd->mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
248 efx_mtd->mtd.erasesize = spi->erase_size;
249 efx_mtd->mtd.writesize = 1;
250 efx_mtd_rename(efx);
251
252 efx_mtd->mtd.owner = THIS_MODULE;
253 efx_mtd->mtd.priv = efx_mtd;
254 efx_mtd->mtd.name = efx_mtd->name;
255 efx_mtd->mtd.erase = efx_mtd_erase;
256 efx_mtd->mtd.read = efx_mtd_read;
257 efx_mtd->mtd.write = efx_mtd_write;
258 efx_mtd->mtd.sync = efx_mtd_sync;
259
260 if (add_mtd_device(&efx_mtd->mtd)) {
261 kfree(efx_mtd);
262 spi->mtd = NULL;
263 /* add_mtd_device() returns 1 if the MTD table is full */
264 return -ENOMEM;
265 }
266
267 return 0;
268}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index cdb11fad6050..c953eb19df42 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -655,6 +655,7 @@ union efx_multicast_hash {
655 * This field will be %NULL if no flash device is present. 655 * This field will be %NULL if no flash device is present.
656 * @spi_eeprom: SPI EEPROM device 656 * @spi_eeprom: SPI EEPROM device
657 * This field will be %NULL if no EEPROM device is present. 657 * This field will be %NULL if no EEPROM device is present.
658 * @spi_lock: SPI bus lock
658 * @n_rx_nodesc_drop_cnt: RX no descriptor drop count 659 * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
659 * @nic_data: Hardware dependant state 660 * @nic_data: Hardware dependant state
660 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, 661 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
@@ -731,6 +732,7 @@ struct efx_nic {
731 732
732 struct efx_spi_device *spi_flash; 733 struct efx_spi_device *spi_flash;
733 struct efx_spi_device *spi_eeprom; 734 struct efx_spi_device *spi_eeprom;
735 struct mutex spi_lock;
734 736
735 unsigned n_rx_nodesc_drop_cnt; 737 unsigned n_rx_nodesc_drop_cnt;
736 738
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h
index b73f86cf5fa2..c4aca132348a 100644
--- a/drivers/net/sfc/spi.h
+++ b/drivers/net/sfc/spi.h
@@ -25,6 +25,7 @@
25#define SPI_WRDI 0x04 /* Reset write enable latch */ 25#define SPI_WRDI 0x04 /* Reset write enable latch */
26#define SPI_RDSR 0x05 /* Read status register */ 26#define SPI_RDSR 0x05 /* Read status register */
27#define SPI_WREN 0x06 /* Set write enable latch */ 27#define SPI_WREN 0x06 /* Set write enable latch */
28#define SPI_SST_EWSR 0x50 /* SST: Enable write to status register */
28 29
29#define SPI_STATUS_WPEN 0x80 /* Write-protect pin enabled */ 30#define SPI_STATUS_WPEN 0x80 /* Write-protect pin enabled */
30#define SPI_STATUS_BP2 0x10 /* Block protection bit 2 */ 31#define SPI_STATUS_BP2 0x10 /* Block protection bit 2 */
@@ -36,6 +37,7 @@
36/** 37/**
37 * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device 38 * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device
38 * @efx: The Efx controller that owns this device 39 * @efx: The Efx controller that owns this device
40 * @mtd: MTD state
39 * @device_id: Controller's id for the device 41 * @device_id: Controller's id for the device
40 * @size: Size (in bytes) 42 * @size: Size (in bytes)
41 * @addr_len: Number of address bytes in read/write commands 43 * @addr_len: Number of address bytes in read/write commands
@@ -44,20 +46,30 @@
44 * use bit 3 of the command byte as address bit A8, rather 46 * 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 47 * than having a two-byte address. If this flag is set, then
46 * commands should be munged in this way. 48 * commands should be munged in this way.
49 * @erase_command: Erase command (or 0 if sector erase not needed).
50 * @erase_size: Erase sector size (in bytes)
51 * Erase commands affect sectors with this size and alignment.
52 * This must be a power of two.
47 * @block_size: Write block size (in bytes). 53 * @block_size: Write block size (in bytes).
48 * Write commands are limited to blocks with this size and alignment. 54 * 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
51 */ 55 */
52struct efx_spi_device { 56struct efx_spi_device {
53 struct efx_nic *efx; 57 struct efx_nic *efx;
58#ifdef CONFIG_SFC_MTD
59 void *mtd;
60#endif
54 int device_id; 61 int device_id;
55 unsigned int size; 62 unsigned int size;
56 unsigned int addr_len; 63 unsigned int addr_len;
57 unsigned int munge_address:1; 64 unsigned int munge_address:1;
65 u8 erase_command;
66 unsigned int erase_size;
58 unsigned int block_size; 67 unsigned int block_size;
59}; 68};
60 69
70int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command,
71 int address, const void* in, void *out, unsigned int len);
72int falcon_spi_fast_wait(const struct efx_spi_device *spi);
61int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, 73int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
62 size_t len, size_t *retlen, u8 *buffer); 74 size_t len, size_t *retlen, u8 *buffer);
63int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, 75int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
@@ -77,6 +89,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
77 * be absent or truncated depending on the devices used. 89 * be absent or truncated depending on the devices used.
78 */ 90 */
79#define FALCON_NVCONFIG_END 0x400U 91#define FALCON_NVCONFIG_END 0x400U
92#define FALCON_FLASH_BOOTCODE_START 0x8000U
80#define EFX_EEPROM_BOOTCONFIG_START 0x800U 93#define EFX_EEPROM_BOOTCONFIG_START 0x800U
81#define EFX_EEPROM_BOOTCONFIG_END 0x1800U 94#define EFX_EEPROM_BOOTCONFIG_END 0x1800U
82 95