MTD core:

* Dropped inactive maintainers, updated the repositories and added the IRC
   channel.
 * Debugfs functions improvements.
 * Initialized of more structure parameters.
 * Misc fixes reported by robots.
 
 MTD devices:
 * spear_smi: Fixed Write Burst mode
 * New Intel IXP4xx flash probing hook.
 
 Raw NAND core:
 * Useless extra checks dropped.
 * Updated the detection of the bad block markers position
 
 Raw NAND controller drivers:
 * Cadence : New driver
 * Brcmnand: Support for flash-dma v0 + fixes
 * Denali : Support for the legacy controller/chip DT representation
            dropped
 * Superfluous dev_err() calls removed
 
 SPI NOR core changes:
 * introduce 'struct spi_nor_controller_ops',
 * clean the Register Operations methods,
 * use dev_dbg insted of dev_err for low level info,
 * fix retlen handling in sst_write(),
 * fix silent truncations in spi_nor_read and spi_nor_read_raw(),
 * fix the clearing of QE bit on lock()/unlock(),
 * rework the disabling of the block write protection,
 * rework the Quad Enable methods,
 * make sure nor->spimem and nor->controller_ops are mutually exclusive,
 * set default Quad Enable method for ISSI flashes,
 * add support for few flashes.
 
 SPI NOR controller drivers changes:
 * intel-spi:
   - support chips without software sequencer,
   - add support for Intel Cannon Lake and Intel Comet Lake-H flashes.
 
 CFI core changes:
 * Code cleanups related useless initializers and coding style issues
 * Fix for a possible double free problem in cfi_cmdset_0002
 * Improved error reporting and handling in cfi_cmdset_0002 core for HyperFlash
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAl3YPbAACgkQJWrqGEe9
 VoRBOQf5AcGMw1eNrPNUW5RjyyEf/e29KZ1UKu6fD+2EFeY8qU/VYQzMCyM5sV2S
 B/ks8cHJ2CAD6GmiQJJP4727QFjngT8Wi/G1H5+D8juFewCYQ2QosKoohnUwsCyC
 Pq/QtMz2qQC9289PTaK4K3E9IygcnSztGUDkZWNolBJLMG0OShc3BeKhH45tXGwC
 UC1KhS79ymJbVsIJk/PQxWKUOUVN6YL8eWBMZoOdmRDTfTZeWCpCZiALzuwrE8qb
 pW9vOfeL9irslHVSkDAFa8zV6K3PzZGDTg3+gynXtX+Dx6buDSPDNXD4xdjxKmmW
 9p4MetkgGClTUV3Cwg95OIj1C6Mgjw==
 =50ZW
 -----END PGP SIGNATURE-----

Merge tag 'mtd/for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD updates from Miquel Raynal:
 "MTD core:
   - drop inactive maintainers, update the repositories and add IRC
     channel
   - debugfs functions improvements
   - initialize more structure parameters
   - misc fixes reported by robots

  MTD devices:
   - spear_smi: Fixed Write Burst mode
   - new Intel IXP4xx flash probing hook

  Raw NAND core:
   - useless extra checks dropped
   - update the detection of the bad block markers position

  Raw NAND controller drivers:
   - Cadence: new driver
   - Brcmnand: support for flash-dma v0 + fixes
   - Denali: drop support for the legacy controller/chip DT representation
   - superfluous dev_err() calls removed

  SPI NOR core changes:
   - introduce 'struct spi_nor_controller_ops'
   - clean the Register Operations methods
   - use dev_dbg insted of dev_err for low level info
   - fix retlen handling in sst_write()
   - fix silent truncations in spi_nor_read and spi_nor_read_raw()
   - fix the clearing of QE bit on lock()/unlock()
   - rework the disabling of the block write protection
   - rework the Quad Enable methods
   - make sure nor->spimem and nor->controller_ops are mutually exclusive
   - set default Quad Enable method for ISSI flashes
   - add support for few flashes

  SPI NOR controller drivers changes:
   - intel-spi:
      - support chips without software sequencer
      - add support for Intel Cannon Lake and Intel Comet Lake-H flashes

  CFI core changes:
   - code cleanups related useless initializers and coding style issues
   - fix for a possible double free problem in cfi_cmdset_0002
   - improved HyperFlash error reporting and handling in cfi_cmdset_0002 core"

* tag 'mtd/for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (73 commits)
  mtd: devices: fix mchp23k256 read and write
  mtd: no need to check return value of debugfs_create functions
  mtd: spi-nor: Set default Quad Enable method for ISSI flashes
  mtd: spi-nor: Add support for is25wp256
  mtd: spi-nor: Add support for w25q256jw
  mtd: spi-nor: Move condition to avoid a NULL check
  mtd: spi-nor: Make sure nor->spimem and nor->controller_ops are mutually exclusive
  mtd: spi-nor: Rename Quad Enable methods
  mtd: spi-nor: Merge spansion Quad Enable methods
  mtd: spi-nor: Rename CR_QUAD_EN_SPAN to SR2_QUAD_EN_BIT1
  mtd: spi-nor: Extend the SR Read Back test
  mtd: spi-nor: Rework the disabling of block write protection
  mtd: spi-nor: Fix clearing of QE bit on lock()/unlock()
  mtd: cfi_cmdset_0002: fix delayed error detection on HyperFlash
  mtd: cfi_cmdset_0002: only check errors when ready in cfi_check_err_status()
  mtd: cfi_cmdset_0002: don't free cfi->cfiq in error path of cfi_amdstd_setup()
  mtd: cfi_cmdset_*: kill useless 'ret' variable initializers
  mtd: cfi_util: use DIV_ROUND_UP() in cfi_udelay()
  mtd: spi-nor: Print debug message when the read back test fails
  mtd: spi-nor: Check all the bits written, not just the BP ones
  ...
This commit is contained in:
Linus Torvalds 2019-11-25 11:55:30 -08:00
commit 1b88176b9c
48 changed files with 4655 additions and 1153 deletions

View file

@ -0,0 +1,53 @@
* Cadence NAND controller
Required properties:
- compatible : "cdns,hp-nfc"
- reg : Contains two entries, each of which is a tuple consisting of a
physical address and length. The first entry is the address and
length of the controller register set. The second entry is the
address and length of the Slave DMA data port.
- reg-names: should contain "reg" and "sdma"
- #address-cells: should be 1. The cell encodes the chip select connection.
- #size-cells : should be 0.
- interrupts : The interrupt number.
- clocks: phandle of the controller core clock (nf_clk).
Optional properties:
- dmas: shall reference DMA channel associated to the NAND controller
- cdns,board-delay-ps : Estimated Board delay. The value includes the total
round trip delay for the signals and is used for deciding on values
associated with data read capture. The example formula for SDR mode is
the following:
board delay = RE#PAD delay + PCB trace to device + PCB trace from device
+ DQ PAD delay
Child nodes represent the available NAND chips.
Required properties of NAND chips:
- reg: shall contain the native Chip Select ids from 0 to max supported by
the cadence nand flash controller
See Documentation/devicetree/bindings/mtd/nand.txt for more details on
generic bindings.
Example:
nand_controller: nand-controller@60000000 {
compatible = "cdns,hp-nfc";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x60000000 0x10000>, <0x80000000 0x10000>;
reg-names = "reg", "sdma";
clocks = <&nf_clk>;
cdns,board-delay-ps = <4830>;
interrupts = <2 0>;
nand@0 {
reg = <0>;
label = "nand-1";
};
nand@1 {
reg = <1>;
label = "nand-2";
};
};

View file

@ -0,0 +1,22 @@
Flash device on Intel IXP4xx SoC
This flash is regular CFI compatible (Intel or AMD extended) flash chips with
specific big-endian or mixed-endian memory access pattern.
Required properties:
- compatible : must be "intel,ixp4xx-flash", "cfi-flash";
- reg : memory address for the flash chip
- bank-width : width in bytes of flash interface, should be <2>
For the rest of the properties, see mtd-physmap.txt.
The device tree may optionally contain sub-nodes describing partitions of the
address space. See partition.txt for more detail.
Example:
flash@50000000 {
compatible = "intel,ixp4xx-flash", "cfi-flash";
reg = <0x50000000 0x01000000>;
bank-width = <2>;
};

View file

