You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'for-linus-20160112' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"Generic MTD:
- populate the MTD device 'of_node' field (and get a proper 'of_node'
symlink in sysfs)
This yielded some new helper functions, and changes across a
variety of drivers
- partitioning cleanups, to prepare for better device-tree based
partitioning in the future
Eliminate a lot of boilerplate for drivers that want to use
OF-based partition parsing
The DT bindings for this didn't settle yet, so most non-cleanup
portions are deferred for a future release
NAND:
- embed a struct mtd_info inside struct nand_chip
This is really long overdue; too many drivers have to do the same
silly boilerplate to allocate and link up two "independent"
structs, when in fact, everyone is assuming there is an exact 1:1
relationship between a NAND chips struct and its underlying MTD.
This aids improved helpers and should make certain abstractions
easier in the future.
Also causes a lot of churn, helped along by some automated code
transformations
- add more core support for detecting (and "correcting") bitflips in
erased pages; requires opt-in by drivers, but at least we kill a
few bad implementations and hopefully stave off future ones
- pxa3xx_nand: cleanups, a few fixes, and PM improvements
- new JZ4780 NAND driver
SPI NOR:
- provide default erase function, for controllers that just want to
send the SECTOR_ERASE command directly
- fix some module auto-loading issues with device tree
("jedec,spi-nor")
- error handling fixes
- new Mediatek QSPI flash driver
Other:
- cfi: force valid geometry Kconfig (finally!)
This one used to trip up randconfigs occasionally, since bots
aren't deterred by big scary "advanced configuration" menus
More? Probably. See the commit logs"
* tag 'for-linus-20160112' of git://git.infradead.org/linux-mtd: (168 commits)
mtd: jz4780_nand: replace if/else blocks with switch/case
mtd: nand: jz4780: Update ecc correction error codes
mtd: nandsim: use nand_get_controller_data()
mtd: jz4780_nand: remove useless mtd->priv = chip assignment
staging: mt29f_spinand: make use of nand_set/get_controller_data() helpers
mtd: nand: make use of nand_set/get_controller_data() helpers
ARM: make use of nand_set/get_controller_data() helpers
mtd: nand: add helpers to access ->priv
mtd: nand: jz4780: driver for NAND devices on JZ4780 SoCs
mtd: nand: jz4740: remove custom 'erased check' implementation
mtd: nand: diskonchip: remove custom 'erased check' implementation
mtd: nand: davinci: remove custom 'erased check' implementation
mtd: nand: use nand_check_erased_ecc_chunk in default ECC read functions
mtd: nand: return consistent error codes in ecc.correct() implementations
doc: dt: mtd: new binding for jz4780-{nand,bch}
mtd: cfi_cmdset_0001: fixing memory leak and handling failed kmalloc
mtd: spi-nor: wait until lock/unlock operations are ready
mtd: tests: consolidate kmalloc/memset 0 call to kzalloc
jffs2: use to_delayed_work
mtd: nand: assign reasonable default name for NAND drivers
...
This commit is contained in:
@@ -162,12 +162,15 @@
|
||||
<sect1 id="Basic_defines">
|
||||
<title>Basic defines</title>
|
||||
<para>
|
||||
At least you have to provide a mtd structure and
|
||||
a storage for the ioremap'ed chip address.
|
||||
You can allocate the mtd structure using kmalloc
|
||||
or you can allocate it statically.
|
||||
In case of static allocation you have to allocate
|
||||
a nand_chip structure too.
|
||||
At least you have to provide a nand_chip structure
|
||||
and a storage for the ioremap'ed chip address.
|
||||
You can allocate the nand_chip structure using
|
||||
kmalloc or you can allocate it statically.
|
||||
The NAND chip structure embeds an mtd structure
|
||||
which will be registered to the MTD subsystem.
|
||||
You can extract a pointer to the mtd structure
|
||||
from a nand_chip pointer using the nand_to_mtd()
|
||||
helper.
|
||||
</para>
|
||||
<para>
|
||||
Kmalloc based example
|
||||
@@ -180,7 +183,6 @@ static void __iomem *baseaddr;
|
||||
Static example
|
||||
</para>
|
||||
<programlisting>
|
||||
static struct mtd_info board_mtd;
|
||||
static struct nand_chip board_chip;
|
||||
static void __iomem *baseaddr;
|
||||
</programlisting>
|
||||
@@ -235,7 +237,7 @@ static void board_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
<programlisting>
|
||||
static void board_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *) mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
switch(cmd){
|
||||
case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT; break;
|
||||
case NAND_CTL_CLRCLE: this->IO_ADDR_W &= ~CLE_ADRR_BIT; break;
|
||||
@@ -274,13 +276,15 @@ static int __init board_init (void)
|
||||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
board_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!board_mtd) {
|
||||
this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!this) {
|
||||
printk ("Unable to allocate NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
board_mtd = nand_to_mtd(this);
|
||||
|
||||
/* map physical address */
|
||||
baseaddr = ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
|
||||
if (!baseaddr) {
|
||||
@@ -289,11 +293,6 @@ static int __init board_init (void)
|
||||
goto out_mtd;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) ();
|
||||
/* Link the private data with the MTD structure */
|
||||
board_mtd->priv = this;
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = baseaddr;
|
||||
this->IO_ADDR_W = baseaddr;
|
||||
@@ -317,7 +316,7 @@ static int __init board_init (void)
|
||||
out_ior:
|
||||
iounmap(baseaddr);
|
||||
out_mtd:
|
||||
kfree (board_mtd);
|
||||
kfree (this);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@@ -343,7 +342,7 @@ static void __exit board_cleanup (void)
|
||||
iounmap(baseaddr);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (board_mtd);
|
||||
kfree (mtd_to_nand(board_mtd));
|
||||
}
|
||||
module_exit(board_cleanup);
|
||||
#endif
|
||||
@@ -399,7 +398,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
|
||||
<programlisting>
|
||||
static void board_select_chip (struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *) mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
/* Deselect all chips */
|
||||
this->IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK;
|
||||
|
||||
@@ -45,6 +45,8 @@ Required properties:
|
||||
- #size-cells : <0>
|
||||
|
||||
Optional properties:
|
||||
- clock : reference to the clock for the NAND controller
|
||||
- clock-names : "nand" (required for the above clock)
|
||||
- brcm,nand-has-wp : Some versions of this IP include a write-protect
|
||||
(WP) control bit. It is always available on >=
|
||||
v7.0. Use this property to describe the rare
|
||||
@@ -72,6 +74,12 @@ we define additional 'compatible' properties and associated register resources w
|
||||
and enable registers
|
||||
- reg-names: (required) "nand-int-base"
|
||||
|
||||
* "brcm,nand-bcm6368"
|
||||
- compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm6368"
|
||||
- reg: (required) the 'NAND_INTR_BASE' register range, with combined status
|
||||
and enable registers, and boot address registers
|
||||
- reg-names: (required) "nand-int-base"
|
||||
|
||||
* "brcm,nand-iproc"
|
||||
- reg: (required) the "IDM" register range, for interrupt enable and APB
|
||||
bus access endianness configuration, and the "EXT" register range,
|
||||
@@ -148,3 +156,27 @@ nand@f0442800 {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nand@10000200 {
|
||||
compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
|
||||
"brcm,brcmnand-v4.0", "brcm,brcmnand";
|
||||
reg = <0x10000200 0x180>,
|
||||
<0x10000600 0x200>,
|
||||
<0x100000b0 0x10>;
|
||||
reg-names = "nand", "nand-cache", "nand-int-base";
|
||||
interrupt-parent = <&periph_intc>;
|
||||
interrupts = <50>;
|
||||
clocks = <&periph_clk 20>;
|
||||
clock-names = "nand";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand0: nandcs@0 {
|
||||
compatible = "brcm,nandcs";
|
||||
reg = <0>;
|
||||
nand-on-flash-bbt;
|
||||
nand-ecc-strength = <1>;
|
||||
nand-ecc-step-size = <512>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
* Ingenic JZ4780 NAND/BCH
|
||||
|
||||
This file documents the device tree bindings for NAND flash devices on the
|
||||
JZ4780. NAND devices are connected to the NEMC controller (described in
|
||||
memory-controllers/ingenic,jz4780-nemc.txt), and thus NAND device nodes must
|
||||
be children of the NEMC node.
|
||||
|
||||
Required NAND controller device properties:
|
||||
- compatible: Should be set to "ingenic,jz4780-nand".
|
||||
- reg: For each bank with a NAND chip attached, should specify a bank number,
|
||||
an offset of 0 and a size of 0x1000000 (i.e. the whole NEMC bank).
|
||||
|
||||
Optional NAND controller device properties:
|
||||
- ingenic,bch-controller: To make use of the hardware BCH controller, this
|
||||
property must contain a phandle for the BCH controller node. The required
|
||||
properties for this node are described below. If this is not specified,
|
||||
software BCH will be used instead.
|
||||
|
||||
Optional children nodes:
|
||||
- Individual NAND chips are children of the NAND controller node.
|
||||
|
||||
Required children node properties:
|
||||
- reg: An integer ranging from 1 to 6 representing the CS line to use.
|
||||
|
||||
Optional children node properties:
|
||||
- nand-ecc-step-size: ECC block size in bytes.
|
||||
- nand-ecc-strength: ECC strength (max number of correctable bits).
|
||||
- nand-ecc-mode: String, operation mode of the NAND ecc mode. "hw" by default
|
||||
- nand-on-flash-bbt: boolean to enable on flash bbt option, if not present false
|
||||
- rb-gpios: GPIO specifier for the busy pin.
|
||||
- wp-gpios: GPIO specifier for the write protect pin.
|
||||
|
||||
Optional child node of NAND chip nodes:
|
||||
- partitions: see Documentation/devicetree/bindings/mtd/partition.txt
|
||||
|
||||
Example:
|
||||
|
||||
nemc: nemc@13410000 {
|
||||
...
|
||||
|
||||
nandc: nand-controller@1 {
|
||||
compatible = "ingenic,jz4780-nand";
|
||||
reg = <1 0 0x1000000>; /* Bank 1 */
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ingenic,bch-controller = <&bch>;
|
||||
|
||||
nand@1 {
|
||||
reg = <1>;
|
||||
|
||||
nand-ecc-step-size = <1024>;
|
||||
nand-ecc-strength = <24>;
|
||||
nand-ecc-mode = "hw";
|
||||
nand-on-flash-bbt;
|
||||
|
||||
rb-gpios = <&gpa 20 GPIO_ACTIVE_LOW>;
|
||||
wp-gpios = <&gpf 22 GPIO_ACTIVE_LOW>;
|
||||
|
||||
partitions {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
...
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
The BCH controller is a separate SoC component used for error correction on
|
||||
NAND devices. The following is a description of the device properties for a
|
||||
BCH controller.
|
||||
|
||||
Required BCH properties:
|
||||
- compatible: Should be set to "ingenic,jz4780-bch".
|
||||
- reg: Should specify the BCH controller registers location and length.
|
||||
- clocks: Clock for the BCH controller.
|
||||
|
||||
Example:
|
||||
|
||||
bch: bch@134d0000 {
|
||||
compatible = "ingenic,jz4780-bch";
|
||||
reg = <0x134d0000 0x10000>;
|
||||
|
||||
clocks = <&cgu JZ4780_CLK_BCH>;
|
||||
};
|
||||
@@ -1,15 +1,61 @@
|
||||
* MTD SPI driver for ST M25Pxx (and similar) serial flash chips
|
||||
* SPI NOR flash: ST M25Pxx (and similar) serial flash chips
|
||||
|
||||
Required properties:
|
||||
- #address-cells, #size-cells : Must be present if the device has sub-nodes
|
||||
representing partitions.
|
||||
- compatible : May include a device-specific string consisting of the
|
||||
manufacturer and name of the chip. Bear in mind the DT binding
|
||||
is not Linux-only, but in case of Linux, see the "m25p_ids"
|
||||
table in drivers/mtd/devices/m25p80.c for the list of supported
|
||||
chips.
|
||||
manufacturer and name of the chip. A list of supported chip
|
||||
names follows.
|
||||
Must also include "jedec,spi-nor" for any SPI NOR flash that can
|
||||
be identified by the JEDEC READ ID opcode (0x9F).
|
||||
|
||||
Supported chip names:
|
||||
at25df321a
|
||||
at25df641
|
||||
at26df081a
|
||||
mr25h256
|
||||
mx25l4005a
|
||||
mx25l1606e
|
||||
mx25l6405d
|
||||
mx25l12805d
|
||||
mx25l25635e
|
||||
n25q064
|
||||
n25q128a11
|
||||
n25q128a13
|
||||
n25q512a
|
||||
s25fl256s1
|
||||
s25fl512s
|
||||
s25sl12801
|
||||
s25fl008k
|
||||
s25fl064k
|
||||
sst25vf040b
|
||||
m25p40
|
||||
m25p80
|
||||
m25p16
|
||||
m25p32
|
||||
m25p64
|
||||
m25p128
|
||||
w25x80
|
||||
w25x32
|
||||
w25q32
|
||||
w25q32dw
|
||||
w25q80bl
|
||||
w25q128
|
||||
w25q256
|
||||
|
||||
The following chip names have been used historically to
|
||||
designate quirky versions of flash chips that do not support the
|
||||
JEDEC READ ID opcode (0x9F):
|
||||
m25p05-nonjedec
|
||||
m25p10-nonjedec
|
||||
m25p20-nonjedec
|
||||
m25p40-nonjedec
|
||||
m25p80-nonjedec
|
||||
m25p16-nonjedec
|
||||
m25p32-nonjedec
|
||||
m25p64-nonjedec
|
||||
m25p128-nonjedec
|
||||
|
||||
- reg : Chip-Select number
|
||||
- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
* Serial NOR flash controller for MTK MT81xx (and similar)
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "mediatek,mt8173-nor";
|
||||
- reg: physical base address and length of the controller's register
|
||||
- clocks: the phandle of the clocks needed by the nor controller
|
||||
- clock-names: the names of the clocks
|
||||
the clocks should be named "spi" and "sf". "spi" is used for spi bus,
|
||||
and "sf" is used for controller, these are the clocks witch
|
||||
hardware needs to enabling nor flash and nor flash controller.
|
||||
See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
|
||||
- #address-cells: should be <1>
|
||||
- #size-cells: should be <0>
|
||||
|
||||
The SPI flash must be a child of the nor_flash node and must have a
|
||||
compatible property. Also see jedec,spi-nor.txt.
|
||||
|
||||
Required properties:
|
||||
- compatible: May include a device-specific string consisting of the manufacturer
|
||||
and name of the chip. Must also include "jedec,spi-nor" for any
|
||||
SPI NOR flash that can be identified by the JEDEC READ ID opcode (0x9F).
|
||||
- reg : Chip-Select number
|
||||
|
||||
Example:
|
||||
|
||||
nor_flash: spi@1100d000 {
|
||||
compatible = "mediatek,mt8173-nor";
|
||||
reg = <0 0x1100d000 0 0xe0>;
|
||||
clocks = <&pericfg CLK_PERI_SPI>,
|
||||
<&topckgen CLK_TOP_SPINFI_IFR_SEL>;
|
||||
clock-names = "spi", "sf";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -32,6 +32,8 @@ Optional properties:
|
||||
partition should only be mounted read-only. This is usually used for flash
|
||||
partitions containing early-boot firmware images or data which should not be
|
||||
clobbered.
|
||||
- lock : Do not unlock the partition at initialization time (not supported on
|
||||
all devices)
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ for (i = 0; i < 256; i++)
|
||||
if (i & 0x01)
|
||||
rp1 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp1;
|
||||
else
|
||||
rp0 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp1;
|
||||
rp0 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp0;
|
||||
if (i & 0x02)
|
||||
rp3 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp3;
|
||||
else
|
||||
@@ -127,7 +127,7 @@ for (i = 0; i < 256; i++)
|
||||
if (i & 0x20)
|
||||
rp11 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp11;
|
||||
else
|
||||
rp10 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp10;
|
||||
rp10 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp10;
|
||||
if (i & 0x40)
|
||||
rp13 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp13;
|
||||
else
|
||||
@@ -158,7 +158,7 @@ the values in any order. So instead of calculating all the bits
|
||||
individually, let us try to rearrange things.
|
||||
For the column parity this is easy. We can just xor the bytes and in the
|
||||
end filter out the relevant bits. This is pretty nice as it will bring
|
||||
all cp calculation out of the if loop.
|
||||
all cp calculation out of the for loop.
|
||||
|
||||
Similarly we can first xor the bytes for the various rows.
|
||||
This leads to:
|
||||
@@ -271,11 +271,11 @@ to write our code in such a way that we process data in 32 bit chunks.
|
||||
Of course this means some modification as the row parity is byte by
|
||||
byte. A quick analysis:
|
||||
for the column parity we use the par variable. When extending to 32 bits
|
||||
we can in the end easily calculate p0 and p1 from it.
|
||||
we can in the end easily calculate rp0 and rp1 from it.
|
||||
(because par now consists of 4 bytes, contributing to rp1, rp0, rp1, rp0
|
||||
respectively)
|
||||
respectively, from MSB to LSB)
|
||||
also rp2 and rp3 can be easily retrieved from par as rp3 covers the
|
||||
first two bytes and rp2 the last two bytes.
|
||||
first two MSBs and rp2 covers the last two LSBs.
|
||||
|
||||
Note that of course now the loop is executed only 64 times (256/4).
|
||||
And note that care must taken wrt byte ordering. The way bytes are
|
||||
@@ -387,11 +387,11 @@ Analysis 2
|
||||
|
||||
The code (of course) works, and hurray: we are a little bit faster than
|
||||
the linux driver code (about 15%). But wait, don't cheer too quickly.
|
||||
THere is more to be gained.
|
||||
There is more to be gained.
|
||||
If we look at e.g. rp14 and rp15 we see that we either xor our data with
|
||||
rp14 or with rp15. However we also have par which goes over all data.
|
||||
This means there is no need to calculate rp14 as it can be calculated from
|
||||
rp15 through rp14 = par ^ rp15;
|
||||
rp15 through rp14 = par ^ rp15, because par = rp14 ^ rp15;
|
||||
(or if desired we can avoid calculating rp15 and calculate it from
|
||||
rp14). That is why some places refer to inverse parity.
|
||||
Of course the same thing holds for rp4/5, rp6/7, rp8/9, rp10/11 and rp12/13.
|
||||
@@ -419,12 +419,12 @@ with
|
||||
if (i & 0x20) rp15 ^= cur;
|
||||
|
||||
and outside the loop added:
|
||||
rp4 = par ^ rp5;
|
||||
rp6 = par ^ rp7;
|
||||
rp8 = par ^ rp9;
|
||||
rp10 = par ^ rp11;
|
||||
rp12 = par ^ rp13;
|
||||
rp14 = par ^ rp15;
|
||||
rp4 = par ^ rp5;
|
||||
rp6 = par ^ rp7;
|
||||
rp8 = par ^ rp9;
|
||||
rp10 = par ^ rp11;
|
||||
rp12 = par ^ rp13;
|
||||
rp14 = par ^ rp15;
|
||||
|
||||
And after that the code takes about 30% more time, although the number of
|
||||
statements is reduced. This is also reflected in the assembly code.
|
||||
@@ -524,12 +524,12 @@ THe code within the for loop was changed to:
|
||||
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp10 ^= tmppar;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp10 ^= tmppar;
|
||||
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur; rp8 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur; rp8 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp6 ^= cur; rp8 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp8 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp8 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp8 ^= cur;
|
||||
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur;
|
||||
@@ -537,7 +537,7 @@ THe code within the for loop was changed to:
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur;
|
||||
|
||||
par ^= tmppar;
|
||||
par ^= tmppar;
|
||||
if ((i & 0x1) == 0) rp12 ^= tmppar;
|
||||
if ((i & 0x2) == 0) rp14 ^= tmppar;
|
||||
}
|
||||
@@ -548,8 +548,8 @@ to rp12 and rp14.
|
||||
|
||||
While making the changes I also found that I could exploit that tmppar
|
||||
contains the running parity for this iteration. So instead of having:
|
||||
rp4 ^= cur; rp6 = cur;
|
||||
I removed the rp6 = cur; statement and did rp6 ^= tmppar; on next
|
||||
rp4 ^= cur; rp6 ^= cur;
|
||||
I removed the rp6 ^= cur; statement and did rp6 ^= tmppar; on next
|
||||
statement. A similar change was done for rp8 and rp10
|
||||
|
||||
|
||||
@@ -593,22 +593,22 @@ The new code now looks like:
|
||||
|
||||
cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp10 ^= tmppar;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp10 ^= tmppar;
|
||||
|
||||
notrp8 = tmppar;
|
||||
cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
|
||||
notrp8 = tmppar;
|
||||
cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur;
|
||||
rp8 = rp8 ^ tmppar ^ notrp8;
|
||||
rp8 = rp8 ^ tmppar ^ notrp8;
|
||||
|
||||
cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp6 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur; rp4 ^= cur;
|
||||
cur = *bp++; tmppar ^= cur;
|
||||
|
||||
par ^= tmppar;
|
||||
par ^= tmppar;
|
||||
if ((i & 0x1) == 0) rp12 ^= tmppar;
|
||||
if ((i & 0x2) == 0) rp14 ^= tmppar;
|
||||
}
|
||||
@@ -700,7 +700,7 @@ Conclusion
|
||||
The gain when calculating the ecc is tremendous. Om my development hardware
|
||||
a speedup of a factor of 18 for ecc calculation was achieved. On a test on an
|
||||
embedded system with a MIPS core a factor 7 was obtained.
|
||||
On a test with a Linksys NSLU2 (ARMv5TE processor) the speedup was a factor
|
||||
On a test with a Linksys NSLU2 (ARMv5TE processor) the speedup was a factor
|
||||
5 (big endian mode, gcc 4.1.2, -O3)
|
||||
For correction not much gain could be obtained (as bitflips are rare). Then
|
||||
again there are also much less cycles spent there.
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
static u16 nand_state = SNAPPERCL15_NAND_WPN;
|
||||
u16 set;
|
||||
|
||||
@@ -76,7 +76,7 @@ static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
|
||||
static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ static void __init ts72xx_map_io(void)
|
||||
static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
|
||||
int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
void __iomem *addr = chip->IO_ADDR_R;
|
||||
@@ -96,7 +96,7 @@ static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
|
||||
|
||||
static int ts72xx_nand_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
void __iomem *addr = chip->IO_ADDR_R;
|
||||
|
||||
addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
|
||||
|
||||
@@ -131,7 +131,7 @@ static void qong_init_nor_mtd(void)
|
||||
*/
|
||||
static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
@@ -76,8 +76,8 @@ static struct mtd_partition ixdp425_partitions[] = {
|
||||
static void
|
||||
ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int offset = (int)this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int offset = (int)nand_get_controller_data(this);
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
if (ctrl & NAND_NCE) {
|
||||
@@ -88,7 +88,7 @@ ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
|
||||
offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
|
||||
offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
|
||||
this->priv = (void *)offset;
|
||||
nand_set_controller_data(this, (void *)offset);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
unsigned long mask;
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
|
||||
@@ -176,7 +176,7 @@ static void ts78xx_ts_rtc_unload(void)
|
||||
static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned char bits;
|
||||
@@ -200,7 +200,7 @@ static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
|
||||
static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
void __iomem *io_base = chip->IO_ADDR_W;
|
||||
unsigned long off = ((unsigned long)buf & 3);
|
||||
int sz;
|
||||
@@ -227,7 +227,7 @@ static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
|
||||
static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
void __iomem *io_base = chip->IO_ADDR_R;
|
||||
unsigned long off = ((unsigned long)buf & 3);
|
||||
int sz;
|
||||
|
||||
@@ -572,7 +572,7 @@ static inline void balloon3_i2c_init(void) {}
|
||||
#if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
|
||||
static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
|
||||
@@ -289,7 +289,7 @@ static void nand_cs_off(void)
|
||||
static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
|
||||
|
||||
dsb();
|
||||
|
||||
@@ -250,7 +250,7 @@ static inline void palmtx_keys_init(void) {}
|
||||
static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
char __iomem *nandaddr = this->IO_ADDR_W;
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
|
||||
@@ -404,7 +404,7 @@ static struct mtd_partition bfin_plat_nand_partitions[] = {
|
||||
#define BFIN_NAND_PLAT_ALE 1
|
||||
static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
@@ -267,7 +267,7 @@ static struct mtd_partition bfin_plat_nand_partitions[] = {
|
||||
static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#define CE_BIT 12
|
||||
|
||||
struct mtd_info_wrapper {
|
||||
struct mtd_info info;
|
||||
struct nand_chip chip;
|
||||
};
|
||||
|
||||
@@ -52,7 +51,7 @@ static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
{
|
||||
unsigned long flags;
|
||||
reg_pio_rw_dout dout;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
@@ -148,10 +147,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = &wrapper->chip;
|
||||
crisv32_mtd = &wrapper->info;
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
crisv32_mtd->priv = this;
|
||||
crisv32_mtd = nand_to_mtd(this);
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = read_cs;
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#define BY_BIT 7
|
||||
|
||||
struct mtd_info_wrapper {
|
||||
struct mtd_info info;
|
||||
struct nand_chip chip;
|
||||
};
|
||||
|
||||
@@ -51,7 +50,7 @@ static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
{
|
||||
unsigned long flags;
|
||||
reg_gio_rw_pa_dout dout;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
@@ -129,7 +128,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = &wrapper->chip;
|
||||
crisv32_mtd = &wrapper->info;
|
||||
crisv32_mtd = nand_to_mtd(this);
|
||||
|
||||
pa_oe.oe |= 1 << CE_BIT;
|
||||
pa_oe.oe |= 1 << ALE_BIT;
|
||||
@@ -141,9 +140,6 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
|
||||
bif_cfg.gated_csp1 = regk_bif_core_wr;
|
||||
REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg);
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
crisv32_mtd->priv = this;
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = read_cs;
|
||||
this->IO_ADDR_W = write_cs;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user