Merge tag 'mtd/for-4.21' of git://git.infradead.org/linux-mtd

Pull mtd updates from Boris Brezillon:
 "SPI NOR Core changes:
   - Parse the 4BAIT SFDP section
   - Add a bunch of SPI NOR entries to the flash_info table
   - Add the concept of SFDP fixups and use it to fix a bug on MX25L25635F
   - A bunch of minor cleanups/comestic changes

  NAND core changes:
   - kernel-doc miscellaneous fixes.
   - Third batch of fixes/cleanup to the raw NAND core impacting various
     controller drivers (ams-delta, marvell, fsmc, denali, tegra,
     vf610):
      * Stop to pass mtd_info objects to internal functions
      * Reorganize code to avoid forward declarations
      * Drop useless test in nand_legacy_set_defaults()
      * Move nand_exec_op() to internal.h
      * Add nand_[de]select_target() helpers
      * Pass the CS line to be selected in struct nand_operation
      * Make ->select_chip() optional when ->exec_op() is implemented
      * Deprecate the ->select_chip() hook
      * Move the ->exec_op() method to nand_controller_ops
      * Move ->setup_data_interface() to nand_controller_ops
      * Deprecate the dummy_controller field
      * Fix JEDEC detection
      * Provide a helper for polling GPIO R/B pin

  Raw NAND chip drivers changes:
   - Macronix:
      * Flag 1.8V AC chips with a broken GET_FEATURES(TIMINGS)

  Raw NAND controllers drivers changes:
   - Ams-delta:
      * Fix the error path
      * SPDX tag added
      * May be compiled with COMPILE_TEST=y
      * Conversion to ->exec_op() interface
      * Drop .IOADDR_R/W use
      * Use GPIO API for data I/O
   - Denali:
      * Remove denali_reset_banks()
      * Remove ->dev_ready() hook
      * Include <linux/bits.h> instead of <linux/bitops.h>
      * Changes to comply with the above fixes/cleanup done in the core.
   - FSMC:
      * Add an SPDX tag to replace the license text
      * Make conversion from chip to fsmc consistent
      * Fix unchecked return value in fsmc_read_page_hwecc
      * Changes to comply with the above fixes/cleanup done in the core.
   - Marvell:
      * Prevent timeouts on a loaded machine (fix)
      * Changes to comply with the above fixes/cleanup done in the core.
   - OMAP2:
      * Pass the parent of pdev to dma_request_chan() (fix)
   - R852:
      * Use generic DMA API
   - sh_flctl:
      * Convert to SPDX identifiers
   - Sunxi:
      * Write pageprog related opcodes to the right register: WCMD_SET (fix)
   - Tegra:
      * Stop implementing ->select_chip()
   - VF610:
      * Add an SPDX tag to replace the license text
      * Changes to comply with the above fixes/cleanup done in the core.
   - Various trivial/spelling/coding style fixes.

  SPI-NAND drivers changes:
   - Remove the depreacated mt29f_spinand driver from staging.
   - Add support for:
      * Toshiba TC58CVG2S0H
      * GigaDevice GD5FxGQ4xA
      * Winbond W25N01GV

  JFFS2 changes:
   - Fix a lockdep issue

  MTD changes:
   - Rework the physmap driver to merge gpio-addr-flash and physmap_of
     in it
   - Add a new compatible for RedBoot partitions
   - Make sub-partitions RW if the parent partition was RO because of a
     mis-alignment
   - Add pinctrl support to the
   - Addition of /* fall-through */ comments where appropriate
   - Various minor fixes and cleanups

  Other changes:
   - Update my email address"

* tag 'mtd/for-4.21' of git://git.infradead.org/linux-mtd: (108 commits)
  mtd: rawnand: sunxi: Write pageprog related opcodes to WCMD_SET
  MAINTAINERS: Update my email address
  mtd: rawnand: marvell: prevent timeouts on a loaded machine
  mtd: rawnand: omap2: Pass the parent of pdev to dma_request_chan()
  mtd: rawnand: Fix JEDEC detection
  mtd: spi-nor: Add support for is25lp016d
  mtd: spi-nor: parse SFDP 4-byte Address Instruction Table
  mtd: spi-nor: Add 4B_OPCODES flag to is25lp256
  mtd: spi-nor: Add an SPDX tag to spi-nor.{c,h}
  mtd: spi-nor: Make the enable argument passed to set_byte() a bool
  mtd: spi-nor: Stop passing flash_info around
  mtd: spi-nor: Avoid forward declaration of internal functions
  mtd: spi-nor: Drop inline on all internal helpers
  mtd: spi-nor: Add a post BFPT fixup for MX25L25635E
  mtd: spi-nor: Add a post BFPT parsing fixup hook
  mtd: spi-nor: Add the SNOR_F_4B_OPCODES flag
  mtd: spi-nor: cast to u64 to avoid uint overflows
  mtd: spi-nor: Add support for IS25LP032/064
  mtd: spi-nor: add entry for mt35xu512aba flash
  mtd: spi-nor: add macros related to MICRON flash
  ...