@ -3595,6 +3595,13 @@ S: Maintained
F: Documentation/devicetree/bindings/media/cdns,*.txt
F: drivers/media/platform/cadence/cdns-csi2*
CADENCE NAND DRIVER
M: Piotr Sroka <piotrs@cadence.com>
L: linux-mtd@lists.infradead.org
S: Maintained
F: drivers/mtd/nand/raw/cadence-nand-controller.c
F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
CADET FM/AM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
@ -10537,15 +10544,13 @@ F: include/linux/vmalloc.h
F: mm/
MEMORY TECHNOLOGY DEVICES (MTD)
M: David Woodhouse <dwmw2@infradead.org>
M: Brian Norris <computersforpeace@gmail.com>
M: Marek Vasut <marek.vasut@gmail.com>
M: Miquel Raynal <miquel.raynal@bootlin.com>
M: Richard Weinberger <richard@nod.at>
M: Vignesh Raghavendra <vigneshr@ti.com>
L: linux-mtd@lists.infradead.org
W: http://www.linux-mtd.infradead.org/
Q: http://patchwork.ozlabs.org/project/linux-mtd/list/
C: irc://irc.oftc.net/mtd
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/fixes
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
S: Maintained
@ -15296,7 +15301,6 @@ F: arch/arm/boot/dts/spear*
F: arch/arm/mach-spear/
SPI NOR SUBSYSTEM
M: Marek Vasut <marek.vasut@gmail.com>
M: Tudor Ambarus <tudor.ambarus@microchip.com>
L: linux-mtd@lists.infradead.org
W: http://www.linux-mtd.infradead.org/
@ -16593,10 +16597,9 @@ F: drivers/media/pci/tw686x/
UBI FILE SYSTEM (UBIFS)
M: Richard Weinberger <richard@nod.at>
M: Artem Bityutskiy <dedekind1@gmail.com>
M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
S: Supported
F: Documentation/filesystems/ubifs.txt
@ -16711,11 +16714,11 @@ S: Maintained
F: drivers/scsi/ufs/ufs-mediatek*
UNSORTED BLOCK IMAGES (UBI)
M: Artem Bityutskiy <dedekind1@gmail.com>
M: Richard Weinberger <richard@nod.at>
W: http://www.linux-mtd.infradead.org/
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
S: Supported
F: drivers/mtd/ubi/
F: include/linux/mtd/ubi.h

View file

