diff options
Diffstat (limited to 'drivers/net/sfc/mtd.c')
| -rw-r--r-- | drivers/net/sfc/mtd.c | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c deleted file mode 100644 index 820c233c3ea..00000000000 --- a/drivers/net/sfc/mtd.c +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#include <linux/module.h> -#include <linux/mtd/mtd.h> -#include <linux/delay.h> - -#define EFX_DRIVER_NAME "sfc_mtd" -#include "net_driver.h" -#include "spi.h" -#include "efx.h" - -#define EFX_SPI_VERIFY_BUF_LEN 16 - -struct efx_mtd { - const struct efx_spi_device *spi; - struct mtd_info mtd; - char name[IFNAMSIZ + 20]; -}; - -/* SPI utilities */ - -static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible) -{ - const struct efx_spi_device *spi = efx_mtd->spi; - struct efx_nic *efx = spi->efx; - u8 status; - int rc, i; - - /* Wait up to 4s for flash/EEPROM to finish a slow operation. */ - for (i = 0; i < 40; i++) { - __set_current_state(uninterruptible ? - TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); - rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, - &status, sizeof(status)); - if (rc) - return rc; - if (!(status & SPI_STATUS_NRDY)) - return 0; - if (signal_pending(current)) - return -EINTR; - } - EFX_ERR(efx, "timed out waiting for %s\n", efx_mtd->name); - return -ETIMEDOUT; -} - -static int efx_spi_unlock(const struct efx_spi_device *spi) -{ - const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 | - SPI_STATUS_BP0); - u8 status; - int rc; - - rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status)); - if (rc) - return rc; - - if (!(status & unlock_mask)) - return 0; /* already unlocked */ - - rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0); - if (rc) - return rc; - rc = falcon_spi_cmd(spi, SPI_SST_EWSR, -1, NULL, NULL, 0); - if (rc) - return rc; - - status &= ~unlock_mask; - rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status)); - if (rc) - return rc; - rc = falcon_spi_wait_write(spi); - if (rc) - return rc; - - return 0; -} - -static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len) -{ - const struct efx_spi_device *spi = efx_mtd->spi; - unsigned pos, block_len; - u8 empty[EFX_SPI_VERIFY_BUF_LEN]; - u8 buffer[EFX_SPI_VERIFY_BUF_LEN]; - int rc; - - if (len != spi->erase_size) - return -EINVAL; - - if (spi->erase_command == 0) - return -EOPNOTSUPP; - - rc = efx_spi_unlock(spi); - if (rc) - return rc; - rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0); - if (rc) - return rc; - rc = falcon_spi_cmd(spi, spi->erase_command, start, NULL, NULL, 0); - if (rc) - return rc; - rc = efx_spi_slow_wait(efx_mtd, false); - - /* Verify the entire region has been wiped */ - memset(empty, 0xff, sizeof(empty)); - for (pos = 0; pos < len; pos += block_len) { - block_len = min(len - pos, sizeof(buffer)); - rc = falcon_spi_read(spi, start + pos, block_len, NULL, buffer); - if (rc) - return rc; - if (memcmp(empty, buffer, block_len)) - return -EIO; - - /* Avoid locking up the system */ - cond_resched(); - if (signal_pending(current)) - return -EINTR; - } - - return rc; -} - -/* MTD interface */ - -static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len, - size_t *retlen, u8 *buffer) -{ - struct efx_mtd *efx_mtd = mtd->priv; - const struct efx_spi_device *spi = efx_mtd->spi; - struct efx_nic *efx = spi->efx; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_read(spi, FALCON_FLASH_BOOTCODE_START + start, - len, retlen, buffer); - mutex_unlock(&efx->spi_lock); - return rc; -} - -static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) -{ - struct efx_mtd *efx_mtd = mtd->priv; - struct efx_nic *efx = efx_mtd->spi->efx; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = efx_spi_erase(efx_mtd, FALCON_FLASH_BOOTCODE_START + erase->addr, - erase->len); - mutex_unlock(&efx->spi_lock); - - if (rc == 0) { - erase->state = MTD_ERASE_DONE; - } else { - erase->state = MTD_ERASE_FAILED; - erase->fail_addr = 0xffffffff; - } - mtd_erase_callback(erase); - return rc; -} - -static int efx_mtd_write(struct mtd_info *mtd, loff_t start, - size_t len, size_t *retlen, const u8 *buffer) -{ - struct efx_mtd *efx_mtd = mtd->priv; - const struct efx_spi_device *spi = efx_mtd->spi; - struct efx_nic *efx = spi->efx; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_write(spi, FALCON_FLASH_BOOTCODE_START + start, - len, retlen, buffer); - mutex_unlock(&efx->spi_lock); - return rc; -} - -static void efx_mtd_sync(struct mtd_info *mtd) -{ - struct efx_mtd *efx_mtd = mtd->priv; - struct efx_nic *efx = efx_mtd->spi->efx; - int rc; - - mutex_lock(&efx->spi_lock); - rc = efx_spi_slow_wait(efx_mtd, true); - mutex_unlock(&efx->spi_lock); - - if (rc) - EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc); - return; -} - -void efx_mtd_remove(struct efx_nic *efx) -{ - if (efx->spi_flash && efx->spi_flash->mtd) { - struct efx_mtd *efx_mtd = efx->spi_flash->mtd; - int rc; - - for (;;) { - rc = del_mtd_device(&efx_mtd->mtd); - if (rc != -EBUSY) - break; - ssleep(1); - } - WARN_ON(rc); - kfree(efx_mtd); - } -} - -void efx_mtd_rename(struct efx_nic *efx) -{ - if (efx->spi_flash && efx->spi_flash->mtd) { - struct efx_mtd *efx_mtd = efx->spi_flash->mtd; - snprintf(efx_mtd->name, sizeof(efx_mtd->name), - "%s sfc_flash_bootrom", efx->name); - } -} - -int efx_mtd_probe(struct efx_nic *efx) -{ - struct efx_spi_device *spi = efx->spi_flash; - struct efx_mtd *efx_mtd; - - if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START) - return -ENODEV; - - efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL); - if (!efx_mtd) - return -ENOMEM; - - efx_mtd->spi = spi; - spi->mtd = efx_mtd; - - efx_mtd->mtd.type = MTD_NORFLASH; - efx_mtd->mtd.flags = MTD_CAP_NORFLASH; - efx_mtd->mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START; - efx_mtd->mtd.erasesize = spi->erase_size; - efx_mtd->mtd.writesize = 1; - efx_mtd_rename(efx); - - efx_mtd->mtd.owner = THIS_MODULE; - efx_mtd->mtd.priv = efx_mtd; - efx_mtd->mtd.name = efx_mtd->name; - efx_mtd->mtd.erase = efx_mtd_erase; - efx_mtd->mtd.read = efx_mtd_read; - efx_mtd->mtd.write = efx_mtd_write; - efx_mtd->mtd.sync = efx_mtd_sync; - - if (add_mtd_device(&efx_mtd->mtd)) { - kfree(efx_mtd); - spi->mtd = NULL; - /* add_mtd_device() returns 1 if the MTD table is full */ - return -ENOMEM; - } - - return 0; -} |