This commit is contained in:
Linus Torvalds
2018-12-25 12:49:46 -08:00
96 changed files with 3302 additions and 4108 deletions
+4 -3
View File
@@ -36,9 +36,10 @@ Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com>
Ben Gardner <bgardner@wabtec.com>
Ben M Cahill <ben.m.cahill@intel.com>
Björn Steinbrink <B.Steinbrink@gmx.de>
Boris Brezillon <boris.brezillon@bootlin.com> <boris.brezillon@free-electrons.com>
Boris Brezillon <boris.brezillon@bootlin.com> <b.brezillon.dev@gmail.com>
Boris Brezillon <boris.brezillon@bootlin.com> <b.brezillon@overkiz.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@free-electrons.com>
Boris Brezillon <bbrezillon@kernel.org> <b.brezillon.dev@gmail.com>
Boris Brezillon <bbrezillon@kernel.org> <b.brezillon@overkiz.com>
Brian Avery <b.avery@hp.com>
Brian King <brking@us.ibm.com>
Christoph Hellwig <hch@lst.de>
@@ -29,6 +29,8 @@ file systems on embedded devices.
- use-advanced-sector-protection: boolean to enable support for the
advanced sector protection (Spansion: PPB - Persistent Protection
Bits) locking.
- addr-gpios : (optional) List of GPIO descriptors that will be used to
address the MSBs address lines. The order goes from LSB to MSB.
For JEDEC compatible devices, the following additional properties
are defined:
@@ -0,0 +1,27 @@
RedBoot FLASH Image System (FIS) Partitions
===========================================
The FLASH Image System (FIS) directory is a flash description
format closely associated with the RedBoot boot loader.
It uses one single flash eraseblock in the flash to store an index of
all images in the flash.
This block size will vary depending on flash but is typically
32 KB in size.
Required properties:
- compatible : (required) must be "redboot-fis"
- fis-index-block : (required) a index to the eraseblock containing
the FIS directory on this device. On a flash memory with 32KB
eraseblocks, 0 means the first eraseblock at 0x00000000, 1 means the
second eraseblock at 0x00008000 and so on.
Example:
flash@0 {
partitions {
compatible = "redboot-fis";
fis-index-block = <0>;
};
};
+4 -4
View File
@@ -4915,7 +4915,7 @@ F: Documentation/gpu/meson.rst
T: git git://anongit.freedesktop.org/drm/drm-misc
DRM DRIVERS FOR ATMEL HLCDC
M: Boris Brezillon <boris.brezillon@bootlin.com>
M: Boris Brezillon <bbrezillon@kernel.org>
L: dri-devel@lists.freedesktop.org
S: Supported
F: drivers/gpu/drm/atmel-hlcdc/
@@ -8998,7 +8998,7 @@ F: include/uapi/drm/armada_drm.h
F: Documentation/devicetree/bindings/display/armada/
MARVELL CRYPTO DRIVER
M: Boris Brezillon <boris.brezillon@bootlin.com>
M: Boris Brezillon <bbrezillon@kernel.org>
M: Arnaud Ebalard <arno@natisbad.org>
F: drivers/crypto/marvell/
S: Maintained
@@ -9709,7 +9709,7 @@ F: mm/
MEMORY TECHNOLOGY DEVICES (MTD)
M: David Woodhouse <dwmw2@infradead.org>
M: Brian Norris <computersforpeace@gmail.com>
M: Boris Brezillon <boris.brezillon@bootlin.com>
M: Boris Brezillon <bbrezillon@kernel.org>
M: Marek Vasut <marek.vasut@gmail.com>
M: Richard Weinberger <richard@nod.at>
L: linux-mtd@lists.infradead.org
@@ -10296,7 +10296,7 @@ S: Supported
F: drivers/net/ethernet/myricom/myri10ge/
NAND FLASH SUBSYSTEM
M: Boris Brezillon <boris.brezillon@bootlin.com>
M: Boris Brezillon <bbrezillon@kernel.org>
M: Miquel Raynal <miquel.raynal@bootlin.com>
R: Richard Weinberger <richard@nod.at>
L: linux-mtd@lists.infradead.org
+10 -12
View File
@@ -296,23 +296,13 @@ struct modem_private_data {
static struct modem_private_data modem_priv;
static struct resource ams_delta_nand_resources[] = {
[0] = {
.start = OMAP1_MPUIO_BASE,
.end = OMAP1_MPUIO_BASE +
OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device ams_delta_nand_device = {
.name = "ams-delta-nand",
.id = -1,
.num_resources = ARRAY_SIZE(ams_delta_nand_resources),
.resource = ams_delta_nand_resources,
};
#define OMAP_GPIO_LABEL "gpio-0-15"
#define OMAP_GPIO_LABEL "gpio-0-15"
#define OMAP_MPUIO_LABEL "mpuio"
static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
.table = {
@@ -324,6 +314,14 @@ static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 0, "data", 0, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 1, "data", 1, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 2, "data", 2, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 3, "data", 3, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 4, "data", 4, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 5, "data", 5, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 6, "data", 6, 0),
GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 7, "data", 7, 0),
{ },
},
};
+1 -51
View File
@@ -22,56 +22,6 @@ config MTD_TESTS
WARNING: some of the tests will ERASE entire MTD device which they
test. Do not use these tests unless you really know what you do.
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
help
RedBoot is a ROM monitor and bootloader which deals with multiple
'images' in flash devices by putting a table one of the erase
blocks on the device, similar to a partition table, which gives
the offsets, lengths and names of all the images stored in the
flash.
If you need code which can detect and parse this table, and register
MTD 'partitions' corresponding to each image in the table, enable
this option.
You will still need the parsing functions to be called by the driver
for your particular device. It won't happen automatically. The
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
example.
if MTD_REDBOOT_PARTS
config MTD_REDBOOT_DIRECTORY_BLOCK
int "Location of RedBoot partition table"
default "-1"
help
This option is the Linux counterpart to the
CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK RedBoot compile time
option.
The option specifies which Flash sectors holds the RedBoot
partition table. A zero or positive value gives an absolute
erase block number. A negative value specifies a number of
sectors before the end of the device.
For example "2" means block number 2, "-1" means the last
block and "-2" means the penultimate block.
config MTD_REDBOOT_PARTS_UNALLOCATED
bool "Include unallocated flash regions"
help
If you need to register each unallocated flash region as a MTD
'partition', enable this option.
config MTD_REDBOOT_PARTS_READONLY
bool "Force read-only for RedBoot system images"
help
If you need to force read-only for 'RedBoot', 'RedBoot Config' and
'FIS directory' images, enable this option.
endif # MTD_REDBOOT_PARTS
config MTD_CMDLINE_PARTS
tristate "Command line partition table parsing"
depends on MTD
@@ -144,7 +94,7 @@ config MTD_BCM63XX_PARTS
depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
select CRC32
help
This provides partions parsing for BCM63xx devices with CFE
This provides partition parsing for BCM63xx devices with CFE
bootloaders.
config MTD_BCM47XX_PARTS
-1
View File
@@ -8,7 +8,6 @@ obj-$(CONFIG_MTD) += mtd.o
mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
+6
View File
@@ -324,6 +324,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
case FL_JEDEC_QUERY:
map_write(map, CMD(0x70), cmd_addr);
chip->state = FL_STATUS;
/* Fall through */
case FL_STATUS:
status = map_read(map, cmd_addr);
@@ -461,6 +462,7 @@ static int do_write_buffer(struct map_info *map, struct flchip *chip,
#ifdef DEBUG_CFI_FEATURES
printk("%s: 1 status[%x]\n", __func__, map_read(map, cmd_adr));
#endif
/* Fall through */
case FL_STATUS:
status = map_read(map, cmd_adr);
@@ -754,6 +756,7 @@ retry:
case FL_READY:
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
/* Fall through */
case FL_STATUS:
status = map_read(map, adr);
@@ -995,6 +998,7 @@ static void cfi_staa_sync (struct mtd_info *mtd)
* as the whole point is that nobody can do anything
* with the chip now anyway.
*/
/* Fall through */
case FL_SYNCING:
mutex_unlock(&chip->mutex);
break;
@@ -1050,6 +1054,7 @@ retry:
case FL_READY:
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
/* Fall through */
case FL_STATUS:
status = map_read(map, adr);
@@ -1196,6 +1201,7 @@ retry:
case FL_READY:
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
/* Fall through */
case FL_STATUS:
status = map_read(map, adr);
+2
View File
@@ -329,8 +329,10 @@ static int ustrtoul(const char *cp, char **endp, unsigned int base)
switch (**endp) {
case 'G' :
result *= 1024;
/* fall through */
case 'M':
result *= 1024;
/* fall through */
case 'K':
case 'k':
result *= 1024;
+8 -8
View File
@@ -1603,7 +1603,7 @@ static void doc_unregister_sysfs(struct platform_device *pdev,
/*
* Debug sysfs entries
*/
static int dbg_flashctrl_show(struct seq_file *s, void *p)
static int flashcontrol_show(struct seq_file *s, void *p)
{
struct docg3 *docg3 = (struct docg3 *)s->private;
@@ -1623,9 +1623,9 @@ static int dbg_flashctrl_show(struct seq_file *s, void *p)
return 0;
}
DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show);
DEFINE_SHOW_ATTRIBUTE(flashcontrol);
static int dbg_asicmode_show(struct seq_file *s, void *p)
static int asic_mode_show(struct seq_file *s, void *p)
{
struct docg3 *docg3 = (struct docg3 *)s->private;
@@ -1660,9 +1660,9 @@ static int dbg_asicmode_show(struct seq_file *s, void *p)
seq_puts(s, ")\n");
return 0;
}
DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show);
DEFINE_SHOW_ATTRIBUTE(asic_mode);
static int dbg_device_id_show(struct seq_file *s, void *p)
static int device_id_show(struct seq_file *s, void *p)
{
struct docg3 *docg3 = (struct docg3 *)s->private;
int id;
@@ -1674,9 +1674,9 @@ static int dbg_device_id_show(struct seq_file *s, void *p)
seq_printf(s, "DeviceId = %d\n", id);
return 0;
}
DEBUGFS_RO_ATTR(device_id, dbg_device_id_show);
DEFINE_SHOW_ATTRIBUTE(device_id);
static int dbg_protection_show(struct seq_file *s, void *p)
static int protection_show(struct seq_file *s, void *p)
{
struct docg3 *docg3 = (struct docg3 *)s->private;
int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high;
@@ -1726,7 +1726,7 @@ static int dbg_protection_show(struct seq_file *s, void *p)
!!(dps1 & DOC_DPS_KEY_OK));
return 0;
}
DEBUGFS_RO_ATTR(protection, dbg_protection_show);
DEFINE_SHOW_ATTRIBUTE(protection);
static void __init doc_dbg_register(struct mtd_info *floor)
{
-11
View File
@@ -317,17 +317,6 @@ struct docg3 {
#define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg)
#define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg)
#define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg)
#define DEBUGFS_RO_ATTR(name, show_fct) \
static int name##_open(struct inode *inode, struct file *file) \
{ return single_open(file, show_fct, inode->i_private); } \
static const struct file_operations name##_fops = { \
.owner = THIS_MODULE, \
.open = name##_open, \
.llseek = seq_lseek, \
.read = seq_read, \
.release = single_release \
};
#endif
/*
+14 -23
View File
@@ -66,15 +66,15 @@ config MTD_PHYSMAP_BANKWIDTH
used internally by the CFI drivers.
config MTD_PHYSMAP_OF
tristate "Memory device in physical memory map based on OF description"
depends on OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_RAM)
bool "Memory device in physical memory map based on OF description"
depends on OF && MTD_PHYSMAP
help
This provides a 'mapping' driver which allows the NOR Flash, ROM
and RAM driver code to communicate with chips which are mapped
physically into the CPU's memory. The mapping description here is
taken from OF device tree.
config MTD_PHYSMAP_OF_VERSATILE
config MTD_PHYSMAP_VERSATILE
bool "ARM Versatile OF-based physical memory map handling"
depends on MTD_PHYSMAP_OF
depends on MFD_SYSCON
@@ -84,16 +84,26 @@ config MTD_PHYSMAP_OF_VERSATILE
platforms, basically to add a VPP (write protection) callback so
the flash can be taken out of write protection.
config MTD_PHYSMAP_OF_GEMINI
config MTD_PHYSMAP_GEMINI
bool "Cortina Gemini OF-based physical memory map handling"
depends on MTD_PHYSMAP_OF
depends on MFD_SYSCON
select MTD_COMPLEX_MAPPINGS
default ARCH_GEMINI
help
This provides some extra DT physmap parsing for the Gemini
platforms, some detection and setting up parallel mode on the
external interface.
config MTD_PHYSMAP_GPIO_ADDR
bool "GPIO-assisted Flash Chip Support"
depends on MTD_PHYSMAP
depends on GPIOLIB || COMPILE_TEST
depends on MTD_COMPLEX_MAPPINGS
help
Extend the physmap driver to allow flashes to be partially
physically addressed and assisted by GPIOs.
config MTD_PMC_MSP_EVM
tristate "CFI Flash device mapped on PMC-Sierra MSP"
depends on PMC_MSP && MTD_CFI
@@ -334,16 +344,6 @@ config MTD_PCMCIA_ANONYMOUS
If unsure, say N.
config MTD_GPIO_ADDR
tristate "GPIO-assisted Flash Chip Support"
depends on GPIOLIB || COMPILE_TEST
depends on MTD_COMPLEX_MAPPINGS
help
Map driver which allows flashes to be partially physically addressed
and assisted by GPIOs.
If compiled as a module, it will be called gpio-addr-flash.
config MTD_UCLINUX
bool "Generic uClinux RAM/ROM filesystem support"
depends on (MTD_RAM=y || MTD_ROM=y) && (!MMU || COLDFIRE)
@@ -400,13 +400,4 @@ config MTD_PISMO
When built as a module, it will be called pismo.ko
config MTD_LATCH_ADDR
tristate "Latch-assisted Flash Chip Support"
depends on MTD_COMPLEX_MAPPINGS
help
Map driver which allows flashes to be partially physically addressed
and have the upper address lines set by a board specific code.
If compiled as a module, it will be called latch-addr-flash.
endmenu
+4 -7
View File
@@ -17,12 +17,11 @@ obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
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 := $(physmap-objs-y)
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
physmap_of-objs-y += physmap_of_core.o
physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o
physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_GEMINI) += physmap_of_gemini.o
physmap_of-objs := $(physmap_of-objs-y)
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
obj-$(CONFIG_MTD_PISMO) += pismo.o
obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
@@ -44,6 +43,4 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
obj-$(CONFIG_MTD_VMU) += vmu-flash.o
obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o
obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
-281
View File
@@ -1,281 +0,0 @@
/*
* drivers/mtd/maps/gpio-addr-flash.c
*
* Handle the case where a flash device is mostly addressed using physical
* line and supplemented by GPIOs. This way you can hook up say a 8MiB flash
* to a 2MiB memory range and use the GPIOs to select a particular range.
*
* Copyright © 2000 Nicolas Pitre <nico@cam.org>
* Copyright © 2005-2009 Analog Devices Inc.
*
* Enter bugs at http://blackfin.uclinux.org/
*
* Licensed under the GPL-2 or later.
*/
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
#define win_mask(x) ((BIT(x)) - 1)
#define DRIVER_NAME "gpio-addr-flash"
/**
* struct async_state - keep GPIO flash state
* @mtd: MTD state for this mapping
* @map: MTD map state for this flash
* @gpios: Struct containing the array of GPIO descriptors
* @gpio_values: cached GPIO values
* @win_order: dedicated memory size (if no GPIOs)
*/
struct async_state {
struct mtd_info *mtd;
struct map_info map;
struct gpio_descs *gpios;
unsigned int gpio_values;
unsigned int win_order;
};
#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1)
/**
* gf_set_gpios() - set GPIO address lines to access specified flash offset
* @state: GPIO flash state
* @ofs: desired offset to access
*
* Rather than call the GPIO framework every time, cache the last-programmed
* value. This speeds up sequential accesses (which are by far the most common
* type).
*/
static void gf_set_gpios(struct async_state *state, unsigned long ofs)
{
int i;
ofs >>= state->win_order;
if (ofs == state->gpio_values)
return;
for (i = 0; i < state->gpios->ndescs; i++) {
if ((ofs & BIT(i)) == (state->gpio_values & BIT(i)))
continue;
gpiod_set_value(state->gpios->desc[i], !!(ofs & BIT(i)));
}
state->gpio_values = ofs;
}
/**
* gf_read() - read a word at the specified offset
* @map: MTD map state
* @ofs: desired offset to read
*/
static map_word gf_read(struct map_info *map, unsigned long ofs)
{
struct async_state *state = gf_map_info_to_state(map);
uint16_t word;
map_word test;
gf_set_gpios(state, ofs);
word = readw(map->virt + (ofs & win_mask(state->win_order)));
test.x[0] = word;
return test;
}
/**
* gf_copy_from() - copy a chunk of data from the flash
* @map: MTD map state
* @to: memory to copy to
* @from: flash offset to copy from
* @len: how much to copy
*
* The "from" region may straddle more than one window, so toggle the GPIOs for
* each window region before reading its data.
*/
static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
struct async_state *state = gf_map_info_to_state(map);
int this_len;
while (len) {
this_len = from & win_mask(state->win_order);
this_len = BIT(state->win_order) - this_len;
this_len = min_t(int, len, this_len);
gf_set_gpios(state, from);
memcpy_fromio(to,
map->virt + (from & win_mask(state->win_order)),
this_len);
len -= this_len;
from += this_len;
to += this_len;
}
}
/**
* gf_write() - write a word at the specified offset
* @map: MTD map state
* @ofs: desired offset to write
*/
static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
{
struct async_state *state = gf_map_info_to_state(map);
uint16_t d;
gf_set_gpios(state, ofs);
d = d1.x[0];
writew(d, map->virt + (ofs & win_mask(state->win_order)));
}
/**
* gf_copy_to() - copy a chunk of data to the flash
* @map: MTD map state
* @to: flash offset to copy to
* @from: memory to copy from
* @len: how much to copy
*
* See gf_copy_from() caveat.
*/
static void gf_copy_to(struct map_info *map, unsigned long to,
const void *from, ssize_t len)
{
struct async_state *state = gf_map_info_to_state(map);
int this_len;
while (len) {
this_len = to & win_mask(state->win_order);
this_len = BIT(state->win_order) - this_len;
this_len = min_t(int, len, this_len);
gf_set_gpios(state, to);
memcpy_toio(map->virt + (to & win_mask(state->win_order)),
from, len);
len -= this_len;
to += this_len;
from += this_len;
}
}
static const char * const part_probe_types[] = {
"cmdlinepart", "RedBoot", NULL };
/**
* gpio_flash_probe() - setup a mapping for a GPIO assisted flash
* @pdev: platform device
*
* The platform resource layout expected looks something like:
* struct mtd_partition partitions[] = { ... };
* struct physmap_flash_data flash_data = { ... };
* static struct gpiod_lookup_table addr_flash_gpios = {
* .dev_id = "gpio-addr-flash.0",
* .table = {
* GPIO_LOOKUP_IDX("gpio.0", 15, "addr", 0, GPIO_ACTIVE_HIGH),
* GPIO_LOOKUP_IDX("gpio.0", 16, "addr", 1, GPIO_ACTIVE_HIGH),
* );
* };
* gpiod_add_lookup_table(&addr_flash_gpios);
*
* struct resource flash_resource[] = {
* {
* .name = "cfi_probe",
* .start = 0x20000000,
* .end = 0x201fffff,
* .flags = IORESOURCE_MEM,
* },
* };
* struct platform_device flash_device = {
* .name = "gpio-addr-flash",
* .dev = { .platform_data = &flash_data, },
* .num_resources = ARRAY_SIZE(flash_resource),
* .resource = flash_resource,
* ...
* };
*/
static int gpio_flash_probe(struct platform_device *pdev)
{
struct physmap_flash_data *pdata;
struct resource *memory;
struct async_state *state;
pdata = dev_get_platdata(&pdev->dev);
memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!memory)
return -EINVAL;
state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
state->gpios = devm_gpiod_get_array(&pdev->dev, "addr", GPIOD_OUT_LOW);
if (IS_ERR(state->gpios))
return PTR_ERR(state->gpios);
state->win_order = get_bitmask_order(resource_size(memory)) - 1;
state->map.name = DRIVER_NAME;
state->map.read = gf_read;
state->map.copy_from = gf_copy_from;
state->map.write = gf_write;
state->map.copy_to = gf_copy_to;
state->map.bankwidth = pdata->width;
state->map.size = BIT(state->win_order + state->gpios->ndescs);
state->map.virt = devm_ioremap_resource(&pdev->dev, memory);
if (IS_ERR(state->map.virt))
return PTR_ERR(state->map.virt);
state->map.phys = NO_XIP;
state->map.map_priv_1 = (unsigned long)state;
platform_set_drvdata(pdev, state);
dev_notice(&pdev->dev, "probing %d-bit flash bus\n",
state->map.bankwidth * 8);
state->mtd = do_map_probe(memory->name, &state->map);
if (!state->mtd)
return -ENXIO;
state->mtd->dev.parent = &pdev->dev;
mtd_device_parse_register(state->mtd, part_probe_types, NULL,
pdata->parts, pdata->nr_parts);
return 0;
}
static int gpio_flash_remove(struct platform_device *pdev)
{
struct async_state *state = platform_get_drvdata(pdev);
mtd_device_unregister(state->mtd);
map_destroy(state->mtd);
return 0;
}
static struct platform_driver gpio_flash_driver = {
.probe = gpio_flash_probe,
.remove = gpio_flash_remove,
.driver = {
.name = DRIVER_NAME,
},
};
module_platform_driver(gpio_flash_driver);
MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios");
MODULE_LICENSE("GPL");
-229
View File
@@ -1,229 +0,0 @@
/*
* Interface for NOR flash driver whose high address lines are latched
*
* Copyright © 2000 Nicolas Pitre <nico@cam.org>
* Copyright © 2005-2008 Analog Devices Inc.
* Copyright © 2008 MontaVista Software, Inc. <source@mvista.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_device.h>
#include <linux/mtd/latch-addr-flash.h>
#include <linux/slab.h>
#define DRIVER_NAME "latch-addr-flash"
struct latch_addr_flash_info {
struct mtd_info *mtd;
struct map_info map;
struct resource *res;
void (*set_window)(unsigned long offset, void *data);
void *data;
/* cache; could be found out of res */
unsigned long win_mask;
spinlock_t lock;
};
static map_word lf_read(struct map_info *map, unsigned long ofs)
{
struct latch_addr_flash_info *info;
map_word datum;
info = (struct latch_addr_flash_info *)map->map_priv_1;
spin_lock(&info->lock);
info->set_window(ofs, info->data);
datum = inline_map_read(map, info->win_mask & ofs);
spin_unlock(&info->lock);
return datum;
}
static void lf_write(struct map_info *map, map_word datum, unsigned long ofs)
{
struct latch_addr_flash_info *info;
info = (struct latch_addr_flash_info *)map->map_priv_1;
spin_lock(&info->lock);
info->set_window(ofs, info->data);
inline_map_write(map, datum, info->win_mask & ofs);
spin_unlock(&info->lock);
}
static void lf_copy_from(struct map_info *map, void *to,
unsigned long from, ssize_t len)
{
struct latch_addr_flash_info *info =
(struct latch_addr_flash_info *) map->map_priv_1;
unsigned n;
while (len > 0) {
n = info->win_mask + 1 - (from & info->win_mask);
if (n > len)
n = len;
spin_lock(&info->lock);
info->set_window(from, info->data);
memcpy_fromio(to, map->virt + (from & info->win_mask), n);
spin_unlock(&info->lock);
to += n;
from += n;
len -= n;
}
}
static char *rom_probe_types[] = { "cfi_probe", NULL };
static int latch_addr_flash_remove(struct platform_device *dev)
{
struct latch_addr_flash_info *info;
struct latch_addr_flash_data *latch_addr_data;
info = platform_get_drvdata(dev);
if (info == NULL)
return 0;
latch_addr_data = dev_get_platdata(&dev->dev);
if (info->mtd != NULL) {
mtd_device_unregister(info->mtd);
map_destroy(info->mtd);
}
if (info->map.virt != NULL)
iounmap(info->map.virt);
if (info->res != NULL)
release_mem_region(info->res->start, resource_size(info->res));
kfree(info);
if (latch_addr_data->done)
latch_addr_data->done(latch_addr_data->data);
return 0;
}
static int latch_addr_flash_probe(struct platform_device *dev)
{
struct latch_addr_flash_data *latch_addr_data;
struct latch_addr_flash_info *info;
resource_size_t win_base = dev->resource->start;
resource_size_t win_size = resource_size(dev->resource);
char **probe_type;
int chipsel;
int err;
latch_addr_data = dev_get_platdata(&dev->dev);
if (latch_addr_data == NULL)
return -ENODEV;
pr_notice("latch-addr platform flash device: %#llx byte "
"window at %#.8llx\n",
(unsigned long long)win_size, (unsigned long long)win_base);
chipsel = dev->id;
if (latch_addr_data->init) {
err = latch_addr_data->init(latch_addr_data->data, chipsel);
if (err != 0)
return err;
}
info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
goto done;
}
platform_set_drvdata(dev, info);
info->res = request_mem_region(win_base, win_size, DRIVER_NAME);
if (info->res == NULL) {
dev_err(&dev->dev, "Could not reserve memory region\n");
err = -EBUSY;
goto free_info;
}
info->map.name = DRIVER_NAME;
info->map.size = latch_addr_data->size;
info->map.bankwidth = latch_addr_data->width;
info->map.phys = NO_XIP;
info->map.virt = ioremap(win_base, win_size);
if (!info->map.virt) {
err = -ENOMEM;
goto free_res;
}
info->map.map_priv_1 = (unsigned long)info;
info->map.read = lf_read;
info->map.copy_from = lf_copy_from;
info->map.write = lf_write;
info->set_window = latch_addr_data->set_window;
info->data = latch_addr_data->data;
info->win_mask = win_size - 1;
spin_lock_init(&info->lock);
for (probe_type = rom_probe_types; !info->mtd && *probe_type;
probe_type++)
info->mtd = do_map_probe(*probe_type, &info->map);
if (info->mtd == NULL) {
dev_err(&dev->dev, "map_probe failed\n");
err = -ENODEV;
goto iounmap;
}
info->mtd->dev.parent = &dev->dev;
mtd_device_register(info->mtd, latch_addr_data->parts,
latch_addr_data->nr_parts);
return 0;
iounmap:
iounmap(info->map.virt);
free_res:
release_mem_region(info->res->start, resource_size(info->res));
free_info:
kfree(info);
done:
if (latch_addr_data->done)
latch_addr_data->done(latch_addr_data->data);
return err;
}
static struct platform_driver latch_addr_flash_driver = {
.probe = latch_addr_flash_probe,
.remove = latch_addr_flash_remove,
.driver = {
.name = DRIVER_NAME,
},
};
module_platform_driver(latch_addr_flash_driver);
MODULE_AUTHOR("David Griego <dgriego@mvista.com>");
MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
"address lines being set board specifically");
MODULE_LICENSE("GPL v2");
File diff suppressed because it is too large Load Diff
@@ -10,10 +10,12 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mtd/map.h>
#include <linux/mtd/xip.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/bitops.h>
#include "physmap_of_gemini.h"
#include <linux/pinctrl/consumer.h>
#include "physmap-gemini.h"
/*
* The Flash-relevant parts of the global status register
@@ -44,6 +46,82 @@
#define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */
static const struct of_device_id syscon_match[] = {
{ .compatible = "cortina,gemini-syscon" },
{ },
};
struct gemini_flash {
struct device *dev;
struct pinctrl *p;
struct pinctrl_state *enabled_state;
struct pinctrl_state *disabled_state;
};
/* Static local state */
static struct gemini_flash *gf;
static void gemini_flash_enable_pins(void)
{
int ret;
if (IS_ERR(gf->enabled_state))
return;
ret = pinctrl_select_state(gf->p, gf->enabled_state);
if (ret)
dev_err(gf->dev, "failed to enable pins\n");
}
static void gemini_flash_disable_pins(void)
{
int ret;
if (IS_ERR(gf->disabled_state))
return;
ret = pinctrl_select_state(gf->p, gf->disabled_state);
if (ret)
dev_err(gf->dev, "failed to disable pins\n");
}
static map_word __xipram gemini_flash_map_read(struct map_info *map,
unsigned long ofs)
{
map_word __xipram ret;
gemini_flash_enable_pins();
ret = inline_map_read(map, ofs);
gemini_flash_disable_pins();
return ret;
}
static void __xipram gemini_flash_map_write(struct map_info *map,
const map_word datum,
unsigned long ofs)
{
gemini_flash_enable_pins();
inline_map_write(map, datum, ofs);
gemini_flash_disable_pins();
}
static void __xipram gemini_flash_map_copy_from(struct map_info *map,
void *to, unsigned long from,
ssize_t len)
{
gemini_flash_enable_pins();
inline_map_copy_from(map, to, from, len);
gemini_flash_disable_pins();
}
static void __xipram gemini_flash_map_copy_to(struct map_info *map,
unsigned long to,
const void *from, ssize_t len)
{
gemini_flash_enable_pins();
inline_map_copy_to(map, to, from, len);
gemini_flash_disable_pins();
}
int of_flash_probe_gemini(struct platform_device *pdev,
struct device_node *np,
struct map_info *map)
@@ -57,6 +135,11 @@ int of_flash_probe_gemini(struct platform_device *pdev,
if (!of_device_is_compatible(np, "cortina,gemini-flash"))
return 0;
gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL);
if (!gf)
return -ENOMEM;
gf->dev = dev;
rmap = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(rmap)) {
dev_err(dev, "no syscon\n");
@@ -91,7 +174,32 @@ int of_flash_probe_gemini(struct platform_device *pdev,
map->bankwidth * 8);
}
dev_info(&pdev->dev, "initialized Gemini-specific physmap control\n");
gf->p = devm_pinctrl_get(dev);
if (IS_ERR(gf->p)) {
dev_err(dev, "no pinctrl handle\n");
ret = PTR_ERR(gf->p);
return ret;
}
gf->enabled_state = pinctrl_lookup_state(gf->p, "enabled");
if (IS_ERR(gf->enabled_state))
dev_err(dev, "no enabled pin control state\n");
gf->disabled_state = pinctrl_lookup_state(gf->p, "disabled");
if (IS_ERR(gf->enabled_state)) {
dev_err(dev, "no disabled pin control state\n");
} else {
ret = pinctrl_select_state(gf->p, gf->disabled_state);
if (ret)
dev_err(gf->dev, "failed to disable pins\n");
}
map->read = gemini_flash_map_read;
map->write = gemini_flash_map_write;
map->copy_from = gemini_flash_map_copy_from;
map->copy_to = gemini_flash_map_copy_to;
dev_info(dev, "initialized Gemini-specific physmap control\n");
return 0;
}
@@ -2,7 +2,7 @@
#include <linux/of.h>
#include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PHYSMAP_OF_GEMINI
#ifdef CONFIG_MTD_PHYSMAP_GEMINI
int of_flash_probe_gemini(struct platform_device *pdev,
struct device_node *np,
struct map_info *map);
@@ -28,7 +28,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/bitops.h>
#include "physmap_of_versatile.h"
#include "physmap-versatile.h"
static struct regmap *syscon_regmap;
@@ -2,7 +2,7 @@
#include <linux/of.h>
#include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE
#ifdef CONFIG_MTD_PHYSMAP_VERSATILE
int of_flash_probe_versatile(struct platform_device *pdev,
struct device_node *np,
struct map_info *map);

Some files were not shown because too many files have changed in this diff Show More