@ -1353,7 +1353,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
{
unsigned long cmd_addr;
struct cfi_private *cfi = map->fldrv_priv;
int ret = 0;
int ret;
adr += chip->start;
@ -1383,7 +1383,7 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
struct cfi_private *cfi = map->fldrv_priv;
unsigned long ofs, last_end = 0;
int chipnum;
int ret = 0;
int ret;
if (!map->virt)
return -EINVAL;
@ -1550,7 +1550,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
{
struct cfi_private *cfi = map->fldrv_priv;
map_word status, write_cmd;
int ret=0;
int ret;
adr += chip->start;
@ -1624,7 +1624,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
int ret = 0;
int ret;
int chipnum;
unsigned long ofs;
@ -1871,7 +1871,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
int ret = 0;
int ret;
int chipnum;
unsigned long ofs, vec_seek, i;
size_t len = 0;

View file

@ -123,19 +123,23 @@ static int cfi_use_status_reg(struct cfi_private *cfi)
(extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;
}
static void cfi_check_err_status(struct map_info *map, struct flchip *chip,
unsigned long adr)
static int cfi_check_err_status(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
struct cfi_private *cfi = map->fldrv_priv;
map_word status;
if (!cfi_use_status_reg(cfi))
return;
return 0;
cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
status = map_read(map, adr);
/* The error bits are invalid while the chip's busy */
if (!map_word_bitsset(map, status, CMD(CFI_SR_DRB)))
return 0;
if (map_word_bitsset(map, status, CMD(0x3a))) {
unsigned long chipstatus = MERGESTATUS(status);
@ -151,7 +155,12 @@ static void cfi_check_err_status(struct map_info *map, struct flchip *chip,
if (chipstatus & CFI_SR_SLSB)
pr_err("%s sector write protected, status %lx\n",
map->name, chipstatus);
/* Erase/Program status bits are set on the operation failure */
if (chipstatus & (CFI_SR_ESB | CFI_SR_PSB))
return 1;
}
return 0;
}
/* #define DEBUG_CFI_FEATURES */
@ -785,7 +794,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
kfree(mtd->eraseregions);
kfree(mtd);
kfree(cfi->cmdset_priv);
kfree(cfi->cfiq);
return NULL;
}
@ -848,20 +856,16 @@ static int __xipram chip_good(struct map_info *map, struct flchip *chip,
if (cfi_use_status_reg(cfi)) {
map_word ready = CMD(CFI_SR_DRB);
map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB);
/*
* For chips that support status register, check device
* ready bit and Erase/Program status bit to know if
* operation succeeded.
* ready bit
*/
cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
curd = map_read(map, addr);
if (map_word_andequal(map, curd, ready, ready))
return !map_word_bitsset(map, curd, err);
return 0;
return map_word_andequal(map, curd, ready, ready);
}
oldd = map_read(map, addr);
@ -1699,8 +1703,11 @@ static int __xipram do_write_oneword_once(struct map_info *map,
break;
}
if (chip_good(map, chip, adr, datum))
if (chip_good(map, chip, adr, datum)) {
if (cfi_check_err_status(map, chip, adr))
ret = -EIO;
break;
}
/* Latency issues. Drop the lock, wait a while and retry */
UDELAY(map, chip, adr, 1);
@ -1713,7 +1720,7 @@ static int __xipram do_write_oneword_start(struct map_info *map,
struct flchip *chip,
unsigned long adr, int mode)
{
int ret = 0;
int ret;
mutex_lock(&chip->mutex);
@ -1773,7 +1780,6 @@ static int __xipram do_write_oneword_retry(struct map_info *map,
ret = do_write_oneword_once(map, chip, adr, datum, mode, cfi);
if (ret) {
/* reset on all failures. */
cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@ -1791,7 +1797,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
unsigned long adr, map_word datum,
int mode)
{
int ret = 0;
int ret;
adr += chip->start;
@ -1815,7 +1821,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
int ret = 0;
int ret;
int chipnum;
unsigned long ofs, chipstart;
DECLARE_WAITQUEUE(wait, current);
@ -1970,12 +1976,17 @@ static int __xipram do_write_buffer_wait(struct map_info *map,
*/
if (time_after(jiffies, timeo) &&
!chip_good(map, chip, adr, datum)) {
pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
__func__, adr);
ret = -EIO;
break;
}
if (chip_good(map, chip, adr, datum))
if (chip_good(map, chip, adr, datum)) {
if (cfi_check_err_status(map, chip, adr))
ret = -EIO;
break;
}
/* Latency issues. Drop the lock, wait a while and retry */
UDELAY(map, chip, adr, 1);
@ -2014,7 +2025,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
int len)
{
struct cfi_private *cfi = map->fldrv_priv;
int ret = -EIO;
int ret;
unsigned long cmd_adr;
int z, words;
map_word datum;
@ -2071,12 +2082,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
chip->word_write_time);
ret = do_write_buffer_wait(map, chip, adr, datum);
if (ret) {
cfi_check_err_status(map, chip, adr);
if (ret)
do_write_buffer_reset(map, chip, cfi);
pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
__func__, adr);
}
xip_enable(map, chip, adr);
@ -2095,7 +2102,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
int ret = 0;
int ret;
int chipnum;
unsigned long ofs;
@ -2232,7 +2239,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
struct cfi_private *cfi = map->fldrv_priv;
int retry_cnt = 0;
map_word oldd;
int ret = 0;
int ret;
int i;
adr += chip->start;
@ -2271,9 +2278,9 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
udelay(1);
}
if (!chip_good(map, chip, adr, datum)) {
if (!chip_good(map, chip, adr, datum) ||
cfi_check_err_status(map, chip, adr)) {
/* reset on all failures. */
cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@ -2307,7 +2314,7 @@ static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
unsigned long ofs, chipstart;
int ret = 0;
int ret;
int chipnum;
chipnum = to >> cfi->chipshift;
@ -2411,7 +2418,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
unsigned long timeo = jiffies + HZ;
unsigned long int adr;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ret;
int retry_cnt = 0;
adr = cfi->addr_unlock1;
@ -2467,8 +2474,11 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
chip->erase_suspended = 0;
}
if (chip_good(map, chip, adr, map_word_ff(map)))
if (chip_good(map, chip, adr, map_word_ff(map))) {
if (cfi_check_err_status(map, chip, adr))
ret = -EIO;
break;
}
if (time_after(jiffies, timeo)) {
printk(KERN_WARNING "MTD %s(): software timeout\n",
@ -2483,7 +2493,6 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
/* Did we succeed? */
if (ret) {
/* reset on all failures. */
cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@ -2508,7 +2517,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
struct cfi_private *cfi = map->fldrv_priv;
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ret;
int retry_cnt = 0;
adr += chip->start;
@ -2564,8 +2573,11 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->erase_suspended = 0;
}
if (chip_good(map, chip, adr, map_word_ff(map)))
if (chip_good(map, chip, adr, map_word_ff(map))) {
if (cfi_check_err_status(map, chip, adr))
ret = -EIO;
break;
}
if (time_after(jiffies, timeo)) {
printk(KERN_WARNING "MTD %s(): software timeout\n",
@ -2580,7 +2592,6 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
/* Did we succeed? */
if (ret) {
/* reset on all failures. */
cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */

View file

@ -611,7 +611,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
int ret = 0;
int ret;
int chipnum;
unsigned long ofs;
@ -895,7 +895,7 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
{ struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
unsigned long adr, len;
int chipnum, ret = 0;
int chipnum, ret;
int i, first;
struct mtd_erase_region_info *regions = mtd->eraseregions;
@ -1132,7 +1132,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
unsigned long adr;
int chipnum, ret = 0;
int chipnum, ret;
#ifdef DEBUG_LOCK_BITS
int ofs_factor = cfi->interleave * cfi->device_type;
#endif
@ -1279,7 +1279,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
unsigned long adr;
int chipnum, ret = 0;
int chipnum, ret;
#ifdef DEBUG_LOCK_BITS
int ofs_factor = cfi->interleave * cfi->device_type;
#endif

View file

@ -26,7 +26,7 @@
void cfi_udelay(int us)
{
if (us >= 1000) {
msleep((us+999)/1000);
msleep(DIV_ROUND_UP(us, 1000));
} else {
udelay(us);
cond_resched();

View file

@ -64,15 +64,17 @@ static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len,
struct spi_transfer transfer[2] = {};
struct spi_message message;
unsigned char command[MAX_CMD_SIZE];
int ret;
int ret, cmd_len;
spi_message_init(&message);
cmd_len = mchp23k256_cmdsz(flash);
command[0] = MCHP23K256_CMD_WRITE;
mchp23k256_addr2cmd(flash, to, command);
transfer[0].tx_buf = command;
transfer[0].len = mchp23k256_cmdsz(flash);
transfer[0].len = cmd_len;
spi_message_add_tail(&transfer[0], &message);
transfer[1].tx_buf = buf;
@ -88,8 +90,8 @@ static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len,
if (ret)
return ret;
if (retlen && message.actual_length > sizeof(command))
*retlen += message.actual_length - sizeof(command);
if (retlen && message.actual_length > cmd_len)
*retlen += message.actual_length - cmd_len;
return 0;
}
@ -101,16 +103,18 @@ static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len,
struct spi_transfer transfer[2] = {};
struct spi_message message;
unsigned char command[MAX_CMD_SIZE];
int ret;
int ret, cmd_len;
spi_message_init(&message);
cmd_len = mchp23k256_cmdsz(flash);
memset(&transfer, 0, sizeof(transfer));
command[0] = MCHP23K256_CMD_READ;
mchp23k256_addr2cmd(flash, from, command);
transfer[0].tx_buf = command;
transfer[0].len = mchp23k256_cmdsz(flash);
transfer[0].len = cmd_len;
spi_message_add_tail(&transfer[0], &message);
transfer[1].rx_buf = buf;
@ -126,8 +130,8 @@ static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len,
if (ret)
return ret;
if (retlen && message.actual_length > sizeof(command))
*retlen += message.actual_length - sizeof(command);
if (retlen && message.actual_length > cmd_len)
*retlen += message.actual_length - cmd_len;
return 0;
}

View file

@ -592,6 +592,26 @@ static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
return 0;
}
/*
* The purpose of this function is to ensure a memcpy_toio() with byte writes
* only. Its structure is inspired from the ARM implementation of _memcpy_toio()
* which also does single byte writes but cannot be used here as this is just an
* implementation detail and not part of the API. Not mentioning the comment
* stating that _memcpy_toio() should be optimized.
*/
static void spear_smi_memcpy_toio_b(volatile void __iomem *dest,
const void *src, size_t len)
{
const unsigned char *from = src;
while (len) {
len--;
writeb(*from, dest);
from++;
dest++;
}
}
static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
void __iomem *dest, const void *src, size_t len)
{
@ -614,7 +634,23 @@ static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
ctrlreg1 = readl(dev->io_base + SMI_CR1);
writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1);
memcpy_toio(dest, src, len);
/*
* In Write Burst mode (WB_MODE), the specs states that writes must be:
* - incremental
* - of the same size
* The ARM implementation of memcpy_toio() will optimize the number of
* I/O by using as much 4-byte writes as possible, surrounded by
* 2-byte/1-byte access if:
* - the destination is not 4-byte aligned
* - the length is not a multiple of 4-byte.
* Avoid this alternance of write access size by using our own 'byte
* access' helper if at least one of the two conditions above is true.
*/
if (IS_ALIGNED(len, sizeof(u32)) &&
IS_ALIGNED((uintptr_t)dest, sizeof(u32)))
memcpy_toio(dest, src, len);
else
spear_smi_memcpy_toio_b(dest, src, len);
writel(ctrlreg1, dev->io_base + SMI_CR1);
@ -777,9 +813,6 @@ static int spear_smi_probe_config_dt(struct platform_device *pdev,
/* Fill structs for each subnode (flash device) */
while ((pp = of_get_next_child(np, pp))) {
struct spear_smi_flash_info *flash_info;
flash_info = &pdata->board_flash_info[i];
pdata->np[i] = pp;
/* Read base-addr and size from DT */
@ -933,7 +966,6 @@ static int spear_smi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = -ENODEV;
dev_err(&pdev->dev, "invalid smi irq\n");
goto err;
}

View file

@ -255,7 +255,6 @@ struct stfsm_seq {
struct stfsm {
struct device *dev;
void __iomem *base;
struct resource *region;
struct mtd_info mtd;
struct mutex lock;
struct flash_info *info;

View file

@ -96,6 +96,17 @@ config MTD_PHYSMAP_GEMINI
platforms, some detection and setting up parallel mode on the
external interface.
config MTD_PHYSMAP_IXP4XX
bool "Intel IXP4xx OF-based physical memory map handling"
depends on MTD_PHYSMAP_OF
depends on ARM
select MTD_COMPLEX_MAPPINGS
select MTD_CFI_BE_BYTE_SWAP if CPU_BIG_ENDIAN
default ARCH_IXP4XX
help
This provides some extra DT physmap parsing for the Intel IXP4xx
platforms, some elaborate endianness handling in particular.
config MTD_PHYSMAP_GPIO_ADDR
bool "GPIO-assisted Flash Chip Support"
depends on MTD_PHYSMAP

View file

@ -20,6 +20,7 @@ obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
physmap-objs-y += physmap-core.o
physmap-objs-$(CONFIG_MTD_PHYSMAP_VERSATILE) += physmap-versatile.o
physmap-objs-$(CONFIG_MTD_PHYSMAP_GEMINI) += physmap-gemini.o
physmap-objs-$(CONFIG_MTD_PHYSMAP_IXP4XX) += physmap-ixp4xx.o
physmap-objs := $(physmap-objs-y)
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
obj-$(CONFIG_MTD_PISMO) += pismo.o

View file

@ -86,7 +86,7 @@ static int __init init_l440gx(void)
return -ENOMEM;
}
simple_map_init(&l440gx_map);
printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt);
pr_debug("window_addr = %p\n", l440gx_map.virt);
/* Setup the pm iobase resource
* This code should move into some kind of generic bridge

View file

@ -41,6 +41,7 @@
#include <linux/gpio/consumer.h>
#include "physmap-gemini.h"
#include "physmap-ixp4xx.h"
#include "physmap-versatile.h"
struct physmap_flash_info {
@ -370,6 +371,10 @@ static int physmap_flash_of_init(struct platform_device *dev)
if (err)
return err;
err = of_flash_probe_ixp4xx(dev, dp, &info->maps[i]);
if (err)
return err;
err = of_flash_probe_versatile(dev, dp, &info->maps[i]);
if (err)
return err;

View file

@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Intel IXP4xx OF physmap add-on
* Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
*
* Based on the ixp4xx.c map driver, originally written by:
* Intel Corporation
* Deepak Saxena <dsaxena@mvista.com>
* Copyright (C) 2002 Intel Corporation
* Copyright (C) 2003-2004 MontaVista Software, Inc.
*/
#include <linux/export.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mtd/map.h>
#include <linux/mtd/xip.h>
#include "physmap-ixp4xx.h"
/*
* Read/write a 16 bit word from flash address 'addr'.
*
* When the cpu is in little-endian mode it swizzles the address lines
* ('address coherency') so we need to undo the swizzling to ensure commands
* and the like end up on the correct flash address.
*
* To further complicate matters, due to the way the expansion bus controller
* handles 32 bit reads, the byte stream ABCD is stored on the flash as:
* D15 D0
* +---+---+
* | A | B | 0
* +---+---+
* | C | D | 2
* +---+---+
* This means that on LE systems each 16 bit word must be swapped. Note that
* this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI
* data and other flash commands which are always in D7-D0.
*/
#ifndef CONFIG_CPU_BIG_ENDIAN
static inline u16 flash_read16(void __iomem *addr)
{
return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2)));
}
static inline void flash_write16(u16 d, void __iomem *addr)
{
__raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2));
}
#define BYTE0(h) ((h) & 0xFF)
#define BYTE1(h) (((h) >> 8) & 0xFF)
#else
static inline u16 flash_read16(const void __iomem *addr)
{
return __raw_readw(addr);
}
static inline void flash_write16(u16 d, void __iomem *addr)
{
__raw_writew(d, addr);
}
#define BYTE0(h) (((h) >> 8) & 0xFF)
#define BYTE1(h) ((h) & 0xFF)
#endif
static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = flash_read16(map->virt + ofs);
return val;
}
/*
* The IXP4xx expansion bus only allows 16-bit wide acceses
* when attached to a 16-bit wide device (such as the 28F128J3A),
* so we can't just memcpy_fromio().
*/
static void ixp4xx_copy_from(struct map_info *map, void *to,
unsigned long from, ssize_t len)
{
u8 *dest = (u8 *) to;
void __iomem *src = map->virt + from;
if (len <= 0)
return;
if (from & 1) {
*dest++ = BYTE1(flash_read16(src-1));
src++;
--len;
}
while (len >= 2) {
u16 data = flash_read16(src);
*dest++ = BYTE0(data);
*dest++ = BYTE1(data);
src += 2;
len -= 2;
}
if (len > 0)
*dest++ = BYTE0(flash_read16(src));
}
static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
{
flash_write16(d.x[0], map->virt + adr);
}
int of_flash_probe_ixp4xx(struct platform_device *pdev,
struct device_node *np,
struct map_info *map)
{
struct device *dev = &pdev->dev;
/* Multiplatform guard */
if (!of_device_is_compatible(np, "intel,ixp4xx-flash"))
return 0;
map->read = ixp4xx_read16;
map->write = ixp4xx_write16;
map->copy_from = ixp4xx_copy_from;
map->copy_to = NULL;
dev_info(dev, "initialized Intel IXP4xx-specific physmap control\n");
return 0;
}

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/of.h>
#include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PHYSMAP_IXP4XX
int of_flash_probe_ixp4xx(struct platform_device *pdev,
struct device_node *np,
struct map_info *map);
#else
static inline
int of_flash_probe_ixp4xx(struct platform_device *pdev,
struct device_node *np,
struct map_info *map)
{
return 0;
}
#endif

View file

@ -174,7 +174,7 @@ static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
break;
case MTD_FILE_MODE_RAW:
{
struct mtd_oob_ops ops;
struct mtd_oob_ops ops = {};
ops.mode = MTD_OPS_RAW;
ops.datbuf = kbuf;
@ -268,7 +268,7 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c
case MTD_FILE_MODE_RAW:
{
struct mtd_oob_ops ops;
struct mtd_oob_ops ops = {};
ops.mode = MTD_OPS_RAW;
ops.datbuf = kbuf;
@ -350,7 +350,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
uint32_t __user *retp)
{
struct mtd_file_info *mfi = file->private_data;
struct mtd_oob_ops ops;
struct mtd_oob_ops ops = {};
uint32_t retlen;
int ret = 0;
@ -394,7 +394,7 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
uint32_t __user *retp)
{
struct mtd_file_info *mfi = file->private_data;
struct mtd_oob_ops ops;
struct mtd_oob_ops ops = {};
int ret = 0;
if (length > 4096)
@ -587,7 +587,7 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
struct mtd_write_req __user *argp)
{
struct mtd_write_req req;
struct mtd_oob_ops ops;
struct mtd_oob_ops ops = {};
const void __user *usr_data, *usr_oob;
int ret;

View file

@ -382,33 +382,21 @@ static struct dentry *dfs_dir_mtd;
static void mtd_debugfs_populate(struct mtd_info *mtd)
{
struct device *dev = &mtd->dev;
struct dentry *root, *dent;
struct dentry *root;
if (IS_ERR_OR_NULL(dfs_dir_mtd))
return;
root = debugfs_create_dir(dev_name(dev), dfs_dir_mtd);
if (IS_ERR_OR_NULL(root)) {
dev_dbg(dev, "won't show data in debugfs\n");
return;
}
mtd->dbg.dfs_dir = root;
if (mtd->dbg.partid) {
dent = debugfs_create_file("partid", 0400, root, mtd,
&mtd_partid_debug_fops);
if (IS_ERR_OR_NULL(dent))
dev_err(dev, "can't create debugfs entry for partid\n");
}
if (mtd->dbg.partid)
debugfs_create_file("partid", 0400, root, mtd,
&mtd_partid_debug_fops);
if (mtd->dbg.partname) {
dent = debugfs_create_file("partname", 0400, root, mtd,
&mtd_partname_debug_fops);
if (IS_ERR_OR_NULL(dent))
dev_err(dev,
"can't create debugfs entry for partname\n");
}
if (mtd->dbg.partname)
debugfs_create_file("partname", 0400, root, mtd,
&mtd_partname_debug_fops);
}
#ifndef CONFIG_MMU

View file

@ -1257,7 +1257,6 @@ DEFINE_SHOW_ATTRIBUTE(mtdswap);
static int mtdswap_add_debugfs(struct mtdswap_dev *d)
{
struct dentry *root = d->mtd->dbg.dfs_dir;
struct dentry *dent;
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
@ -1265,12 +1264,7 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d)
if (IS_ERR_OR_NULL(root))
return -1;
dent = debugfs_create_file("mtdswap_stats", S_IRUSR, root, d,
&mtdswap_fops);
if (!dent) {
dev_err(d->dev, "debugfs_create_file failed\n");
return -1;
}
debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops);
return 0;
}

View file

@ -450,6 +450,13 @@ config MTD_NAND_PLATFORM
devices. You will need to provide platform-specific functions
via platform_data.
config MTD_NAND_CADENCE
tristate "Support Cadence NAND (HPNFC) controller"
depends on OF || COMPILE_TEST
help
Enable the driver for NAND flash on platforms using a Cadence NAND
controller.
comment "Misc"
config MTD_SM_COMMON

View file

@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_MXIC) += mxic_nand.o
obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o
obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o
obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o
obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
nand-objs += nand_onfi.o

View file

@ -117,6 +117,18 @@ enum flash_dma_reg {
FLASH_DMA_CURRENT_DESC_EXT,
};
/* flash_dma registers v0*/
static const u16 flash_dma_regs_v0[] = {
[FLASH_DMA_REVISION] = 0x00,
[FLASH_DMA_FIRST_DESC] = 0x04,
[FLASH_DMA_CTRL] = 0x08,
[FLASH_DMA_MODE] = 0x0c,
[FLASH_DMA_STATUS] = 0x10,
[FLASH_DMA_INTERRUPT_DESC] = 0x14,
[FLASH_DMA_ERROR_STATUS] = 0x18,
[FLASH_DMA_CURRENT_DESC] = 0x1c,
};
/* flash_dma registers v1*/
static const u16 flash_dma_regs_v1[] = {
[FLASH_DMA_REVISION] = 0x00,
@ -597,6 +609,8 @@ static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl)
/* flash_dma register offsets */
if (ctrl->nand_version >= 0x0703)
ctrl->flash_dma_offsets = flash_dma_regs_v4;
else if (ctrl->nand_version == 0x0602)
ctrl->flash_dma_offsets = flash_dma_regs_v0;
else
ctrl->flash_dma_offsets = flash_dma_regs_v1;
}
@ -918,7 +932,7 @@ static inline void disable_ctrl_irqs(struct brcmnand_controller *ctrl)
return;
if (has_flash_dma(ctrl)) {
ctrl->flash_dma_base = 0;
ctrl->flash_dma_base = NULL;
disable_irq(ctrl->dma_irq);
}
@ -1673,8 +1687,11 @@ static void brcmnand_dma_run(struct brcmnand_host *host, dma_addr_t desc)
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC, lower_32_bits(desc));
(void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC);
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, upper_32_bits(desc));
(void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT);
if (ctrl->nand_version > 0x0602) {
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT,
upper_32_bits(desc));
(void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT);
}
/* Start FLASH_DMA engine */
ctrl->dma_pending = true;

File diff suppressed because it is too large Load diff

View file

@ -102,47 +102,6 @@ static int denali_dt_chip_init(struct denali_controller *denali,
return denali_chip_init(denali, dchip);
}
/* Backward compatibility for old platforms */
static int denali_dt_legacy_chip_init(struct denali_controller *denali)
{
struct denali_chip *dchip;
int nsels, i;
nsels = denali->nbanks;
dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels),
GFP_KERNEL);
if (!dchip)
return -ENOMEM;
dchip->nsels = nsels;
for (i = 0; i < nsels; i++)
dchip->sels[i].bank = i;
nand_set_flash_node(&dchip->chip, denali->dev->of_node);
return denali_chip_init(denali, dchip);
}
/*
* Check the DT binding.
* The new binding expects chip subnodes in the controller node.
* So, #address-cells = <1>; #size-cells = <0>; are required.
* Check the #size-cells to distinguish the binding.
*/
static bool denali_dt_is_legacy_binding(struct device_node *np)
{
u32 cells;
int ret;
ret = of_property_read_u32(np, "#size-cells", &cells);
if (ret)
return true;
return cells != 0;
}
static int denali_dt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -167,10 +126,8 @@ static int denali_dt_probe(struct platform_device *pdev)
denali->dev = dev;
denali->irq = platform_get_irq(pdev, 0);
if (denali->irq < 0) {
dev_err(dev, "no irq defined\n");
if (denali->irq < 0)
return denali->irq;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "denali_reg");
denali->reg = devm_ioremap_resource(dev, res);
@ -213,17 +170,11 @@ static int denali_dt_probe(struct platform_device *pdev)
if (ret)
goto out_disable_clk_ecc;
if (denali_dt_is_legacy_binding(dev->of_node)) {
ret = denali_dt_legacy_chip_init(denali);
if (ret)
for_each_child_of_node(dev->of_node, np) {
ret = denali_dt_chip_init(denali, np);
if (ret) {
of_node_put(np);
goto out_remove_denali;
} else {
for_each_child_of_node(dev->of_node, np) {
ret = denali_dt_chip_init(denali, np);
if (ret) {
of_node_put(np);
goto out_remove_denali;
}
}
}

View file

@ -751,10 +751,8 @@ static int hisi_nfc_probe(struct platform_device *pdev)
mtd = nand_to_mtd(chip);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no IRQ resource defined\n");
if (irq < 0)
return -ENXIO;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->iobase = devm_ioremap_resource(dev, res);

View file

@ -773,7 +773,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
dev_err(&pdev->dev, "failed to get platform irq\n");
res = -EINVAL;
goto release_dma_chan;
}

View file

@ -2862,10 +2862,8 @@ static int marvell_nfc_probe(struct platform_device *pdev)
return PTR_ERR(nfc->regs);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to retrieve irq\n");
if (irq < 0)
return irq;
}
nfc->core_clk = devm_clk_get(&pdev->dev, "core");

View file

@ -1399,10 +1399,8 @@ static int meson_nfc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no NFC IRQ resource\n");
if (irq < 0)
return -EINVAL;
}
ret = meson_nfc_clk_init(nfc);
if (ret) {

View file

@ -527,10 +527,8 @@ static int mtk_ecc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to get irq: %d\n", irq);
if (irq < 0)
return irq;
}
ret = dma_set_mask(dev, DMA_BIT_MASK(32));
if (ret) {

View file

@ -1540,7 +1540,6 @@ static int mtk_nfc_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no nfi irq resource\n");
ret = -EINVAL;
goto clk_disable;
}

View file

@ -524,10 +524,8 @@ static int mxic_nfc_probe(struct platform_device *pdev)
nand_chip->controller = &nfc->controller;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to retrieve irq\n");
if (irq < 0)
return irq;
}
mxic_nfc_hw_init(nfc);

View file

@ -292,12 +292,16 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int page)
struct mtd_info *mtd = nand_to_mtd(chip);
int last_page = ((mtd->erasesize - mtd->writesize) >>
chip->page_shift) & chip->pagemask;
unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
| NAND_BBM_LASTPAGE;
if (page == 0 && !(chip->options & bbm_flags))
return 0;
if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
return 0;
else if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
return 1;
else if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
return last_page;
return -EINVAL;

View file

@ -446,8 +446,10 @@ static int micron_nand_init(struct nand_chip *chip)
if (ret)
goto err_free_manuf_data;
chip->options |= NAND_BBM_FIRSTPAGE;
if (mtd->writesize == 2048)
chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
chip->options |= NAND_BBM_SECONDPAGE;
ondie = micron_supports_on_die_ecc(chip);

View file

@ -1967,10 +1967,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
case NAND_OMAP_PREFETCH_IRQ:
info->gpmc_irq_fifo = platform_get_irq(info->pdev, 0);
if (info->gpmc_irq_fifo <= 0) {
dev_err(dev, "Error getting fifo IRQ\n");
if (info->gpmc_irq_fifo <= 0)
return -ENODEV;
}
err = devm_request_irq(dev, info->gpmc_irq_fifo,
omap_nand_irq, IRQF_SHARED,
"gpmc-nand-fifo", info);
@ -1982,10 +1980,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
}
info->gpmc_irq_count = platform_get_irq(info->pdev, 1);
if (info->gpmc_irq_count <= 0) {
dev_err(dev, "Error getting IRQ count\n");
if (info->gpmc_irq_count <= 0)
return -ENODEV;
}
err = devm_request_irq(dev, info->gpmc_irq_count,
omap_nand_irq, IRQF_SHARED,
"gpmc-nand-count", info);

View file

@ -1129,10 +1129,8 @@ static int flctl_probe(struct platform_device *pdev)
flctl->fifo = res->start + 0x24; /* FLDTFIFO */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to get flste irq data: %d\n", irq);
if (irq < 0)
return irq;
}
ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,
"flste", flctl);

View file

@ -1880,11 +1880,8 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
if (irq != -EPROBE_DEFER)
dev_err(dev, "IRQ error missing or invalid\n");
if (irq < 0)
return irq;
}
ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
dev_name(dev), fmc2);

View file

@ -2071,10 +2071,8 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
return PTR_ERR(nfc->regs);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to retrieve irq\n");
if (irq < 0)
return irq;
}
nfc->ahb_clk = devm_clk_get(dev, "ahb");
if (IS_ERR(nfc->ahb_clk)) {

View file

@ -320,7 +320,8 @@ static void aspeed_smc_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
mutex_unlock(&chip->controller->mutex);
}
static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
size_t len)
{
struct aspeed_smc_chip *chip = nor->priv;
@ -331,8 +332,8 @@ static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
return 0;
}
static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
int len)
static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len)
{
struct aspeed_smc_chip *chip = nor->priv;
@ -746,6 +747,15 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
return 0;
}
static const struct spi_nor_controller_ops aspeed_smc_controller_ops = {
.prepare = aspeed_smc_prep,
.unprepare = aspeed_smc_unprep,
.read_reg = aspeed_smc_read_reg,
.write_reg = aspeed_smc_write_reg,
.read = aspeed_smc_read_user,
.write = aspeed_smc_write_user,
};
static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
struct device_node *np, struct resource *r)
{
@ -805,12 +815,7 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
nor->dev = dev;
nor->priv = chip;
spi_nor_set_flash_node(nor, child);
nor->read = aspeed_smc_read_user;
nor->write = aspeed_smc_write_user;
nor->read_reg = aspeed_smc_read_reg;
nor->write_reg = aspeed_smc_write_reg;
nor->prepare = aspeed_smc_prep;
nor->unprepare = aspeed_smc_unprep;
nor->controller_ops = &aspeed_smc_controller_ops;
ret = aspeed_smc_chip_setup_init(chip, r);
if (ret)

View file

@ -285,7 +285,7 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
return IRQ_HANDLED;
}
static unsigned int cqspi_calc_rdreg(struct spi_nor *nor, const u8 opcode)
static unsigned int cqspi_calc_rdreg(struct spi_nor *nor)
{
struct cqspi_flash_pdata *f_pdata = nor->priv;
u32 rdreg = 0;
@ -354,27 +354,27 @@ static int cqspi_exec_flash_cmd(struct cqspi_st *cqspi, unsigned int reg)
return cqspi_wait_idle(cqspi);
}
static int cqspi_command_read(struct spi_nor *nor,
const u8 *txbuf, const unsigned n_tx,
u8 *rxbuf, const unsigned n_rx)
static int cqspi_command_read(struct spi_nor *nor, u8 opcode,
u8 *rxbuf, size_t n_rx)
{
struct cqspi_flash_pdata *f_pdata = nor->priv;
struct cqspi_st *cqspi = f_pdata->cqspi;
void __iomem *reg_base = cqspi->iobase;
unsigned int rdreg;
unsigned int reg;
unsigned int read_len;
size_t read_len;
int status;
if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) {
dev_err(nor->dev, "Invalid input argument, len %d rxbuf 0x%p\n",
dev_err(nor->dev,
"Invalid input argument, len %zu rxbuf 0x%p\n",
n_rx, rxbuf);
return -EINVAL;
}
reg = txbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB;
reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
rdreg = cqspi_calc_rdreg(nor, txbuf[0]);
rdreg = cqspi_calc_rdreg(nor);
writel(rdreg, reg_base + CQSPI_REG_RD_INSTR);
reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB);
@ -404,19 +404,19 @@ static int cqspi_command_read(struct spi_nor *nor,
}
static int cqspi_command_write(struct spi_nor *nor, const u8 opcode,
const u8 *txbuf, const unsigned n_tx)
const u8 *txbuf, size_t n_tx)
{
struct cqspi_flash_pdata *f_pdata = nor->priv;
struct cqspi_st *cqspi = f_pdata->cqspi;
void __iomem *reg_base = cqspi->iobase;
unsigned int reg;
unsigned int data;
u32 write_len;
size_t write_len;
int ret;
if (n_tx > CQSPI_STIG_DATA_LEN_MAX || (n_tx && !txbuf)) {
dev_err(nor->dev,
"Invalid input argument, cmdlen %d txbuf 0x%p\n",
"Invalid input argument, cmdlen %zu txbuf 0x%p\n",
n_tx, txbuf);
return -EINVAL;
}
@ -470,7 +470,7 @@ static int cqspi_read_setup(struct spi_nor *nor)
unsigned int reg;
reg = nor->read_opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB;
reg |= cqspi_calc_rdreg(nor, nor->read_opcode);
reg |= cqspi_calc_rdreg(nor);
/* Setup dummy clock cycles */
dummy_clk = nor->read_dummy;
@ -603,7 +603,7 @@ static int cqspi_write_setup(struct spi_nor *nor)
/* Set opcode. */
reg = nor->program_opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
writel(reg, reg_base + CQSPI_REG_WR_INSTR);
reg = cqspi_calc_rdreg(nor, nor->program_opcode);
reg = cqspi_calc_rdreg(nor);
writel(reg, reg_base + CQSPI_REG_RD_INSTR);
reg = readl(reg_base + CQSPI_REG_SIZE);
@ -1050,7 +1050,7 @@ static int cqspi_erase(struct spi_nor *nor, loff_t offs)
return ret;
/* Send write enable, then erase commands. */
ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
if (ret)
return ret;
@ -1080,18 +1080,19 @@ static void cqspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
mutex_unlock(&cqspi->bus_mutex);
}
static int cqspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int cqspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len)
{
int ret;
ret = cqspi_set_protocol(nor, 0);
if (!ret)
ret = cqspi_command_read(nor, &opcode, 1, buf, len);
ret = cqspi_command_read(nor, opcode, buf, len);
return ret;
}
static int cqspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int cqspi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len)
{
int ret;
@ -1216,6 +1217,16 @@ static void cqspi_request_mmap_dma(struct cqspi_st *cqspi)
init_completion(&cqspi->rx_dma_complete);
}
static const struct spi_nor_controller_ops cqspi_controller_ops = {
.prepare = cqspi_prep,
.unprepare = cqspi_unprep,
.read_reg = cqspi_read_reg,
.write_reg = cqspi_write_reg,
.read = cqspi_read,
.write = cqspi_write,
.erase = cqspi_erase,
};
static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
{
struct platform_device *pdev = cqspi->pdev;
@ -1265,14 +1276,7 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
nor->dev = dev;
spi_nor_set_flash_node(nor, np);
nor->priv = f_pdata;
nor->read_reg = cqspi_read_reg;
nor->write_reg = cqspi_write_reg;
nor->read = cqspi_read;
nor->write = cqspi_write;
nor->erase = cqspi_erase;
nor->prepare = cqspi_prep;
nor->unprepare = cqspi_unprep;
nor->controller_ops = &cqspi_controller_ops;
mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d",
dev_name(dev), cs);
@ -1366,10 +1370,8 @@ static int cqspi_probe(struct platform_device *pdev)
/* Obtain IRQ line. */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "Cannot obtain IRQ.\n");
if (irq < 0)
return -ENXIO;
}
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);

View file

@ -177,7 +177,7 @@ static void hisi_spi_nor_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
}
static int hisi_spi_nor_op_reg(struct spi_nor *nor,
u8 opcode, int len, u8 optype)
u8 opcode, size_t len, u8 optype)
{
struct hifmc_priv *priv = nor->priv;
struct hifmc_host *host = priv->host;
@ -200,7 +200,7 @@ static int hisi_spi_nor_op_reg(struct spi_nor *nor,
}
static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
int len)
size_t len)
{
struct hifmc_priv *priv = nor->priv;
struct hifmc_host *host = priv->host;
@ -215,7 +215,7 @@ static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
}
static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode,
u8 *buf, int len)
const u8 *buf, size_t len)
{
struct hifmc_priv *priv = nor->priv;
struct hifmc_host *host = priv->host;
@ -311,6 +311,15 @@ static ssize_t hisi_spi_nor_write(struct spi_nor *nor, loff_t to,
return len;
}
static const struct spi_nor_controller_ops hisi_controller_ops = {
.prepare = hisi_spi_nor_prep,
.unprepare = hisi_spi_nor_unprep,
.read_reg = hisi_spi_nor_read_reg,
.write_reg = hisi_spi_nor_write_reg,
.read = hisi_spi_nor_read,
.write = hisi_spi_nor_write,
};
/**
* Get spi flash device information and register it as a mtd device.
*/
@ -357,14 +366,8 @@ static int hisi_spi_nor_register(struct device_node *np,
}
priv->host = host;
nor->priv = priv;
nor->controller_ops = &hisi_controller_ops;
nor->prepare = hisi_spi_nor_prep;
nor->unprepare = hisi_spi_nor_unprep;
nor->read_reg = hisi_spi_nor_read_reg;
nor->write_reg = hisi_spi_nor_write_reg;
nor->read = hisi_spi_nor_read;
nor->write = hisi_spi_nor_write;
nor->erase = NULL;
ret = spi_nor_scan(nor, NULL, &hwcaps);
if (ret)
return ret;

View file

@ -20,6 +20,10 @@ static const struct intel_spi_boardinfo bxt_info = {
.type = INTEL_SPI_BXT,
};
static const struct intel_spi_boardinfo cnl_info = {
.type = INTEL_SPI_CNL,
};
static int intel_spi_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@ -61,6 +65,7 @@ static void intel_spi_pci_remove(struct pci_dev *pdev)
static const struct pci_device_id intel_spi_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
@ -68,6 +73,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
{ },
};
MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);

View file

@ -108,6 +108,10 @@
#define BXT_FREG_NUM 12
#define BXT_PR_NUM 6
#define CNL_PR 0x84
#define CNL_FREG_NUM 6
#define CNL_PR_NUM 5
#define LVSCC 0xc4
#define UVSCC 0xc8
#define ERASE_OPCODE_SHIFT 8
@ -187,12 +191,16 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
dev_dbg(ispi->dev, "PR(%d)=0x%08x\n", i,
readl(ispi->pregs + PR(i)));
value = readl(ispi->sregs + SSFSTS_CTL);
dev_dbg(ispi->dev, "SSFSTS_CTL=0x%08x\n", value);
dev_dbg(ispi->dev, "PREOP_OPTYPE=0x%08x\n",
readl(ispi->sregs + PREOP_OPTYPE));
dev_dbg(ispi->dev, "OPMENU0=0x%08x\n", readl(ispi->sregs + OPMENU0));
dev_dbg(ispi->dev, "OPMENU1=0x%08x\n", readl(ispi->sregs + OPMENU1));
if (ispi->sregs) {
value = readl(ispi->sregs + SSFSTS_CTL);
dev_dbg(ispi->dev, "SSFSTS_CTL=0x%08x\n", value);
dev_dbg(ispi->dev, "PREOP_OPTYPE=0x%08x\n",
readl(ispi->sregs + PREOP_OPTYPE));
dev_dbg(ispi->dev, "OPMENU0=0x%08x\n",
readl(ispi->sregs + OPMENU0));
dev_dbg(ispi->dev, "OPMENU1=0x%08x\n",
readl(ispi->sregs + OPMENU1));
}
if (ispi->info->type == INTEL_SPI_BYT)
dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
@ -340,6 +348,13 @@ static int intel_spi_init(struct intel_spi *ispi)
ispi->erase_64k = true;
break;
case INTEL_SPI_CNL:
ispi->sregs = NULL;
ispi->pregs = ispi->base + CNL_PR;
ispi->nregions = CNL_FREG_NUM;
ispi->pr_num = CNL_PR_NUM;
break;
default:
return -EINVAL;
}
@ -367,6 +382,11 @@ static int intel_spi_init(struct intel_spi *ispi)
!(uvscc & ERASE_64K_OPCODE_MASK))
ispi->erase_64k = false;
if (ispi->sregs == NULL && (ispi->swseq_reg || ispi->swseq_erase)) {
dev_err(ispi->dev, "software sequencer not supported, but required\n");
return -EINVAL;
}
/*
* Some controllers can only do basic operations using hardware
* sequencer. All other operations are supposed to be carried out
@ -383,7 +403,7 @@ static int intel_spi_init(struct intel_spi *ispi)
val = readl(ispi->base + HSFSTS_CTL);
ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN);
if (ispi->locked) {
if (ispi->locked && ispi->sregs) {
/*
* BIOS programs allowed opcodes and then locks down the
* register. So read back what opcodes it decided to support.
@ -426,7 +446,7 @@ static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype)
return 0;
}
static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len)
static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, size_t len)
{
u32 val, status;
int ret;
@ -469,7 +489,7 @@ static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len)
return 0;
}
static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len,
static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
int optype)
{
u32 val = 0, status;
@ -535,7 +555,8 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len,
return 0;
}
static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
size_t len)
{
struct intel_spi *ispi = nor->priv;
int ret;
@ -555,7 +576,8 @@ static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
return intel_spi_read_block(ispi, buf, len);
}
static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len)
{
struct intel_spi *ispi = nor->priv;
int ret;
@ -864,6 +886,14 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
}
}
static const struct spi_nor_controller_ops intel_spi_controller_ops = {
.read_reg = intel_spi_read_reg,
.write_reg = intel_spi_write_reg,
.read = intel_spi_read,
.write = intel_spi_write,
.erase = intel_spi_erase,
};
struct intel_spi *intel_spi_probe(struct device *dev,
struct resource *mem, const struct intel_spi_boardinfo *info)
{
@ -897,11 +927,7 @@ struct intel_spi *intel_spi_probe(struct device *dev,
ispi->nor.dev = ispi->dev;
ispi->nor.priv = ispi;
ispi->nor.read_reg = intel_spi_read_reg;
ispi->nor.write_reg = intel_spi_write_reg;
ispi->nor.read = intel_spi_read;
ispi->nor.write = intel_spi_write;
ispi->nor.erase = intel_spi_erase;
ispi->nor.controller_ops = &intel_spi_controller_ops;
ret = spi_nor_scan(&ispi->nor, NULL, &hwcaps);
if (ret) {

View file

@ -151,9 +151,9 @@ static int mtk_nor_execute_cmd(struct mtk_nor *mtk_nor, u8 cmdval)
}
static int mtk_nor_do_tx_rx(struct mtk_nor *mtk_nor, u8 op,
u8 *tx, int txlen, u8 *rx, int rxlen)
const u8 *tx, size_t txlen, u8 *rx, size_t rxlen)
{
int len = 1 + txlen + rxlen;
size_t len = 1 + txlen + rxlen;
int i, ret, idx;
if (len > MTK_NOR_MAX_SHIFT)
@ -193,7 +193,7 @@ static int mtk_nor_do_tx_rx(struct mtk_nor *mtk_nor, u8 op,
}
/* Do a WRSR (Write Status Register) command */
static int mtk_nor_wr_sr(struct mtk_nor *mtk_nor, u8 sr)
static int mtk_nor_wr_sr(struct mtk_nor *mtk_nor, const u8 sr)
{
writeb(sr, mtk_nor->base + MTK_NOR_PRGDATA5_REG);
writeb(8, mtk_nor->base + MTK_NOR_CNT_REG);
@ -354,7 +354,7 @@ static ssize_t mtk_nor_write(struct spi_nor *nor, loff_t to, size_t len,
return len;
}
static int mtk_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int mtk_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len)
{
int ret;
struct mtk_nor *mtk_nor = nor->priv;
@ -376,8 +376,8 @@ static int mtk_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
return ret;
}
static int mtk_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
int len)
static int mtk_nor_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len)
{
int ret;
struct mtk_nor *mtk_nor = nor->priv;
@ -419,6 +419,13 @@ static int mtk_nor_enable_clk(struct mtk_nor *mtk_nor)
return 0;
}
static const struct spi_nor_controller_ops mtk_controller_ops = {
.read_reg = mtk_nor_read_reg,
.write_reg = mtk_nor_write_reg,
.read = mtk_nor_read,
.write = mtk_nor_write,
};
static int mtk_nor_init(struct mtk_nor *mtk_nor,
struct device_node *flash_node)
{
@ -438,12 +445,8 @@ static int mtk_nor_init(struct mtk_nor *mtk_nor,
nor->dev = mtk_nor->dev;
nor->priv = mtk_nor;
spi_nor_set_flash_node(nor, flash_node);
nor->controller_ops = &mtk_controller_ops;
/* fill the hooks to spi nor */
nor->read = mtk_nor_read;
nor->read_reg = mtk_nor_read_reg;
nor->write = mtk_nor_write;
nor->write_reg = mtk_nor_write_reg;
nor->mtd.name = "mtk_nor";
/* initialized with NULL */
ret = spi_nor_scan(nor, NULL, &hwcaps);

View file

@ -123,7 +123,8 @@ static int nxp_spifi_set_memory_mode_on(struct nxp_spifi *spifi)
return ret;
}
static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
size_t len)
{
struct nxp_spifi *spifi = nor->priv;
u32 cmd;
@ -145,7 +146,8 @@ static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
return nxp_spifi_wait_for_cmd(spifi);
}
static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len)
{
struct nxp_spifi *spifi = nor->priv;
u32 cmd;
@ -263,9 +265,18 @@ static int nxp_spifi_setup_memory_cmd(struct nxp_spifi *spifi)
static void nxp_spifi_dummy_id_read(struct spi_nor *nor)
{
u8 id[SPI_NOR_MAX_ID_LEN];
nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
SPI_NOR_MAX_ID_LEN);
}
static const struct spi_nor_controller_ops nxp_spifi_controller_ops = {
.read_reg = nxp_spifi_read_reg,
.write_reg = nxp_spifi_write_reg,
.read = nxp_spifi_read,
.write = nxp_spifi_write,
.erase = nxp_spifi_erase,
};
static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
struct device_node *np)
{
@ -332,11 +343,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,
spifi->nor.dev = spifi->dev;
spi_nor_set_flash_node(&spifi->nor, np);
spifi->nor.priv = spifi;
spifi->nor.read = nxp_spifi_read;
spifi->nor.write = nxp_spifi_write;
spifi->nor.erase = nxp_spifi_erase;
spifi->nor.read_reg = nxp_spifi_read_reg;
spifi->nor.write_reg = nxp_spifi_write_reg;
spifi->nor.controller_ops = &nxp_spifi_controller_ops;
/*
* The first read on a hard reset isn't reliable so do a

File diff suppressed because it is too large Load diff

View file

@ -509,11 +509,9 @@ static const struct file_operations eraseblk_count_fops = {
*/
int ubi_debugfs_init_dev(struct ubi_device *ubi)
{
int err, n;
unsigned long ubi_num = ubi->ubi_num;
const char *fname;
struct dentry *dent;
struct ubi_debug_info *d = &ubi->dbg;
int n;
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
@ -522,95 +520,52 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
ubi->ubi_num);
if (n == UBI_DFS_DIR_LEN) {
/* The array size is too small */
fname = UBI_DFS_DIR_NAME;
dent = ERR_PTR(-EINVAL);
goto out;
return -EINVAL;
}
fname = d->dfs_dir_name;
dent = debugfs_create_dir(fname, dfs_rootdir);
if (IS_ERR_OR_NULL(dent))
goto out;
d->dfs_dir = dent;
d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir);
fname = "chk_gen";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_chk_gen = dent;
d->dfs_chk_gen = debugfs_create_file("chk_gen", S_IWUSR, d->dfs_dir,
(void *)ubi_num, &dfs_fops);
fname = "chk_io";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_chk_io = dent;
d->dfs_chk_io = debugfs_create_file("chk_io", S_IWUSR, d->dfs_dir,
(void *)ubi_num, &dfs_fops);
fname = "chk_fastmap";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_chk_fastmap = dent;
d->dfs_chk_fastmap = debugfs_create_file("chk_fastmap", S_IWUSR,
d->dfs_dir, (void *)ubi_num,
&dfs_fops);
fname = "tst_disable_bgt";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_disable_bgt = dent;
d->dfs_disable_bgt = debugfs_create_file("tst_disable_bgt", S_IWUSR,
d->dfs_dir, (void *)ubi_num,
&dfs_fops);
fname = "tst_emulate_bitflips";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_emulate_bitflips = dent;
d->dfs_emulate_bitflips = debugfs_create_file("tst_emulate_bitflips",
S_IWUSR, d->dfs_dir,
(void *)ubi_num,
&dfs_fops);
fname = "tst_emulate_io_failures";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_emulate_io_failures = dent;
d->dfs_emulate_io_failures = debugfs_create_file("tst_emulate_io_failures",
S_IWUSR, d->dfs_dir,
(void *)ubi_num,
&dfs_fops);
fname = "tst_emulate_power_cut";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_emulate_power_cut = dent;
d->dfs_emulate_power_cut = debugfs_create_file("tst_emulate_power_cut",
S_IWUSR, d->dfs_dir,
(void *)ubi_num,
&dfs_fops);
fname = "tst_emulate_power_cut_min";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_power_cut_min = dent;
d->dfs_power_cut_min = debugfs_create_file("tst_emulate_power_cut_min",
S_IWUSR, d->dfs_dir,
(void *)ubi_num, &dfs_fops);
fname = "tst_emulate_power_cut_max";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
&dfs_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
d->dfs_power_cut_max = dent;
d->dfs_power_cut_max = debugfs_create_file("tst_emulate_power_cut_max",
S_IWUSR, d->dfs_dir,
(void *)ubi_num, &dfs_fops);
fname = "detailed_erase_block_info";
dent = debugfs_create_file(fname, S_IRUSR, d->dfs_dir, (void *)ubi_num,
&eraseblk_count_fops);
if (IS_ERR_OR_NULL(dent))
goto out_remove;
debugfs_create_file("detailed_erase_block_info", S_IRUSR, d->dfs_dir,
(void *)ubi_num, &eraseblk_count_fops);
return 0;
out_remove:
debugfs_remove_recursive(d->dfs_dir);
out:
err = dent ? PTR_ERR(dent) : -ENODEV;
ubi_err(ubi, "cannot create \"%s\" debugfs file or directory, error %d\n",
fname, err);
return err;
}
/**

View file

@ -22,6 +22,7 @@
#define SNOR_MFR_INTEL CFI_MFR_INTEL
#define SNOR_MFR_ST CFI_MFR_ST /* ST Micro */
#define SNOR_MFR_MICRON CFI_MFR_MICRON /* Micron */
#define SNOR_MFR_ISSI CFI_MFR_PMC
#define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX
#define SNOR_MFR_SPANSION CFI_MFR_AMD
#define SNOR_MFR_SST CFI_MFR_SST
@ -133,7 +134,7 @@
#define SR_E_ERR BIT(5)
#define SR_P_ERR BIT(6)
#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */
#define SR1_QUAD_EN_BIT6 BIT(6)
/* Enhanced Volatile Configuration Register bits */
#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */
@ -144,10 +145,8 @@
#define FSR_P_ERR BIT(4) /* Program operation status */
#define FSR_PT_ERR BIT(1) /* Protection error bit */
/* Configuration Register bits. */
#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */
/* Status Register 2 bits. */
#define SR2_QUAD_EN_BIT1 BIT(1)
#define SR2_QUAD_EN_BIT7 BIT(7)
/* Supported SPI protocols */
@ -243,6 +242,9 @@ enum spi_nor_option_flags {
SNOR_F_4B_OPCODES = BIT(6),
SNOR_F_HAS_4BAIT = BIT(7),
SNOR_F_HAS_LOCK = BIT(8),
SNOR_F_HAS_16BIT_SR = BIT(9),
SNOR_F_NO_READ_CR = BIT(10),
};
/**
@ -465,6 +467,34 @@ enum spi_nor_pp_command_index {
/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
struct spi_nor;
/**
* struct spi_nor_controller_ops - SPI NOR controller driver specific
* operations.
* @prepare: [OPTIONAL] do some preparations for the
* read/write/erase/lock/unlock operations.
* @unprepare: [OPTIONAL] do some post work after the
* read/write/erase/lock/unlock operations.
* @read_reg: read out the register.
* @write_reg: write data to the register.
* @read: read data from the SPI NOR.
* @write: write data to the SPI NOR.
* @erase: erase a sector of the SPI NOR at the offset @offs; if
* not provided by the driver, spi-nor will send the erase
* opcode via write_reg().
*/
struct spi_nor_controller_ops {
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len);
ssize_t (*read)(struct spi_nor *nor, loff_t from, size_t len, u8 *buf);
ssize_t (*write)(struct spi_nor *nor, loff_t to, size_t len,
const u8 *buf);
int (*erase)(struct spi_nor *nor, loff_t offs);
};
/**
* struct spi_nor_locking_ops - SPI NOR locking methods
* @lock: lock a region of the SPI NOR.
@ -549,19 +579,7 @@ struct flash_info;
* @read_proto: the SPI protocol for read operations
* @write_proto: the SPI protocol for write operations
* @reg_proto the SPI protocol for read_reg/write_reg/erase operations
* @prepare: [OPTIONAL] do some preparations for the
* read/write/erase/lock/unlock operations
* @unprepare: [OPTIONAL] do some post work after the
* read/write/erase/lock/unlock operations
* @read_reg: [DRIVER-SPECIFIC] read out the register
* @write_reg: [DRIVER-SPECIFIC] write data to the register
* @read: [DRIVER-SPECIFIC] read data from the SPI NOR
* @write: [DRIVER-SPECIFIC] write data to the SPI NOR
* @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR
* at the offset @offs; if not provided by the driver,
* spi-nor will send the erase opcode via write_reg()
* @clear_sr_bp: [FLASH-SPECIFIC] clears the Block Protection Bits from
* the SPI NOR Status Register.
* @controller_ops: SPI NOR controller driver specific operations.
* @params: [FLASH-SPECIFIC] SPI-NOR flash parameters and settings.
* The structure includes legacy flash parameters and
* settings that can be overwritten by the spi_nor_fixups
@ -588,18 +606,8 @@ struct spi_nor {
bool sst_write_second;
u32 flags;
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
const struct spi_nor_controller_ops *controller_ops;
ssize_t (*read)(struct spi_nor *nor, loff_t from,
size_t len, u_char *read_buf);
ssize_t (*write)(struct spi_nor *nor, loff_t to,
size_t len, const u_char *write_buf);
int (*erase)(struct spi_nor *nor, loff_t offs);
int (*clear_sr_bp)(struct spi_nor *nor);
struct spi_nor_flash_parameter params;
void *priv;

View file

@ -13,6 +13,7 @@ enum intel_spi_type {
INTEL_SPI_BYT = 1,
INTEL_SPI_LPT,
INTEL_SPI_BXT,
INTEL_SPI_CNL,
};
/**