mirror of https://gitee.com/openkylin/linux.git
MTD updates for v4.5:
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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWlZSyAAoJEFySrpd9RFgtVkEP/096SsFs+71jPgc6ARHIKt6j b8vnGeMpjYErIjRZXjeLJvD4whYcooM1IDXiy7HPFEF/DrmN+dBjF6gYNHhC9n+X bpIVS+TJknBKqcAClPVArZI77Fugzn1jBuo8t8rH5bpHNvTfucOt0VmQAu/NRxXe qUHNXDdQ+nb7qUy47Us66ygDiUh6tXYD2gp3duE8W49FnoSxcXNTq467RGyVBREl U+5mxsD4y49mktG3xatYdwmvz9UTWOYa+u4NTG282kP6GrqTPTw0ESaxfViP9nyd WSexhylV/PFJjxyMRazy1EZJ3kiQCQvza/VMmZ6fDSzwZ4JephuCDGLd3MhE3/E7 C275DNHC6U0s79gSlihrYHKEkMN8uNUDwNfeZhY05jXL56kFxUlUvvq14bt4gDDK xrPLNKLOpcoAMiRFOM5NdBeyQx9REq1G09I8MBjBN0kW254lIjGm6naCOl0L/Fu1 Y4c7hJCLFUTrki9DeNcP6dtpSCVdOap4C+920FZyrBnUzpt5G/rUGdSQu0iY5i4j BHe/Pr6ybkQ+b7XZbJlbFOy/u6TL/3T9Z4L52RK4j6F3r2EkNiH0+892L4v4qih6 Bt2wsFw8gGHC3dnnh5yfyst/QaG2Mu7V2JJjrrlERjWQJepWqYnUjlH/PgwKj7t0 /pnD40iDmUG2aYe+Jmcv =wFQI -----END PGP SIGNATURE----- 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:
commit
ac53b2e053
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -200,7 +200,7 @@ static struct i2c_board_info db1200_i2c_devs[] __initdata = {
|
|||
static void au1200_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);
|
||||
unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
|
||||
|
||||
ioaddr &= 0xffffff00;
|
||||
|
|
|
@ -150,7 +150,7 @@ static void __init db1300_gpio_config(void)
|
|||
static void au1300_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);
|
||||
unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
|
||||
|
||||
ioaddr &= 0xffffff00;
|
||||
|
|
|
@ -128,7 +128,7 @@ static struct i2c_board_info db1550_i2c_devs[] __initdata = {
|
|||
static void au1550_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);
|
||||
unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
|
||||
|
||||
ioaddr &= 0xffffff00;
|
||||
|
|
|
@ -180,7 +180,7 @@ static struct platform_device pnx833x_sata_device = {
|
|||
static void
|
||||
pnx833x_flash_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);
|
||||
unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
|
|
|
@ -148,7 +148,7 @@ static int rb532_dev_ready(struct mtd_info *mtd)
|
|||
|
||||
static void rb532_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);
|
||||
unsigned char orbits, nandbits;
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
|
|
|
@ -167,7 +167,7 @@ static struct mtd_partition migor_nand_flash_partitions[] = {
|
|||
static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
|
|
@ -112,7 +112,7 @@ config MTD_CMDLINE_PARTS
|
|||
|
||||
config MTD_AFS_PARTS
|
||||
tristate "ARM Firmware Suite partition parsing"
|
||||
depends on ARM
|
||||
depends on (ARM || ARM64)
|
||||
---help---
|
||||
The ARM Firmware Suite allows the user to divide flash devices into
|
||||
multiple 'images'. Each such image has a header containing its name
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
struct footer_struct {
|
||||
#define AFSV1_FOOTER_MAGIC 0xA0FFFF9F
|
||||
|
||||
struct footer_v1 {
|
||||
u32 image_info_base; /* Address of first word of ImageFooter */
|
||||
u32 image_start; /* Start of area reserved by this footer */
|
||||
u32 signature; /* 'Magic' number proves it's a footer */
|
||||
|
@ -42,7 +44,7 @@ struct footer_struct {
|
|||
u32 checksum; /* Just this structure */
|
||||
};
|
||||
|
||||
struct image_info_struct {
|
||||
struct image_info_v1 {
|
||||
u32 bootFlags; /* Boot flags, compression etc. */
|
||||
u32 imageNumber; /* Unique number, selects for boot etc. */
|
||||
u32 loadAddress; /* Address program should be loaded to */
|
||||
|
@ -67,10 +69,10 @@ static u32 word_sum(void *words, int num)
|
|||
}
|
||||
|
||||
static int
|
||||
afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
|
||||
afs_read_footer_v1(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
|
||||
u_int off, u_int mask)
|
||||
{
|
||||
struct footer_struct fs;
|
||||
struct footer_v1 fs;
|
||||
u_int ptr = off + mtd->erasesize - sizeof(fs);
|
||||
size_t sz;
|
||||
int ret;
|
||||
|
@ -85,25 +87,23 @@ afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
/*
|
||||
* Does it contain the magic number?
|
||||
*/
|
||||
if (fs.signature != 0xa0ffff9f)
|
||||
ret = 0;
|
||||
if (fs.signature != AFSV1_FOOTER_MAGIC)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check the checksum.
|
||||
*/
|
||||
if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff)
|
||||
ret = 0;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Don't touch the SIB.
|
||||
*/
|
||||
if (fs.type == 2)
|
||||
ret = 0;
|
||||
return 0;
|
||||
|
||||
*iis_start = fs.image_info_base & mask;
|
||||
*img_start = fs.image_start & mask;
|
||||
|
@ -113,20 +113,20 @@ afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
|
|||
* be located after the footer structure.
|
||||
*/
|
||||
if (*iis_start >= ptr)
|
||||
ret = 0;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check the start of this image. The image
|
||||
* data can not be located after this block.
|
||||
*/
|
||||
if (*img_start > off)
|
||||
ret = 0;
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
|
||||
afs_read_iis_v1(struct mtd_info *mtd, struct image_info_v1 *iis, u_int ptr)
|
||||
{
|
||||
size_t sz;
|
||||
int ret, i;
|
||||
|
@ -162,7 +162,7 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
|
|||
}
|
||||
|
||||
static int parse_afs_partitions(struct mtd_info *mtd,
|
||||
struct mtd_partition **pparts,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct mtd_partition *parts;
|
||||
|
@ -182,16 +182,14 @@ static int parse_afs_partitions(struct mtd_info *mtd,
|
|||
* the strings.
|
||||
*/
|
||||
for (idx = off = sz = 0; off < mtd->size; off += mtd->erasesize) {
|
||||
struct image_info_struct iis;
|
||||
struct image_info_v1 iis;
|
||||
u_int iis_ptr, img_ptr;
|
||||
|
||||
ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask);
|
||||
ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret == 0)
|
||||
continue;
|
||||
|
||||
ret = afs_read_iis(mtd, &iis, iis_ptr);
|
||||
if (ret) {
|
||||
ret = afs_read_iis_v1(mtd, &iis, iis_ptr);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret == 0)
|
||||
|
@ -201,6 +199,7 @@ static int parse_afs_partitions(struct mtd_info *mtd,
|
|||
sz += strlen(iis.name) + 1;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sz)
|
||||
return ret;
|
||||
|
@ -215,18 +214,18 @@ static int parse_afs_partitions(struct mtd_info *mtd,
|
|||
* Identify the partitions
|
||||
*/
|
||||
for (idx = off = 0; off < mtd->size; off += mtd->erasesize) {
|
||||
struct image_info_struct iis;
|
||||
struct image_info_v1 iis;
|
||||
u_int iis_ptr, img_ptr;
|
||||
|
||||
/* Read the footer. */
|
||||
ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask);
|
||||
ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret == 0)
|
||||
continue;
|
||||
|
||||
/* Read the image info block */
|
||||
ret = afs_read_iis(mtd, &iis, iis_ptr);
|
||||
ret = afs_read_iis_v1(mtd, &iis, iis_ptr);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret == 0)
|
||||
|
@ -257,25 +256,10 @@ static int parse_afs_partitions(struct mtd_info *mtd,
|
|||
}
|
||||
|
||||
static struct mtd_part_parser afs_parser = {
|
||||
.owner = THIS_MODULE,
|
||||
.parse_fn = parse_afs_partitions,
|
||||
.name = "afs",
|
||||
};
|
||||
|
||||
static int __init afs_parser_init(void)
|
||||
{
|
||||
register_mtd_parser(&afs_parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit afs_parser_exit(void)
|
||||
{
|
||||
deregister_mtd_parser(&afs_parser);
|
||||
}
|
||||
|
||||
module_init(afs_parser_init);
|
||||
module_exit(afs_parser_exit);
|
||||
|
||||
module_mtd_part_parser(afs_parser);
|
||||
|
||||
MODULE_AUTHOR("ARM Ltd");
|
||||
MODULE_DESCRIPTION("ARM Firmware Suite partition parser");
|
||||
|
|
|
@ -43,7 +43,7 @@ struct ar7_bin_rec {
|
|||
};
|
||||
|
||||
static int create_mtd_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct ar7_bin_rec header;
|
||||
|
@ -132,24 +132,10 @@ static int create_mtd_partitions(struct mtd_info *master,
|
|||
}
|
||||
|
||||
static struct mtd_part_parser ar7_parser = {
|
||||
.owner = THIS_MODULE,
|
||||
.parse_fn = create_mtd_partitions,
|
||||
.name = "ar7part",
|
||||
};
|
||||
|
||||
static int __init ar7_parser_init(void)
|
||||
{
|
||||
register_mtd_parser(&ar7_parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ar7_parser_exit(void)
|
||||
{
|
||||
deregister_mtd_parser(&ar7_parser);
|
||||
}
|
||||
|
||||
module_init(ar7_parser_init);
|
||||
module_exit(ar7_parser_exit);
|
||||
module_mtd_part_parser(ar7_parser);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR( "Felix Fietkau <nbd@openwrt.org>, "
|
||||
|
|
|
@ -82,7 +82,7 @@ static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master,
|
|||
}
|
||||
|
||||
static int bcm47xxpart_parse(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct mtd_partition *parts;
|
||||
|
@ -313,24 +313,10 @@ static int bcm47xxpart_parse(struct mtd_info *master,
|
|||
};
|
||||
|
||||
static struct mtd_part_parser bcm47xxpart_mtd_parser = {
|
||||
.owner = THIS_MODULE,
|
||||
.parse_fn = bcm47xxpart_parse,
|
||||
.name = "bcm47xxpart",
|
||||
};
|
||||
|
||||
static int __init bcm47xxpart_init(void)
|
||||
{
|
||||
register_mtd_parser(&bcm47xxpart_mtd_parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit bcm47xxpart_exit(void)
|
||||
{
|
||||
deregister_mtd_parser(&bcm47xxpart_mtd_parser);
|
||||
}
|
||||
|
||||
module_init(bcm47xxpart_init);
|
||||
module_exit(bcm47xxpart_exit);
|
||||
module_mtd_part_parser(bcm47xxpart_mtd_parser);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("MTD partitioning for BCM47XX flash memories");
|
||||
|
|
|
@ -68,7 +68,7 @@ static int bcm63xx_detect_cfe(struct mtd_info *master)
|
|||
}
|
||||
|
||||
static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
/* CFE, NVRAM and global Linux are always present */
|
||||
|
@ -214,24 +214,10 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
|
|||
};
|
||||
|
||||
static struct mtd_part_parser bcm63xx_cfe_parser = {
|
||||
.owner = THIS_MODULE,
|
||||
.parse_fn = bcm63xx_parse_cfe_partitions,
|
||||
.name = "bcm63xxpart",
|
||||
};
|
||||
|
||||
static int __init bcm63xx_cfe_parser_init(void)
|
||||
{
|
||||
register_mtd_parser(&bcm63xx_cfe_parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit bcm63xx_cfe_parser_exit(void)
|
||||
{
|
||||
deregister_mtd_parser(&bcm63xx_cfe_parser);
|
||||
}
|
||||
|
||||
module_init(bcm63xx_cfe_parser_init);
|
||||
module_exit(bcm63xx_cfe_parser_exit);
|
||||
module_mtd_part_parser(bcm63xx_cfe_parser);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>");
|
||||
|
|
|
@ -67,6 +67,10 @@ endchoice
|
|||
config MTD_CFI_GEOMETRY
|
||||
bool "Specific CFI Flash geometry selection"
|
||||
depends on MTD_CFI_ADV_OPTIONS
|
||||
select MTD_MAP_BANK_WIDTH_1 if !(MTD_MAP_BANK_WIDTH_2 || \
|
||||
MTD_MAP_BANK_WIDTH_4 || MTD_MAP_BANK_WIDTH_8 || \
|
||||
MTD_MAP_BANK_WIDTH_16 || MTD_MAP_BANK_WIDTH_32)
|
||||
select MTD_CFI_I1 if !(MTD_CFI_I2 || MTD_CFI_I4 || MTD_CFI_I8)
|
||||
help
|
||||
This option does not affect the code directly, but will enable
|
||||
some other configuration options which would allow you to reduce
|
||||
|
|
|
@ -596,7 +596,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
|
|||
mtd->size = devsize * cfi->numchips;
|
||||
|
||||
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
||||
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
||||
mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
|
||||
* mtd->numeraseregions, GFP_KERNEL);
|
||||
if (!mtd->eraseregions)
|
||||
goto setup_err;
|
||||
|
@ -614,6 +614,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
|
|||
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
|
||||
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
|
||||
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 + 1, GFP_KERNEL);
|
||||
if (!mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap)
|
||||
goto setup_err;
|
||||
}
|
||||
offset += (ersize * ernum);
|
||||
}
|
||||
|
@ -650,6 +652,10 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
|
|||
return mtd;
|
||||
|
||||
setup_err:
|
||||
if (mtd->eraseregions)
|
||||
for (i=0; i<cfi->cfiq->NumEraseRegions; i++)
|
||||
for (j=0; j<cfi->numchips; j++)
|
||||
kfree(mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap);
|
||||
kfree(mtd->eraseregions);
|
||||
kfree(mtd);
|
||||
kfree(cfi->cmdset_priv);
|
||||
|
|
|
@ -615,11 +615,9 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||
|
||||
for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
|
||||
int j = (cfi->cfiq->NumEraseRegions-1)-i;
|
||||
__u32 swap;
|
||||
|
||||
swap = cfi->cfiq->EraseRegionInfo[i];
|
||||
cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
|
||||
cfi->cfiq->EraseRegionInfo[j] = swap;
|
||||
swap(cfi->cfiq->EraseRegionInfo[i],
|
||||
cfi->cfiq->EraseRegionInfo[j]);
|
||||
}
|
||||
}
|
||||
/* Set the default CFI lock/unlock addresses */
|
||||
|
|
|
@ -304,7 +304,7 @@ static int mtdpart_setup_real(char *s)
|
|||
* the first one in the chain if a NULL mtd_id is passed in.
|
||||
*/
|
||||
static int parse_cmdline_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
unsigned long long offset;
|
||||
|
@ -382,7 +382,6 @@ static int __init mtdpart_setup(char *s)
|
|||
__setup("mtdparts=", mtdpart_setup);
|
||||
|
||||
static struct mtd_part_parser cmdline_parser = {
|
||||
.owner = THIS_MODULE,
|
||||
.parse_fn = parse_cmdline_partitions,
|
||||
.name = "cmdlinepart",
|
||||
};
|
||||
|
|
|
@ -152,22 +152,6 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int m25p80_erase(struct spi_nor *nor, loff_t offset)
|
||||
{
|
||||
struct m25p *flash = nor->priv;
|
||||
|
||||
dev_dbg(nor->dev, "%dKiB at 0x%08x\n",
|
||||
flash->spi_nor.mtd.erasesize / 1024, (u32)offset);
|
||||
|
||||
/* Set up command buffer. */
|
||||
flash->command[0] = nor->erase_opcode;
|
||||
m25p_addr2cmd(nor, offset, flash->command);
|
||||
|
||||
spi_write(flash->spi, flash->command, m25p_cmdsz(nor));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* board specific setup should have ensured the SPI clock used here
|
||||
* matches what the READ command supports, at least until this driver
|
||||
|
@ -175,12 +159,11 @@ static int m25p80_erase(struct spi_nor *nor, loff_t offset)
|
|||
*/
|
||||
static int m25p_probe(struct spi_device *spi)
|
||||
{
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct flash_platform_data *data;
|
||||
struct m25p *flash;
|
||||
struct spi_nor *nor;
|
||||
enum read_mode mode = SPI_NOR_NORMAL;
|
||||
char *flash_name = NULL;
|
||||
char *flash_name;
|
||||
int ret;
|
||||
|
||||
data = dev_get_platdata(&spi->dev);
|
||||
|
@ -194,12 +177,11 @@ static int m25p_probe(struct spi_device *spi)
|
|||
/* install the hooks */
|
||||
nor->read = m25p80_read;
|
||||
nor->write = m25p80_write;
|
||||
nor->erase = m25p80_erase;
|
||||
nor->write_reg = m25p80_write_reg;
|
||||
nor->read_reg = m25p80_read_reg;
|
||||
|
||||
nor->dev = &spi->dev;
|
||||
nor->flash_node = spi->dev.of_node;
|
||||
spi_nor_set_flash_node(nor, spi->dev.of_node);
|
||||
nor->priv = flash;
|
||||
|
||||
spi_set_drvdata(spi, flash);
|
||||
|
@ -220,6 +202,8 @@ static int m25p_probe(struct spi_device *spi)
|
|||
*/
|
||||
if (data && data->type)
|
||||
flash_name = data->type;
|
||||
else if (!strcmp(spi->modalias, "spi-nor"))
|
||||
flash_name = NULL; /* auto-detect */
|
||||
else
|
||||
flash_name = spi->modalias;
|
||||
|
||||
|
@ -227,10 +211,7 @@ static int m25p_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ppdata.of_node = spi->dev.of_node;
|
||||
|
||||
return mtd_device_parse_register(&nor->mtd, NULL, &ppdata,
|
||||
data ? data->parts : NULL,
|
||||
return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
|
||||
data ? data->nr_parts : 0);
|
||||
}
|
||||
|
||||
|
@ -256,15 +237,22 @@ static int m25p_remove(struct spi_device *spi)
|
|||
* keep them available as module aliases for existing platforms.
|
||||
*/
|
||||
static const struct spi_device_id m25p_ids[] = {
|
||||
/*
|
||||
* Allow non-DT platform devices to bind to the "spi-nor" modalias, and
|
||||
* hack around the fact that the SPI core does not provide uevent
|
||||
* matching for .of_match_table
|
||||
*/
|
||||
{"spi-nor"},
|
||||
|
||||
/*
|
||||
* Entries not used in DTs that should be safe to drop after replacing
|
||||
* them with "nor-jedec" in platform data.
|
||||
* them with "spi-nor" in platform data.
|
||||
*/
|
||||
{"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"},
|
||||
|
||||
/*
|
||||
* Entries that were used in DTs without "nor-jedec" fallback and should
|
||||
* be kept for backward compatibility.
|
||||
* Entries that were used in DTs without "jedec,spi-nor" fallback and
|
||||
* should be kept for backward compatibility.
|
||||
*/
|
||||
{"at25df321a"}, {"at25df641"}, {"at26df081a"},
|
||||
{"mr25h256"},
|
||||
|
|
|
@ -624,7 +624,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
|
|||
{
|
||||
struct dataflash *priv;
|
||||
struct mtd_info *device;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct flash_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
char *otp_tag = "";
|
||||
int err = 0;
|
||||
|
@ -656,6 +655,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
|
|||
device->priv = priv;
|
||||
|
||||
device->dev.parent = &spi->dev;
|
||||
mtd_set_of_node(device, spi->dev.of_node);
|
||||
|
||||
if (revision >= 'c')
|
||||
otp_tag = otp_setup(device, revision);
|
||||
|
@ -665,8 +665,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
|
|||
pagesize, otp_tag);
|
||||
spi_set_drvdata(spi, priv);
|
||||
|
||||
ppdata.of_node = spi->dev.of_node;
|
||||
err = mtd_device_parse_register(device, NULL, &ppdata,
|
||||
err = mtd_device_register(device,
|
||||
pdata ? pdata->parts : NULL,
|
||||
pdata ? pdata->nr_parts : 0);
|
||||
|
||||
|
|
|
@ -810,7 +810,6 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
|
|||
u32 bank, struct device_node *np)
|
||||
{
|
||||
struct spear_smi *dev = platform_get_drvdata(pdev);
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
struct spear_smi_flash_info *flash_info;
|
||||
struct spear_smi_plat_data *pdata;
|
||||
struct spear_snor_flash *flash;
|
||||
|
@ -855,6 +854,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
|
|||
flash->mtd.name = flash_devices[flash_index].name;
|
||||
|
||||
flash->mtd.dev.parent = &pdev->dev;
|
||||
mtd_set_of_node(&flash->mtd, np);
|
||||
flash->mtd.type = MTD_NORFLASH;
|
||||
flash->mtd.writesize = 1;
|
||||
flash->mtd.flags = MTD_CAP_NORFLASH;
|
||||
|
@ -881,10 +881,8 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
|
|||
count = flash_info->nr_partitions;
|
||||
}
|
||||
#endif
|
||||
ppdata.of_node = np;
|
||||
|
||||
ret = mtd_device_parse_register(&flash->mtd, NULL, &ppdata, parts,
|
||||
count);
|
||||
ret = mtd_device_register(&flash->mtd, parts, count);
|
||||
if (ret) {
|
||||
dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret);
|
||||
return ret;
|
||||
|
|
|
@ -2025,7 +2025,6 @@ static void stfsm_fetch_platform_configs(struct platform_device *pdev)
|
|||
static int stfsm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct flash_info *info;
|
||||
struct resource *res;
|
||||
struct stfsm *fsm;
|
||||
|
@ -2035,7 +2034,6 @@ static int stfsm_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ppdata.of_node = np;
|
||||
|
||||
fsm = devm_kzalloc(&pdev->dev, sizeof(*fsm), GFP_KERNEL);
|
||||
if (!fsm)
|
||||
|
@ -2106,6 +2104,7 @@ static int stfsm_probe(struct platform_device *pdev)
|
|||
|
||||
fsm->mtd.name = info->name;
|
||||
fsm->mtd.dev.parent = &pdev->dev;
|
||||
mtd_set_of_node(&fsm->mtd, np);
|
||||
fsm->mtd.type = MTD_NORFLASH;
|
||||
fsm->mtd.writesize = 4;
|
||||
fsm->mtd.writebufsize = fsm->mtd.writesize;
|
||||
|
@ -2124,7 +2123,7 @@ static int stfsm_probe(struct platform_device *pdev)
|
|||
(long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20),
|
||||
fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10));
|
||||
|
||||
return mtd_device_parse_register(&fsm->mtd, NULL, &ppdata, NULL, 0);
|
||||
return mtd_device_register(&fsm->mtd, NULL, 0);
|
||||
}
|
||||
|
||||
static int stfsm_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -571,12 +571,8 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
|
|||
|
||||
|
||||
/* Update the maps and usage stats*/
|
||||
i = xfer->EraseCount;
|
||||
xfer->EraseCount = eun->EraseCount;
|
||||
eun->EraseCount = i;
|
||||
i = xfer->Offset;
|
||||
xfer->Offset = eun->Offset;
|
||||
eun->Offset = i;
|
||||
swap(xfer->EraseCount, eun->EraseCount);
|
||||
swap(xfer->Offset, eun->Offset);
|
||||
part->FreeTotal -= eun->Free;
|
||||
part->FreeTotal += free;
|
||||
eun->Free = free;
|
||||
|
|
|
@ -110,7 +110,6 @@ ltq_copy_to(struct map_info *map, unsigned long to,
|
|||
static int
|
||||
ltq_mtd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct ltq_mtd *ltq_mtd;
|
||||
struct cfi_private *cfi;
|
||||
int err;
|
||||
|
@ -161,13 +160,13 @@ ltq_mtd_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
ltq_mtd->mtd->dev.parent = &pdev->dev;
|
||||
mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node);
|
||||
|
||||
cfi = ltq_mtd->map->fldrv_priv;
|
||||
cfi->addr_unlock1 ^= 1;
|
||||
cfi->addr_unlock2 ^= 1;
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
err = mtd_device_parse_register(ltq_mtd->mtd, NULL, &ppdata, NULL, 0);
|
||||
err = mtd_device_register(ltq_mtd->mtd, NULL, 0);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to add partitions\n");
|
||||
goto err_destroy;
|
||||
|
|
|
@ -166,7 +166,6 @@ static int of_flash_probe(struct platform_device *dev)
|
|||
int reg_tuple_size;
|
||||
struct mtd_info **mtd_list = NULL;
|
||||
resource_size_t res_size;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
bool map_indirect;
|
||||
const char *mtd_name = NULL;
|
||||
|
||||
|
@ -310,13 +309,14 @@ static int of_flash_probe(struct platform_device *dev)
|
|||
if (err)
|
||||
goto err_out;
|
||||
|
||||
ppdata.of_node = dp;
|
||||
info->cmtd->dev.parent = &dev->dev;
|
||||
mtd_set_of_node(info->cmtd, dp);
|
||||
part_probe_types = of_get_probes(dp);
|
||||
if (!part_probe_types) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
|
||||
mtd_device_parse_register(info->cmtd, part_probe_types, NULL,
|
||||
NULL, 0);
|
||||
of_free_probes(part_probe_types);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/backing-dev.h>
|
||||
|
@ -445,6 +446,7 @@ int add_mtd_device(struct mtd_info *mtd)
|
|||
mtd->dev.devt = MTD_DEVT(i);
|
||||
dev_set_name(&mtd->dev, "mtd%d", i);
|
||||
dev_set_drvdata(&mtd->dev, mtd);
|
||||
of_node_get(mtd_get_of_node(mtd));
|
||||
error = device_register(&mtd->dev);
|
||||
if (error)
|
||||
goto fail_added;
|
||||
|
@ -467,6 +469,7 @@ int add_mtd_device(struct mtd_info *mtd)
|
|||
return 0;
|
||||
|
||||
fail_added:
|
||||
of_node_put(mtd_get_of_node(mtd));
|
||||
idr_remove(&mtd_idr, i);
|
||||
fail_locked:
|
||||
mutex_unlock(&mtd_table_mutex);
|
||||
|
@ -508,6 +511,7 @@ int del_mtd_device(struct mtd_info *mtd)
|
|||
device_unregister(&mtd->dev);
|
||||
|
||||
idr_remove(&mtd_idr, mtd->index);
|
||||
of_node_put(mtd_get_of_node(mtd));
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
ret = 0;
|
||||
|
@ -519,9 +523,10 @@ int del_mtd_device(struct mtd_info *mtd)
|
|||
}
|
||||
|
||||
static int mtd_add_device_partitions(struct mtd_info *mtd,
|
||||
struct mtd_partition *real_parts,
|
||||
int nbparts)
|
||||
struct mtd_partitions *parts)
|
||||
{
|
||||
const struct mtd_partition *real_parts = parts->parts;
|
||||
int nbparts = parts->nr_parts;
|
||||
int ret;
|
||||
|
||||
if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
|
||||
|
@ -590,29 +595,29 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
|
|||
const struct mtd_partition *parts,
|
||||
int nr_parts)
|
||||
{
|
||||
struct mtd_partitions parsed;
|
||||
int ret;
|
||||
struct mtd_partition *real_parts = NULL;
|
||||
|
||||
mtd_set_dev_defaults(mtd);
|
||||
|
||||
ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
|
||||
if (ret <= 0 && nr_parts && parts) {
|
||||
real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
|
||||
GFP_KERNEL);
|
||||
if (!real_parts)
|
||||
ret = -ENOMEM;
|
||||
else
|
||||
ret = nr_parts;
|
||||
}
|
||||
/* Didn't come up with either parsed OR fallback partitions */
|
||||
if (ret < 0) {
|
||||
memset(&parsed, 0, sizeof(parsed));
|
||||
|
||||
ret = parse_mtd_partitions(mtd, types, &parsed, parser_data);
|
||||
if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) {
|
||||
/* Fall back to driver-provided partitions */
|
||||
parsed = (struct mtd_partitions){
|
||||
.parts = parts,
|
||||
.nr_parts = nr_parts,
|
||||
};
|
||||
} else if (ret < 0) {
|
||||
/* Didn't come up with parsed OR fallback partitions */
|
||||
pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n",
|
||||
ret);
|
||||
/* Don't abort on errors; we can still use unpartitioned MTD */
|
||||
ret = 0;
|
||||
memset(&parsed, 0, sizeof(parsed));
|
||||
}
|
||||
|
||||
ret = mtd_add_device_partitions(mtd, real_parts, ret);
|
||||
ret = mtd_add_device_partitions(mtd, &parsed);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
@ -632,7 +637,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
|
|||
}
|
||||
|
||||
out:
|
||||
kfree(real_parts);
|
||||
/* Cleanup any parsed partitions */
|
||||
mtd_part_parser_cleanup(&parsed);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_device_parse_register);
|
||||
|
|
|
@ -10,10 +10,15 @@ int add_mtd_device(struct mtd_info *mtd);
|
|||
int del_mtd_device(struct mtd_info *mtd);
|
||||
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
|
||||
int del_mtd_partitions(struct mtd_info *);
|
||||
|
||||
struct mtd_partitions;
|
||||
|
||||
int parse_mtd_partitions(struct mtd_info *master, const char * const *types,
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_partitions *pparts,
|
||||
struct mtd_part_parser_data *data);
|
||||
|
||||
void mtd_part_parser_cleanup(struct mtd_partitions *parts);
|
||||
|
||||
int __init init_mtdchar(void);
|
||||
void __exit cleanup_mtdchar(void);
|
||||
|
||||
|
|
|
@ -48,9 +48,12 @@ struct mtd_part {
|
|||
|
||||
/*
|
||||
* Given a pointer to the MTD object in the mtd_part structure, we can retrieve
|
||||
* the pointer to that structure with this macro.
|
||||
* the pointer to that structure.
|
||||
*/
|
||||
#define PART(x) ((struct mtd_part *)(x))
|
||||
static inline struct mtd_part *mtd_to_part(const struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd, struct mtd_part, mtd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -61,7 +64,7 @@ struct mtd_part {
|
|||
static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
struct mtd_ecc_stats stats;
|
||||
int res;
|
||||
|
||||
|
@ -80,7 +83,7 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||
static int part_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, void **virt, resource_size_t *phys)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
|
||||
return part->master->_point(part->master, from + part->offset, len,
|
||||
retlen, virt, phys);
|
||||
|
@ -88,7 +91,7 @@ static int part_point(struct mtd_info *mtd, loff_t from, size_t len,
|
|||
|
||||
static int part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
|
||||
return part->master->_unpoint(part->master, from + part->offset, len);
|
||||
}
|
||||
|
@ -98,7 +101,7 @@ static unsigned long part_get_unmapped_area(struct mtd_info *mtd,
|
|||
unsigned long offset,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
|
||||
offset += part->offset;
|
||||
return part->master->_get_unmapped_area(part->master, len, offset,
|
||||
|
@ -108,7 +111,7 @@ static unsigned long part_get_unmapped_area(struct mtd_info *mtd,
|
|||
static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
||||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
int res;
|
||||
|
||||
if (from >= mtd->size)
|
||||
|
@ -146,7 +149,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
|||
static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
|
||||
size_t len, size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_read_user_prot_reg(part->master, from, len,
|
||||
retlen, buf);
|
||||
}
|
||||
|
@ -154,7 +157,7 @@ static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
|
|||
static int part_get_user_prot_info(struct mtd_info *mtd, size_t len,
|
||||
size_t *retlen, struct otp_info *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_get_user_prot_info(part->master, len, retlen,
|
||||
buf);
|
||||
}
|
||||
|
@ -162,7 +165,7 @@ static int part_get_user_prot_info(struct mtd_info *mtd, size_t len,
|
|||
static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
|
||||
size_t len, size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_read_fact_prot_reg(part->master, from, len,
|
||||
retlen, buf);
|
||||
}
|
||||
|
@ -170,7 +173,7 @@ static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
|
|||
static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len,
|
||||
size_t *retlen, struct otp_info *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_get_fact_prot_info(part->master, len, retlen,
|
||||
buf);
|
||||
}
|
||||
|
@ -178,7 +181,7 @@ static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len,
|
|||
static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_write(part->master, to + part->offset, len,
|
||||
retlen, buf);
|
||||
}
|
||||
|
@ -186,7 +189,7 @@ static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||
static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_panic_write(part->master, to + part->offset, len,
|
||||
retlen, buf);
|
||||
}
|
||||
|
@ -194,7 +197,7 @@ static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||
static int part_write_oob(struct mtd_info *mtd, loff_t to,
|
||||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
|
||||
if (to >= mtd->size)
|
||||
return -EINVAL;
|
||||
|
@ -206,7 +209,7 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
|
|||
static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
|
||||
size_t len, size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_write_user_prot_reg(part->master, from, len,
|
||||
retlen, buf);
|
||||
}
|
||||
|
@ -214,21 +217,21 @@ static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
|
|||
static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
|
||||
size_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_lock_user_prot_reg(part->master, from, len);
|
||||
}
|
||||
|
||||
static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
|
||||
unsigned long count, loff_t to, size_t *retlen)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_writev(part->master, vecs, count,
|
||||
to + part->offset, retlen);
|
||||
}
|
||||
|
||||
static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
int ret;
|
||||
|
||||
instr->addr += part->offset;
|
||||
|
@ -244,7 +247,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||
void mtd_erase_callback(struct erase_info *instr)
|
||||
{
|
||||
if (instr->mtd->_erase == part_erase) {
|
||||
struct mtd_part *part = PART(instr->mtd);
|
||||
struct mtd_part *part = mtd_to_part(instr->mtd);
|
||||
|
||||
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
|
||||
instr->fail_addr -= part->offset;
|
||||
|
@ -257,57 +260,57 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback);
|
|||
|
||||
static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_lock(part->master, ofs + part->offset, len);
|
||||
}
|
||||
|
||||
static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_unlock(part->master, ofs + part->offset, len);
|
||||
}
|
||||
|
||||
static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_is_locked(part->master, ofs + part->offset, len);
|
||||
}
|
||||
|
||||
static void part_sync(struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
part->master->_sync(part->master);
|
||||
}
|
||||
|
||||
static int part_suspend(struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return part->master->_suspend(part->master);
|
||||
}
|
||||
|
||||
static void part_resume(struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
part->master->_resume(part->master);
|
||||
}
|
||||
|
||||
static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
ofs += part->offset;
|
||||
return part->master->_block_isreserved(part->master, ofs);
|
||||
}
|
||||
|
||||
static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
ofs += part->offset;
|
||||
return part->master->_block_isbad(part->master, ofs);
|
||||
}
|
||||
|
||||
static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
int res;
|
||||
|
||||
ofs += part->offset;
|
||||
|
@ -558,7 +561,7 @@ static ssize_t mtd_partition_offset_show(struct device *dev,
|
|||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mtd_info *mtd = dev_get_drvdata(dev);
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_part *part = mtd_to_part(mtd);
|
||||
return snprintf(buf, PAGE_SIZE, "%lld\n", part->offset);
|
||||
}
|
||||
|
||||
|
@ -596,11 +599,10 @@ int mtd_add_partition(struct mtd_info *master, const char *name,
|
|||
if (length <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&part, 0, sizeof(part));
|
||||
part.name = name;
|
||||
part.size = length;
|
||||
part.offset = offset;
|
||||
part.mask_flags = 0;
|
||||
part.ecclayout = NULL;
|
||||
|
||||
new = allocate_partition(master, &part, -1, offset);
|
||||
if (IS_ERR(new))
|
||||
|
@ -685,7 +687,7 @@ int add_mtd_partitions(struct mtd_info *master,
|
|||
static DEFINE_SPINLOCK(part_parser_lock);
|
||||
static LIST_HEAD(part_parsers);
|
||||
|
||||
static struct mtd_part_parser *get_partition_parser(const char *name)
|
||||
static struct mtd_part_parser *mtd_part_parser_get(const char *name)
|
||||
{
|
||||
struct mtd_part_parser *p, *ret = NULL;
|
||||
|
||||
|
@ -702,15 +704,35 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
|
||||
|
||||
void register_mtd_parser(struct mtd_part_parser *p)
|
||||
static inline void mtd_part_parser_put(const struct mtd_part_parser *p)
|
||||
{
|
||||
module_put(p->owner);
|
||||
}
|
||||
|
||||
/*
|
||||
* Many partition parsers just expected the core to kfree() all their data in
|
||||
* one chunk. Do that by default.
|
||||
*/
|
||||
static void mtd_part_parser_cleanup_default(const struct mtd_partition *pparts,
|
||||
int nr_parts)
|
||||
{
|
||||
kfree(pparts);
|
||||
}
|
||||
|
||||
int __register_mtd_parser(struct mtd_part_parser *p, struct module *owner)
|
||||
{
|
||||
p->owner = owner;
|
||||
|
||||
if (!p->cleanup)
|
||||
p->cleanup = &mtd_part_parser_cleanup_default;
|
||||
|
||||
spin_lock(&part_parser_lock);
|
||||
list_add(&p->list, &part_parsers);
|
||||
spin_unlock(&part_parser_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_mtd_parser);
|
||||
EXPORT_SYMBOL_GPL(__register_mtd_parser);
|
||||
|
||||
void deregister_mtd_parser(struct mtd_part_parser *p)
|
||||
{
|
||||
|
@ -734,7 +756,7 @@ static const char * const default_mtd_part_types[] = {
|
|||
* parse_mtd_partitions - parse MTD partitions
|
||||
* @master: the master partition (describes whole MTD device)
|
||||
* @types: names of partition parsers to try or %NULL
|
||||
* @pparts: array of partitions found is returned here
|
||||
* @pparts: info about partitions found is returned here
|
||||
* @data: MTD partition parser-specific data
|
||||
*
|
||||
* This function tries to find partition on MTD device @master. It uses MTD
|
||||
|
@ -746,12 +768,13 @@ static const char * const default_mtd_part_types[] = {
|
|||
*
|
||||
* This function may return:
|
||||
* o a negative error code in case of failure
|
||||
* o zero if no partitions were found
|
||||
* o a positive number of found partitions, in which case on exit @pparts will
|
||||
* point to an array containing this number of &struct mtd_info objects.
|
||||
* o zero otherwise, and @pparts will describe the partitions, number of
|
||||
* partitions, and the parser which parsed them. Caller must release
|
||||
* resources with mtd_part_parser_cleanup() when finished with the returned
|
||||
* data.
|
||||
*/
|
||||
int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_partitions *pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct mtd_part_parser *parser;
|
||||
|
@ -762,22 +785,24 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
|
|||
|
||||
for ( ; *types; types++) {
|
||||
pr_debug("%s: parsing partitions %s\n", master->name, *types);
|
||||
parser = get_partition_parser(*types);
|
||||
parser = mtd_part_parser_get(*types);
|
||||
if (!parser && !request_module("%s", *types))
|
||||
parser = get_partition_parser(*types);
|
||||
parser = mtd_part_parser_get(*types);
|
||||
pr_debug("%s: got parser %s\n", master->name,
|
||||
parser ? parser->name : NULL);
|
||||
if (!parser)
|
||||
continue;
|
||||
ret = (*parser->parse_fn)(master, pparts, data);
|
||||
ret = (*parser->parse_fn)(master, &pparts->parts, data);
|
||||
pr_debug("%s: parser %s: %i\n",
|
||||
master->name, parser->name, ret);
|
||||
put_partition_parser(parser);
|
||||
if (ret > 0) {
|
||||
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
|
||||
ret, parser->name, master->name);
|
||||
return ret;
|
||||
pparts->nr_parts = ret;
|
||||
pparts->parser = parser;
|
||||
return 0;
|
||||
}
|
||||
mtd_part_parser_put(parser);
|
||||
/*
|
||||
* Stash the first error we see; only report it if no parser
|
||||
* succeeds
|
||||
|
@ -788,6 +813,22 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
|
|||
return err;
|
||||
}
|
||||
|
||||
void mtd_part_parser_cleanup(struct mtd_partitions *parts)
|
||||
{
|
||||
const struct mtd_part_parser *parser;
|
||||
|
||||
if (!parts)
|
||||
return;
|
||||
|
||||
parser = parts->parser;
|
||||
if (parser) {
|
||||
if (parser->cleanup)
|
||||
parser->cleanup(parts->parts, parts->nr_parts);
|
||||
|
||||
mtd_part_parser_put(parser);
|
||||
}
|
||||
}
|
||||
|
||||
int mtd_is_partition(const struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part;
|
||||
|
@ -811,6 +852,6 @@ uint64_t mtd_get_device_size(const struct mtd_info *mtd)
|
|||
if (!mtd_is_partition(mtd))
|
||||
return mtd->size;
|
||||
|
||||
return PART(mtd)->master->size;
|
||||
return mtd_to_part(mtd)->master->size;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_get_device_size);
|
||||
|
|
|
@ -55,7 +55,7 @@ config MTD_NAND_DENALI_PCI
|
|||
config MTD_NAND_DENALI_DT
|
||||
tristate "Support Denali NAND controller as a DT device"
|
||||
select MTD_NAND_DENALI
|
||||
depends on HAS_DMA && HAVE_CLK
|
||||
depends on HAS_DMA && HAVE_CLK && OF
|
||||
help
|
||||
Enable the driver for NAND flash on platforms using a Denali NAND
|
||||
controller as a DT device.
|
||||
|
@ -480,7 +480,7 @@ config MTD_NAND_MXC
|
|||
|
||||
config MTD_NAND_SH_FLCTL
|
||||
tristate "Support for NAND on Renesas SuperH FLCTL"
|
||||
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
|
||||
depends on SUPERH || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
depends on HAS_DMA
|
||||
help
|
||||
|
@ -519,6 +519,13 @@ config MTD_NAND_JZ4740
|
|||
help
|
||||
Enables support for NAND Flash on JZ4740 SoC based boards.
|
||||
|
||||
config MTD_NAND_JZ4780
|
||||
tristate "Support for NAND on JZ4780 SoC"
|
||||
depends on MACH_JZ4780 && JZ4780_NEMC
|
||||
help
|
||||
Enables support for NAND Flash connected to the NEMC on JZ4780 SoC
|
||||
based boards, using the BCH controller for hardware error correction.
|
||||
|
||||
config MTD_NAND_FSMC
|
||||
tristate "Support for NAND on ST Micros FSMC"
|
||||
depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
|
||||
|
|
|
@ -49,6 +49,7 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
|
|||
obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o
|
||||
obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
|
||||
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_JZ4780) += jz4780_nand.o jz4780_bch.o
|
||||
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
|
||||
obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/
|
||||
|
|
|
@ -64,8 +64,8 @@ static struct mtd_partition partition_info[] = {
|
|||
|
||||
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
void __iomem *io_base = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
|
||||
|
||||
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
|
||||
writew(byte, this->IO_ADDR_W);
|
||||
|
@ -77,8 +77,8 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
|
|||
static u_char ams_delta_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
u_char res;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
void __iomem *io_base = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
|
||||
|
||||
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
|
||||
ndelay(40);
|
||||
|
@ -183,22 +183,16 @@ static int ams_delta_init(struct platform_device *pdev)
|
|||
return -ENXIO;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
ams_delta_mtd = kzalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!ams_delta_mtd) {
|
||||
this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!this) {
|
||||
printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ams_delta_mtd = nand_to_mtd(this);
|
||||
ams_delta_mtd->owner = THIS_MODULE;
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&ams_delta_mtd[1]);
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
ams_delta_mtd->priv = this;
|
||||
|
||||
/*
|
||||
* Don't try to request the memory region from here,
|
||||
* it should have been already requested from the
|
||||
|
@ -212,7 +206,7 @@ static int ams_delta_init(struct platform_device *pdev)
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
this->priv = io_base;
|
||||
nand_set_controller_data(this, (void *)io_base);
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
|
||||
|
@ -256,7 +250,7 @@ static int ams_delta_init(struct platform_device *pdev)
|
|||
gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
|
||||
iounmap(io_base);
|
||||
out_free:
|
||||
kfree(ams_delta_mtd);
|
||||
kfree(this);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -276,7 +270,7 @@ static int ams_delta_cleanup(struct platform_device *pdev)
|
|||
iounmap(io_base);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree(ams_delta_mtd);
|
||||
kfree(mtd_to_nand(ams_delta_mtd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,6 @@ static struct atmel_nfc nand_nfc;
|
|||
|
||||
struct atmel_nand_host {
|
||||
struct nand_chip nand_chip;
|
||||
struct mtd_info mtd;
|
||||
void __iomem *io_base;
|
||||
dma_addr_t io_phys;
|
||||
struct atmel_nand_data board;
|
||||
|
@ -128,7 +127,7 @@ struct atmel_nand_host {
|
|||
|
||||
struct atmel_nfc *nfc;
|
||||
|
||||
struct atmel_nand_caps *caps;
|
||||
const struct atmel_nand_caps *caps;
|
||||
bool has_pmecc;
|
||||
u8 pmecc_corr_cap;
|
||||
u16 pmecc_sector_size;
|
||||
|
@ -182,8 +181,8 @@ static void atmel_nand_disable(struct atmel_nand_host *host)
|
|||
*/
|
||||
static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
if (ctrl & NAND_NCE)
|
||||
|
@ -205,8 +204,8 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
|
|||
*/
|
||||
static int atmel_nand_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
return gpio_get_value(host->board.rdy_pin) ^
|
||||
!!host->board.rdy_pin_active_low;
|
||||
|
@ -215,8 +214,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
|
|||
/* Set up for hardware ready pin and enable pin. */
|
||||
static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
int res = 0;
|
||||
|
||||
if (gpio_is_valid(host->board.rdy_pin)) {
|
||||
|
@ -267,8 +266,8 @@ static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd)
|
|||
*/
|
||||
static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
|
||||
memcpy(buf, host->nfc->data_in_sram, len);
|
||||
|
@ -280,8 +279,8 @@ static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
|
|||
|
||||
static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
|
||||
memcpy(buf, host->nfc->data_in_sram, len);
|
||||
|
@ -293,14 +292,14 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
|
|||
|
||||
static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
|
||||
__raw_writesb(nand_chip->IO_ADDR_W, buf, len);
|
||||
}
|
||||
|
||||
static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
|
||||
__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
|
||||
}
|
||||
|
@ -317,8 +316,10 @@ static int nfc_set_sram_bank(struct atmel_nand_host *host, unsigned int bank)
|
|||
return -EINVAL;
|
||||
|
||||
if (bank) {
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
|
||||
|
||||
/* Only for a 2k-page or lower flash, NFC can handle 2 banks */
|
||||
if (host->mtd.writesize > 2048)
|
||||
if (mtd->writesize > 2048)
|
||||
return -EINVAL;
|
||||
nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK1);
|
||||
} else {
|
||||
|
@ -352,8 +353,8 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
|
|||
dma_addr_t dma_src_addr, dma_dst_addr, phys_addr;
|
||||
struct dma_async_tx_descriptor *tx = NULL;
|
||||
dma_cookie_t cookie;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
void *p = buf;
|
||||
int err = -EIO;
|
||||
enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
|
@ -425,8 +426,8 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
|
|||
|
||||
static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
if (use_dma && len > mtd->oobsize)
|
||||
/* only use DMA for bigger than oob size: better performances */
|
||||
|
@ -441,8 +442,8 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
|||
|
||||
static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
if (use_dma && len > mtd->oobsize)
|
||||
/* only use DMA for bigger than oob size: better performances */
|
||||
|
@ -533,8 +534,8 @@ static int pmecc_data_alloc(struct atmel_nand_host *host)
|
|||
|
||||
static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
int i;
|
||||
uint32_t value;
|
||||
|
||||
|
@ -550,8 +551,8 @@ static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
|
|||
|
||||
static void pmecc_substitute(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
int16_t __iomem *alpha_to = host->pmecc_alpha_to;
|
||||
int16_t __iomem *index_of = host->pmecc_index_of;
|
||||
int16_t *partial_syn = host->pmecc_partial_syn;
|
||||
|
@ -592,8 +593,8 @@ static void pmecc_substitute(struct mtd_info *mtd)
|
|||
|
||||
static void pmecc_get_sigma(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
int16_t *lmu = host->pmecc_lmu;
|
||||
int16_t *si = host->pmecc_si;
|
||||
|
@ -750,8 +751,8 @@ static void pmecc_get_sigma(struct mtd_info *mtd)
|
|||
|
||||
static int pmecc_err_location(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
unsigned long end_time;
|
||||
const int cap = host->pmecc_corr_cap;
|
||||
const int num = 2 * cap + 1;
|
||||
|
@ -802,8 +803,8 @@ static int pmecc_err_location(struct mtd_info *mtd)
|
|||
static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
|
||||
int sector_num, int extra_bytes, int err_nbr)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
int i = 0;
|
||||
int byte_pos, bit_pos, sector_size, pos;
|
||||
uint32_t tmp;
|
||||
|
@ -848,8 +849,8 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
|
|||
static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
|
||||
u8 *ecc)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
int i, err_nbr;
|
||||
uint8_t *buf_pos;
|
||||
int max_bitflips = 0;
|
||||
|
@ -919,7 +920,7 @@ static void pmecc_enable(struct atmel_nand_host *host, int ecc_op)
|
|||
static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
int eccsize = chip->ecc.size * chip->ecc.steps;
|
||||
uint8_t *oob = chip->oob_poi;
|
||||
uint32_t *eccpos = chip->ecc.layout->eccpos;
|
||||
|
@ -957,7 +958,7 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
|
|||
struct nand_chip *chip, const uint8_t *buf, int oob_required,
|
||||
int page)
|
||||
{
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
uint32_t *eccpos = chip->ecc.layout->eccpos;
|
||||
int i, j;
|
||||
unsigned long end_time;
|
||||
|
@ -992,8 +993,8 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
|
|||
|
||||
static void atmel_pmecc_core_init(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
uint32_t val = 0;
|
||||
struct nand_ecclayout *ecc_layout;
|
||||
|
||||
|
@ -1159,8 +1160,8 @@ static uint16_t *create_lookup_table(struct device *dev, int sector_size)
|
|||
static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
|
||||
struct atmel_nand_host *host)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct nand_chip *nand_chip = &host->nand_chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(nand_chip);
|
||||
struct resource *regs, *regs_pmerr, *regs_rom;
|
||||
uint16_t *galois_table;
|
||||
int cap, sector_size, err_no;
|
||||
|
@ -1308,8 +1309,8 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
|
|||
static int atmel_nand_calculate(struct mtd_info *mtd,
|
||||
const u_char *dat, unsigned char *ecc_code)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
unsigned int ecc_value;
|
||||
|
||||
/* get the first 2 ECC bytes */
|
||||
|
@ -1355,7 +1356,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
* Workaround: Reset the parity registers before reading the
|
||||
* actual data.
|
||||
*/
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
if (host->board.need_reset_workaround)
|
||||
ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
|
||||
|
||||
|
@ -1412,8 +1413,8 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *isnull)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
unsigned int ecc_status;
|
||||
unsigned int ecc_word, ecc_bit;
|
||||
|
||||
|
@ -1444,7 +1445,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
|
|||
* We can't correct so many errors */
|
||||
dev_dbg(host->dev, "atmel_nand : multiple errors detected."
|
||||
" Unable to correct.\n");
|
||||
return -EIO;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
/* if there's a single bit error : we can correct it */
|
||||
|
@ -1478,8 +1479,8 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
|
|||
*/
|
||||
static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (host->board.need_reset_workaround)
|
||||
ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
|
||||
|
@ -1586,8 +1587,8 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
|
|||
static int atmel_hw_nand_init_params(struct platform_device *pdev,
|
||||
struct atmel_nand_host *host)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct nand_chip *nand_chip = &host->nand_chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(nand_chip);
|
||||
struct resource *regs;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
|
@ -1771,8 +1772,8 @@ static int nfc_send_command(struct atmel_nand_host *host,
|
|||
static int nfc_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
u32 status, mask;
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
status = nfc_read_status(host);
|
||||
mask = nfc_readl(host->nfc->hsmc_regs, IMR);
|
||||
|
@ -1787,8 +1788,8 @@ static int nfc_device_ready(struct mtd_info *mtd)
|
|||
|
||||
static void nfc_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct atmel_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (chip == -1)
|
||||
nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_DISABLE);
|
||||
|
@ -1799,7 +1800,7 @@ static void nfc_select_chip(struct mtd_info *mtd, int chip)
|
|||
static int nfc_make_addr(struct mtd_info *mtd, int command, int column,
|
||||
int page_addr, unsigned int *addr1234, unsigned int *cycle0)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
int acycle = 0;
|
||||
unsigned char addr_bytes[8];
|
||||
|
@ -1839,8 +1840,8 @@ static int nfc_make_addr(struct mtd_info *mtd, int command, int column,
|
|||
static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
unsigned long timeout;
|
||||
unsigned int nfc_addr_cmd = 0;
|
||||
|
||||
|
@ -1966,7 +1967,7 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
{
|
||||
int cfg, len;
|
||||
int status = 0;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
void *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host);
|
||||
|
||||
/* Subpage write is not supported */
|
||||
|
@ -2026,8 +2027,8 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
|
||||
static int nfc_sram_init(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct atmel_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct atmel_nand_host *host = nand_get_controller_data(chip);
|
||||
int res = 0;
|
||||
|
||||
/* Initialize the NFC CFG register */
|
||||
|
@ -2093,7 +2094,6 @@ static int atmel_nand_probe(struct platform_device *pdev)
|
|||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand_chip;
|
||||
struct resource *mem;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
int res, irq;
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
|
@ -2113,10 +2113,11 @@ static int atmel_nand_probe(struct platform_device *pdev)
|
|||
}
|
||||
host->io_phys = (dma_addr_t)mem->start;
|
||||
|
||||
mtd = &host->mtd;
|
||||
nand_chip = &host->nand_chip;
|
||||
mtd = nand_to_mtd(nand_chip);
|
||||
host->dev = &pdev->dev;
|
||||
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
|
||||
nand_set_flash_node(nand_chip, pdev->dev.of_node);
|
||||
/* Only when CONFIG_OF is enabled of_node can be parsed */
|
||||
res = atmel_of_init_port(host, pdev->dev.of_node);
|
||||
if (res)
|
||||
|
@ -2126,8 +2127,8 @@ static int atmel_nand_probe(struct platform_device *pdev)
|
|||
sizeof(struct atmel_nand_data));
|
||||
}
|
||||
|
||||
nand_chip->priv = host; /* link the private data structures */
|
||||
mtd->priv = nand_chip;
|
||||
/* link the private data structures */
|
||||
nand_set_controller_data(nand_chip, host);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
|
@ -2259,9 +2260,8 @@ static int atmel_nand_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
mtd->name = "atmel_nand";
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
res = mtd_device_parse_register(mtd, NULL, &ppdata,
|
||||
host->board.parts, host->board.num_parts);
|
||||
res = mtd_device_register(mtd, host->board.parts,
|
||||
host->board.num_parts);
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
|
@ -2284,7 +2284,7 @@ static int atmel_nand_probe(struct platform_device *pdev)
|
|||
static int atmel_nand_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct atmel_nand_host *host = platform_get_drvdata(pdev);
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
|
||||
|
||||
nand_release(mtd);
|
||||
|
||||
|
@ -2304,11 +2304,11 @@ static int atmel_nand_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct atmel_nand_caps at91rm9200_caps = {
|
||||
static const struct atmel_nand_caps at91rm9200_caps = {
|
||||
.pmecc_correct_erase_page = false,
|
||||
};
|
||||
|
||||
static struct atmel_nand_caps sama5d4_caps = {
|
||||
static const struct atmel_nand_caps sama5d4_caps = {
|
||||
.pmecc_correct_erase_page = true,
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
|
||||
struct au1550nd_ctx {
|
||||
struct mtd_info info;
|
||||
struct nand_chip chip;
|
||||
|
||||
int cs;
|
||||
|
@ -39,7 +38,7 @@ struct au1550nd_ctx {
|
|||
*/
|
||||
static u_char au_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
u_char ret = readb(this->IO_ADDR_R);
|
||||
wmb(); /* drain writebuffer */
|
||||
return ret;
|
||||
|
@ -54,7 +53,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
|
|||
*/
|
||||
static void au_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
writeb(byte, this->IO_ADDR_W);
|
||||
wmb(); /* drain writebuffer */
|
||||
}
|
||||
|
@ -67,7 +66,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
|
|||
*/
|
||||
static u_char au_read_byte16(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
|
||||
wmb(); /* drain writebuffer */
|
||||
return ret;
|
||||
|
@ -82,7 +81,7 @@ static u_char au_read_byte16(struct mtd_info *mtd)
|
|||
*/
|
||||
static void au_write_byte16(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
|
||||
wmb(); /* drain writebuffer */
|
||||
}
|
||||
|
@ -95,7 +94,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
|
|||
*/
|
||||
static u16 au_read_word(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
u16 ret = readw(this->IO_ADDR_R);
|
||||
wmb(); /* drain writebuffer */
|
||||
return ret;
|
||||
|
@ -112,7 +111,7 @@ static u16 au_read_word(struct mtd_info *mtd)
|
|||
static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
writeb(buf[i], this->IO_ADDR_W);
|
||||
|
@ -131,7 +130,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = readb(this->IO_ADDR_R);
|
||||
|
@ -150,7 +149,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
u16 *p = (u16 *) buf;
|
||||
len >>= 1;
|
||||
|
||||
|
@ -172,7 +171,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
u16 *p = (u16 *) buf;
|
||||
len >>= 1;
|
||||
|
||||
|
@ -197,8 +196,9 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info);
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
|
||||
chip);
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
|
@ -267,8 +267,9 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip)
|
|||
*/
|
||||
static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
|
||||
{
|
||||
struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info);
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
|
||||
chip);
|
||||
int ce_override = 0, i;
|
||||
unsigned long flags = 0;
|
||||
|
||||
|
@ -405,6 +406,7 @@ static int au1550nd_probe(struct platform_device *pdev)
|
|||
struct au1550nd_platdata *pd;
|
||||
struct au1550nd_ctx *ctx;
|
||||
struct nand_chip *this;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *r;
|
||||
int ret, cs;
|
||||
|
||||
|
@ -438,8 +440,8 @@ static int au1550nd_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
this = &ctx->chip;
|
||||
ctx->info.priv = this;
|
||||
ctx->info.dev.parent = &pdev->dev;
|
||||
mtd = nand_to_mtd(this);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
/* figure out which CS# r->start belongs to */
|
||||
cs = find_nand_cs(r->start);
|
||||
|
@ -467,13 +469,13 @@ static int au1550nd_probe(struct platform_device *pdev)
|
|||
this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
|
||||
this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
|
||||
|
||||
ret = nand_scan(&ctx->info, 1);
|
||||
ret = nand_scan(mtd, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "NAND scan failed with %d\n", ret);
|
||||
goto out3;
|
||||
}
|
||||
|
||||
mtd_device_register(&ctx->info, pd->parts, pd->num_parts);
|
||||
mtd_device_register(mtd, pd->parts, pd->num_parts);
|
||||
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
|
@ -493,7 +495,7 @@ static int au1550nd_remove(struct platform_device *pdev)
|
|||
struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
|
||||
struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
nand_release(&ctx->info);
|
||||
nand_release(nand_to_mtd(&ctx->chip));
|
||||
iounmap(ctx->base);
|
||||
release_mem_region(r->start, 0x1000);
|
||||
kfree(ctx);
|
||||
|
|
|
@ -12,7 +12,6 @@ struct bcm47xxnflash {
|
|||
struct bcma_drv_cc *cc;
|
||||
|
||||
struct nand_chip nand_chip;
|
||||
struct mtd_info mtd;
|
||||
|
||||
unsigned curr_command;
|
||||
int curr_page_addr;
|
||||
|
|
|
@ -27,15 +27,16 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
|
||||
struct bcm47xxnflash *b47n;
|
||||
struct mtd_info *mtd;
|
||||
int err = 0;
|
||||
|
||||
b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL);
|
||||
if (!b47n)
|
||||
return -ENOMEM;
|
||||
|
||||
b47n->nand_chip.priv = b47n;
|
||||
b47n->mtd.dev.parent = &pdev->dev;
|
||||
b47n->mtd.priv = &b47n->nand_chip; /* Required */
|
||||
nand_set_controller_data(&b47n->nand_chip, b47n);
|
||||
mtd = nand_to_mtd(&b47n->nand_chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
|
||||
|
||||
if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
|
||||
|
@ -49,7 +50,9 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0);
|
||||
platform_set_drvdata(pdev, b47n);
|
||||
|
||||
err = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
|
||||
if (err) {
|
||||
pr_err("Failed to register MTD device: %d\n", err);
|
||||
return err;
|
||||
|
@ -60,10 +63,9 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
|
|||
|
||||
static int bcm47xxnflash_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
|
||||
struct bcm47xxnflash *nflash = platform_get_drvdata(pdev);
|
||||
|
||||
if (nflash->mtd)
|
||||
mtd_device_unregister(nflash->mtd);
|
||||
nand_release(nand_to_mtd(&nflash->nand_chip));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -89,8 +89,8 @@ static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
|
|||
static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
|
||||
int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
|
||||
u32 ctlcode;
|
||||
u32 *dest = (u32 *)buf;
|
||||
|
@ -139,8 +139,8 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
|
|||
static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
struct bcma_drv_cc *cc = b47n->cc;
|
||||
|
||||
u32 ctlcode;
|
||||
|
@ -173,8 +173,8 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
|
|||
static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
u32 code = 0;
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
|
@ -199,8 +199,8 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
|
|||
|
||||
static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
|
||||
return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
|
||||
}
|
||||
|
@ -216,8 +216,8 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
|
|||
unsigned command, int column,
|
||||
int page_addr)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
struct bcma_drv_cc *cc = b47n->cc;
|
||||
u32 ctlcode;
|
||||
int i;
|
||||
|
@ -312,8 +312,8 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
|
|||
|
||||
static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
struct bcma_drv_cc *cc = b47n->cc;
|
||||
u32 tmp = 0;
|
||||
|
||||
|
@ -341,8 +341,8 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
|
|||
static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
|
||||
switch (b47n->curr_command) {
|
||||
case NAND_CMD_READ0:
|
||||
|
@ -357,8 +357,8 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
|
|||
static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
|
||||
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
|
||||
|
||||
switch (b47n->curr_command) {
|
||||
case NAND_CMD_SEQIN:
|
||||
|
@ -421,7 +421,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
|
|||
(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
|
||||
|
||||
/* Scan NAND */
|
||||
err = nand_scan(&b47n->mtd, 1);
|
||||
err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1);
|
||||
if (err) {
|
||||
pr_err("Could not scan NAND flash: %d\n", err);
|
||||
goto exit;
|
||||
|
|
|
@ -142,7 +142,6 @@ static struct nand_ecclayout bootrom_ecclayout = {
|
|||
struct bf5xx_nand_info {
|
||||
/* mtd info */
|
||||
struct nand_hw_control controller;
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
|
||||
/* platform info */
|
||||
|
@ -160,7 +159,8 @@ struct bf5xx_nand_info {
|
|||
*/
|
||||
static struct bf5xx_nand_info *mtd_to_nand_info(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd, struct bf5xx_nand_info, mtd);
|
||||
return container_of(mtd_to_nand(mtd), struct bf5xx_nand_info,
|
||||
chip);
|
||||
}
|
||||
|
||||
static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev)
|
||||
|
@ -252,7 +252,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
|
|||
*/
|
||||
if (hweight32(syndrome[0]) == 1) {
|
||||
dev_err(info->device, "ECC data was incorrect!\n");
|
||||
return 1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF);
|
||||
|
@ -285,7 +285,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
|
|||
data = data ^ (0x1 << failing_bit);
|
||||
*(dat + failing_byte) = data;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -298,26 +298,34 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
|
|||
dev_err(info->device,
|
||||
"Please discard data, mark bad block\n");
|
||||
|
||||
return 1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
int ret;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int ret, bitflips = 0;
|
||||
|
||||
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bitflips = ret;
|
||||
|
||||
/* If ecc size is 512, correct second 256 bytes */
|
||||
if (chip->ecc.size == 512) {
|
||||
dat += 256;
|
||||
read_ecc += 3;
|
||||
calc_ecc += 3;
|
||||
ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
|
||||
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bitflips += ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return bitflips;
|
||||
}
|
||||
|
||||
static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
|
@ -329,7 +337,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
|
|||
const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u16 ecc0, ecc1;
|
||||
u32 code[2];
|
||||
u8 *p;
|
||||
|
@ -466,7 +474,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
|
|||
uint8_t *buf, int is_read)
|
||||
{
|
||||
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
unsigned short val;
|
||||
|
||||
dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
|
||||
|
@ -532,7 +540,7 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
|
|||
uint8_t *buf, int len)
|
||||
{
|
||||
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
|
||||
|
||||
|
@ -546,7 +554,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
|
|||
const uint8_t *buf, int len)
|
||||
{
|
||||
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
|
||||
|
||||
|
@ -660,7 +668,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
|
|||
*/
|
||||
static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
|
||||
{
|
||||
struct mtd_info *mtd = &info->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&info->chip);
|
||||
struct mtd_partition *parts = info->platform->partitions;
|
||||
int nr = info->platform->nr_partitions;
|
||||
|
||||
|
@ -675,7 +683,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
|
|||
* and their partitions, then go through freeing the
|
||||
* resources used
|
||||
*/
|
||||
nand_release(&info->mtd);
|
||||
nand_release(nand_to_mtd(&info->chip));
|
||||
|
||||
peripheral_free_list(bfin_nfc_pin_req);
|
||||
bf5xx_nand_dma_remove(info);
|
||||
|
@ -685,7 +693,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
|
|||
|
||||
static int bf5xx_nand_scan(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int ret;
|
||||
|
||||
ret = nand_scan_ident(mtd, 1, NULL);
|
||||
|
@ -756,6 +764,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
|
|||
|
||||
/* initialise chip data struct */
|
||||
chip = &info->chip;
|
||||
mtd = nand_to_mtd(&info->chip);
|
||||
|
||||
if (plat->data_width)
|
||||
chip->options |= NAND_BUSWIDTH_16;
|
||||
|
@ -772,7 +781,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
|
|||
chip->cmd_ctrl = bf5xx_nand_hwcontrol;
|
||||
chip->dev_ready = bf5xx_nand_devready;
|
||||
|
||||
chip->priv = &info->mtd;
|
||||
nand_set_controller_data(chip, mtd);
|
||||
chip->controller = &info->controller;
|
||||
|
||||
chip->IO_ADDR_R = (void __iomem *) NFC_READ;
|
||||
|
@ -781,8 +790,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
|
|||
chip->chip_delay = 0;
|
||||
|
||||
/* initialise mtd info data struct */
|
||||
mtd = &info->mtd;
|
||||
mtd->priv = chip;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
/* initialise the hardware */
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
# more specific iproc_nand.o, for instance
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2015 Simon Arlott
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from bcm63138_nand.c:
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*
|
||||
* Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
|
||||
* Copyright 2000-2010 Broadcom Corporation
|
||||
*
|
||||
* Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
|
||||
* Copyright 2000-2010 Broadcom Corporation
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "brcmnand.h"
|
||||
|
||||
struct bcm6368_nand_soc {
|
||||
struct brcmnand_soc soc;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
#define BCM6368_NAND_INT 0x00
|
||||
#define BCM6368_NAND_STATUS_SHIFT 0
|
||||
#define BCM6368_NAND_STATUS_MASK (0xfff << BCM6368_NAND_STATUS_SHIFT)
|
||||
#define BCM6368_NAND_ENABLE_SHIFT 16
|
||||
#define BCM6368_NAND_ENABLE_MASK (0xffff << BCM6368_NAND_ENABLE_SHIFT)
|
||||
#define BCM6368_NAND_BASE_ADDR0 0x04
|
||||
#define BCM6368_NAND_BASE_ADDR1 0x0c
|
||||
|
||||
enum {
|
||||
BCM6368_NP_READ = BIT(0),
|
||||
BCM6368_BLOCK_ERASE = BIT(1),
|
||||
BCM6368_COPY_BACK = BIT(2),
|
||||
BCM6368_PAGE_PGM = BIT(3),
|
||||
BCM6368_CTRL_READY = BIT(4),
|
||||
BCM6368_DEV_RBPIN = BIT(5),
|
||||
BCM6368_ECC_ERR_UNC = BIT(6),
|
||||
BCM6368_ECC_ERR_CORR = BIT(7),
|
||||
};
|
||||
|
||||
static bool bcm6368_nand_intc_ack(struct brcmnand_soc *soc)
|
||||
{
|
||||
struct bcm6368_nand_soc *priv =
|
||||
container_of(soc, struct bcm6368_nand_soc, soc);
|
||||
void __iomem *mmio = priv->base + BCM6368_NAND_INT;
|
||||
u32 val = brcmnand_readl(mmio);
|
||||
|
||||
if (val & (BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT)) {
|
||||
/* Ack interrupt */
|
||||
val &= ~BCM6368_NAND_STATUS_MASK;
|
||||
val |= BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT;
|
||||
brcmnand_writel(val, mmio);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void bcm6368_nand_intc_set(struct brcmnand_soc *soc, bool en)
|
||||
{
|
||||
struct bcm6368_nand_soc *priv =
|
||||
container_of(soc, struct bcm6368_nand_soc, soc);
|
||||
void __iomem *mmio = priv->base + BCM6368_NAND_INT;
|
||||
u32 val = brcmnand_readl(mmio);
|
||||
|
||||
/* Don't ack any interrupts */
|
||||
val &= ~BCM6368_NAND_STATUS_MASK;
|
||||
|
||||
if (en)
|
||||
val |= BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT;
|
||||
else
|
||||
val &= ~(BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT);
|
||||
|
||||
brcmnand_writel(val, mmio);
|
||||
}
|
||||
|
||||
static int bcm6368_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcm6368_nand_soc *priv;
|
||||
struct brcmnand_soc *soc;
|
||||
struct resource *res;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
soc = &priv->soc;
|
||||
|
||||
res = platform_get_resource_byname(pdev,
|
||||
IORESOURCE_MEM, "nand-int-base");
|
||||
priv->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
soc->ctlrdy_ack = bcm6368_nand_intc_ack;
|
||||
soc->ctlrdy_set_enabled = bcm6368_nand_intc_set;
|
||||
|
||||
/* Disable and ack all interrupts */
|
||||
brcmnand_writel(0, priv->base + BCM6368_NAND_INT);
|
||||
brcmnand_writel(BCM6368_NAND_STATUS_MASK,
|
||||
priv->base + BCM6368_NAND_INT);
|
||||
|
||||
return brcmnand_probe(pdev, soc);
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm6368_nand_of_match[] = {
|
||||
{ .compatible = "brcm,nand-bcm6368" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcm6368_nand_of_match);
|
||||
|
||||
static struct platform_driver bcm6368_nand_driver = {
|
||||
.probe = bcm6368_nand_probe,
|
||||
.remove = brcmnand_remove,
|
||||
.driver = {
|
||||
.name = "bcm6368_nand",
|
||||
.pm = &brcmnand_pm_ops,
|
||||
.of_match_table = bcm6368_nand_of_match,
|
||||
}
|
||||
};
|
||||
module_platform_driver(bcm6368_nand_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Simon Arlott");
|
||||
MODULE_DESCRIPTION("NAND driver for BCM6368");
|
|
@ -11,6 +11,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -122,6 +123,9 @@ struct brcmnand_controller {
|
|||
/* Some SoCs provide custom interrupt status register(s) */
|
||||
struct brcmnand_soc *soc;
|
||||
|
||||
/* Some SoCs have a gateable clock for the controller */
|
||||
struct clk *clk;
|
||||
|
||||
int cmd_pending;
|
||||
bool dma_pending;
|
||||
struct completion done;
|
||||
|
@ -134,7 +138,7 @@ struct brcmnand_controller {
|
|||
dma_addr_t dma_pa;
|
||||
|
||||
/* in-memory cache of the FLASH_CACHE, used only for some commands */
|
||||
u32 flash_cache[FC_WORDS];
|
||||
u8 flash_cache[FC_BYTES];
|
||||
|
||||
/* Controller revision details */
|
||||
const u16 *reg_offsets;
|
||||
|
@ -176,10 +180,8 @@ struct brcmnand_cfg {
|
|||
|
||||
struct brcmnand_host {
|
||||
struct list_head node;
|
||||
struct device_node *of_node;
|
||||
|
||||
struct nand_chip chip;
|
||||
struct mtd_info mtd;
|
||||
struct platform_device *pdev;
|
||||
int cs;
|
||||
|
||||
|
@ -874,8 +876,8 @@ static struct nand_ecclayout *brcmstb_choose_ecc_layout(
|
|||
|
||||
static void brcmnand_wp(struct mtd_info *mtd, int wp)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
|
||||
if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) {
|
||||
|
@ -1040,8 +1042,8 @@ static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat,
|
|||
|
||||
static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
unsigned long timeo = msecs_to_jiffies(100);
|
||||
|
||||
|
@ -1075,7 +1077,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
|
|||
enum brcmnand_llop_type type, u32 data,
|
||||
bool last_op)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
||||
struct nand_chip *chip = &host->chip;
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
u32 tmp;
|
||||
|
@ -1114,8 +1116,8 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
|
|||
static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
u64 addr = (u64)page_addr << chip->page_shift;
|
||||
int native_cmd = 0;
|
||||
|
@ -1188,6 +1190,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
|||
|
||||
if (native_cmd == CMD_PARAMETER_READ ||
|
||||
native_cmd == CMD_PARAMETER_CHANGE_COL) {
|
||||
/* Copy flash cache word-wise */
|
||||
u32 *flash_cache = (u32 *)ctrl->flash_cache;
|
||||
int i;
|
||||
|
||||
brcmnand_soc_data_bus_prepare(ctrl->soc);
|
||||
|
@ -1197,7 +1201,11 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
|||
* SECTOR_SIZE_1K may invalidate it
|
||||
*/
|
||||
for (i = 0; i < FC_WORDS; i++)
|
||||
ctrl->flash_cache[i] = brcmnand_read_fc(ctrl, i);
|
||||
/*
|
||||
* Flash cache is big endian for parameter pages, at
|
||||
* least on STB SoCs
|
||||
*/
|
||||
flash_cache[i] = be32_to_cpu(brcmnand_read_fc(ctrl, i));
|
||||
|
||||
brcmnand_soc_data_bus_unprepare(ctrl->soc);
|
||||
|
||||
|
@ -1214,8 +1222,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
|||
|
||||
static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
uint8_t ret = 0;
|
||||
int addr, offs;
|
||||
|
@ -1250,8 +1258,7 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
|
|||
if (host->last_byte > 0 && offs == 0)
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, addr, -1);
|
||||
|
||||
ret = ctrl->flash_cache[offs >> 2] >>
|
||||
(24 - ((offs & 0x03) << 3));
|
||||
ret = ctrl->flash_cache[offs];
|
||||
break;
|
||||
case NAND_CMD_GET_FEATURES:
|
||||
if (host->last_byte >= ONFI_SUBFEATURE_PARAM_LEN) {
|
||||
|
@ -1282,8 +1289,8 @@ static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
|||
int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
switch (host->last_cmd) {
|
||||
case NAND_CMD_SET_FEATURES:
|
||||
|
@ -1393,13 +1400,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
u64 addr, unsigned int trans, u32 *buf,
|
||||
u8 *oob, u64 *err_addr)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
int i, j, ret = 0;
|
||||
|
||||
/* Clear error addresses */
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
|
||||
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
|
||||
(host->cs << 16) | ((addr >> 32) & 0xffff));
|
||||
|
@ -1454,7 +1463,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
u64 addr, unsigned int trans, u32 *buf, u8 *oob)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
u64 err_addr = 0;
|
||||
int err;
|
||||
|
@ -1504,7 +1513,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
|
||||
|
||||
return brcmnand_read(mtd, chip, host->last_addr,
|
||||
|
@ -1514,7 +1523,7 @@ static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
|
||||
int ret;
|
||||
|
||||
|
@ -1536,7 +1545,7 @@ static int brcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
brcmnand_set_ecc_enabled(host, 0);
|
||||
brcmnand_read(mtd, chip, (u64)page << chip->page_shift,
|
||||
|
@ -1546,20 +1555,10 @@ static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int brcmnand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint32_t data_offs, uint32_t readlen,
|
||||
uint8_t *bufpoi, int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
|
||||
return brcmnand_read(mtd, chip, host->last_addr + data_offs,
|
||||
readlen >> FC_SHIFT, (u32 *)bufpoi, NULL);
|
||||
}
|
||||
|
||||
static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
u64 addr, const u32 *buf, u8 *oob)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
unsigned int i, j, trans = mtd->writesize >> FC_SHIFT;
|
||||
int status, ret = 0;
|
||||
|
@ -1630,7 +1629,7 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
const uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
void *oob = oob_required ? chip->oob_poi : NULL;
|
||||
|
||||
brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob);
|
||||
|
@ -1641,7 +1640,7 @@ static int brcmnand_write_page_raw(struct mtd_info *mtd,
|
|||
struct nand_chip *chip, const uint8_t *buf,
|
||||
int oob_required, int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
void *oob = oob_required ? chip->oob_poi : NULL;
|
||||
|
||||
brcmnand_set_ecc_enabled(host, 0);
|
||||
|
@ -1660,7 +1659,7 @@ static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int brcmnand_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int page)
|
||||
{
|
||||
struct brcmnand_host *host = chip->priv;
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
int ret;
|
||||
|
||||
brcmnand_set_ecc_enabled(host, 0);
|
||||
|
@ -1806,7 +1805,7 @@ static inline int get_blk_adr_bytes(u64 size, u32 writesize)
|
|||
|
||||
static int brcmnand_setup_dev(struct brcmnand_host *host)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
||||
struct nand_chip *chip = &host->chip;
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
struct brcmnand_cfg *cfg = &host->hwcfg;
|
||||
|
@ -1816,7 +1815,7 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
|
|||
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
|
||||
ret = of_property_read_u32(chip->flash_node,
|
||||
ret = of_property_read_u32(nand_get_flash_node(chip),
|
||||
"brcm,nand-oob-sector-size",
|
||||
&oob_sector);
|
||||
if (ret) {
|
||||
|
@ -1905,16 +1904,14 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int brcmnand_init_cs(struct brcmnand_host *host)
|
||||
static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
|
||||
{
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
struct device_node *dn = host->of_node;
|
||||
struct platform_device *pdev = host->pdev;
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *chip;
|
||||
int ret;
|
||||
u16 cfg_offs;
|
||||
struct mtd_part_parser_data ppdata = { .of_node = dn };
|
||||
|
||||
ret = of_property_read_u32(dn, "reg", &host->cs);
|
||||
if (ret) {
|
||||
|
@ -1922,12 +1919,11 @@ static int brcmnand_init_cs(struct brcmnand_host *host)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
mtd = &host->mtd;
|
||||
mtd = nand_to_mtd(&host->chip);
|
||||
chip = &host->chip;
|
||||
|
||||
chip->flash_node = dn;
|
||||
chip->priv = host;
|
||||
mtd->priv = chip;
|
||||
nand_set_flash_node(chip, dn);
|
||||
nand_set_controller_data(chip, host);
|
||||
mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d",
|
||||
host->cs);
|
||||
mtd->owner = THIS_MODULE;
|
||||
|
@ -1945,7 +1941,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host)
|
|||
|
||||
chip->ecc.mode = NAND_ECC_HW;
|
||||
chip->ecc.read_page = brcmnand_read_page;
|
||||
chip->ecc.read_subpage = brcmnand_read_subpage;
|
||||
chip->ecc.write_page = brcmnand_write_page;
|
||||
chip->ecc.read_page_raw = brcmnand_read_page_raw;
|
||||
chip->ecc.write_page_raw = brcmnand_write_page_raw;
|
||||
|
@ -1993,7 +1988,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host)
|
|||
if (nand_scan_tail(mtd))
|
||||
return -ENXIO;
|
||||
|
||||
return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
return mtd_device_register(mtd, NULL, 0);
|
||||
}
|
||||
|
||||
static void brcmnand_save_restore_cs_config(struct brcmnand_host *host,
|
||||
|
@ -2067,8 +2062,8 @@ static int brcmnand_resume(struct device *dev)
|
|||
}
|
||||
|
||||
list_for_each_entry(host, &ctrl->host_list, node) {
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = &host->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
|
||||
brcmnand_save_restore_cs_config(host, 1);
|
||||
|
||||
|
@ -2134,10 +2129,24 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
if (IS_ERR(ctrl->nand_base))
|
||||
return PTR_ERR(ctrl->nand_base);
|
||||
|
||||
/* Enable clock before using NAND registers */
|
||||
ctrl->clk = devm_clk_get(dev, "nand");
|
||||
if (!IS_ERR(ctrl->clk)) {
|
||||
ret = clk_prepare_enable(ctrl->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = PTR_ERR(ctrl->clk);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
ctrl->clk = NULL;
|
||||
}
|
||||
|
||||
/* Initialize NAND revision */
|
||||
ret = brcmnand_revision_init(ctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Most chips have this cache at a fixed offset within 'nand' block.
|
||||
|
@ -2146,8 +2155,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache");
|
||||
if (res) {
|
||||
ctrl->nand_fc = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(ctrl->nand_fc))
|
||||
return PTR_ERR(ctrl->nand_fc);
|
||||
if (IS_ERR(ctrl->nand_fc)) {
|
||||
ret = PTR_ERR(ctrl->nand_fc);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
ctrl->nand_fc = ctrl->nand_base +
|
||||
ctrl->reg_offsets[BRCMNAND_FC_BASE];
|
||||
|
@ -2157,8 +2168,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma");
|
||||
if (res) {
|
||||
ctrl->flash_dma_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(ctrl->flash_dma_base))
|
||||
return PTR_ERR(ctrl->flash_dma_base);
|
||||
if (IS_ERR(ctrl->flash_dma_base)) {
|
||||
ret = PTR_ERR(ctrl->flash_dma_base);
|
||||
goto err;
|
||||
}
|
||||
|
||||
flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
|
||||
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
|
||||
|
@ -2167,13 +2180,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
ctrl->dma_desc = dmam_alloc_coherent(dev,
|
||||
sizeof(*ctrl->dma_desc),
|
||||
&ctrl->dma_pa, GFP_KERNEL);
|
||||
if (!ctrl->dma_desc)
|
||||
return -ENOMEM;
|
||||
if (!ctrl->dma_desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctrl->dma_irq = platform_get_irq(pdev, 1);
|
||||
if ((int)ctrl->dma_irq < 0) {
|
||||
dev_err(dev, "missing FLASH_DMA IRQ\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, ctrl->dma_irq,
|
||||
|
@ -2182,7 +2198,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
if (ret < 0) {
|
||||
dev_err(dev, "can't allocate IRQ %d: error %d\n",
|
||||
ctrl->dma_irq, ret);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_info(dev, "enabling FLASH_DMA\n");
|
||||
|
@ -2206,7 +2222,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
ctrl->irq = platform_get_irq(pdev, 0);
|
||||
if ((int)ctrl->irq < 0) {
|
||||
dev_err(dev, "no IRQ defined\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2230,7 +2247,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
if (ret < 0) {
|
||||
dev_err(dev, "can't allocate IRQ %d: error %d\n",
|
||||
ctrl->irq, ret);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for_each_available_child_of_node(dn, child) {
|
||||
|
@ -2238,25 +2255,36 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
|||
struct brcmnand_host *host;
|
||||
|
||||
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
if (!host) {
|
||||
of_node_put(child);
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
host->pdev = pdev;
|
||||
host->ctrl = ctrl;
|
||||
host->of_node = child;
|
||||
|
||||
ret = brcmnand_init_cs(host);
|
||||
if (ret)
|
||||
ret = brcmnand_init_cs(host, child);
|
||||
if (ret) {
|
||||
devm_kfree(dev, host);
|
||||
continue; /* Try all chip-selects */
|
||||
}
|
||||
|
||||
list_add_tail(&host->node, &ctrl->host_list);
|
||||
}
|
||||
}
|
||||
|
||||
/* No chip-selects could initialize properly */
|
||||
if (list_empty(&ctrl->host_list))
|
||||
return -ENODEV;
|
||||
if (list_empty(&ctrl->host_list)) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
clk_disable_unprepare(ctrl->clk);
|
||||
return ret;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(brcmnand_probe);
|
||||
|
||||
|
@ -2266,7 +2294,9 @@ int brcmnand_remove(struct platform_device *pdev)
|
|||
struct brcmnand_host *host;
|
||||
|
||||
list_for_each_entry(host, &ctrl->host_list, node)
|
||||
nand_release(&host->mtd);
|
||||
nand_release(nand_to_mtd(&host->chip));
|
||||
|
||||
clk_disable_unprepare(ctrl->clk);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
|
|||
|
||||
static int cafe_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
|
||||
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
|
||||
|
||||
|
@ -117,7 +118,8 @@ static int cafe_device_ready(struct mtd_info *mtd)
|
|||
|
||||
static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
|
||||
if (usedma)
|
||||
memcpy(cafe->dmabuf + cafe->datalen, buf, len);
|
||||
|
@ -132,7 +134,8 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||
|
||||
static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
|
||||
if (usedma)
|
||||
memcpy(buf, cafe->dmabuf + cafe->datalen, len);
|
||||
|
@ -146,7 +149,8 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
|
||||
static uint8_t cafe_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
uint8_t d;
|
||||
|
||||
cafe_read_buf(mtd, &d, 1);
|
||||
|
@ -158,7 +162,8 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd)
|
|||
static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
int adrbytes = 0;
|
||||
uint32_t ctl1;
|
||||
uint32_t doneint = 0x80000000;
|
||||
|
@ -313,7 +318,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
|||
|
||||
static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
|
||||
cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
|
||||
|
||||
|
@ -328,7 +334,8 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
|
|||
static irqreturn_t cafe_nand_interrupt(int irq, void *id)
|
||||
{
|
||||
struct mtd_info *mtd = id;
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
|
||||
cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
|
||||
if (!irqs)
|
||||
|
@ -377,7 +384,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
unsigned int max_bitflips = 0;
|
||||
|
||||
cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
|
||||
|
@ -519,7 +526,7 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
|
|||
const uint8_t *buf, int oob_required,
|
||||
int page)
|
||||
{
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
|
||||
chip->write_buf(mtd, buf, mtd->writesize);
|
||||
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
|
@ -598,13 +605,13 @@ static int cafe_nand_probe(struct pci_dev *pdev,
|
|||
|
||||
pci_set_master(pdev);
|
||||
|
||||
mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
|
||||
if (!mtd)
|
||||
cafe = kzalloc(sizeof(*cafe), GFP_KERNEL);
|
||||
if (!cafe)
|
||||
return -ENOMEM;
|
||||
cafe = (void *)(&mtd[1]);
|
||||
|
||||
mtd = nand_to_mtd(&cafe->nand);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
mtd->priv = cafe;
|
||||
nand_set_controller_data(&cafe->nand, cafe);
|
||||
|
||||
cafe->pdev = pdev;
|
||||
cafe->mmio = pci_iomap(pdev, 0, 0);
|
||||
|
@ -784,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
|
|||
out_ior:
|
||||
pci_iounmap(pdev, cafe->mmio);
|
||||
out_free_mtd:
|
||||
kfree(mtd);
|
||||
kfree(cafe);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -792,7 +799,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
|
|||
static void cafe_nand_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct mtd_info *mtd = pci_get_drvdata(pdev);
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
|
||||
/* Disable NAND IRQ in global IRQ mask register */
|
||||
cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
|
||||
|
@ -804,7 +812,7 @@ static void cafe_nand_remove(struct pci_dev *pdev)
|
|||
2112 + sizeof(struct nand_buffers) +
|
||||
mtd->writesize + mtd->oobsize,
|
||||
cafe->dmabuf, cafe->dmaaddr);
|
||||
kfree(mtd);
|
||||
kfree(cafe);
|
||||
}
|
||||
|
||||
static const struct pci_device_id cafe_nand_tbl[] = {
|
||||
|
@ -819,7 +827,8 @@ static int cafe_nand_resume(struct pci_dev *pdev)
|
|||
{
|
||||
uint32_t ctrl;
|
||||
struct mtd_info *mtd = pci_get_drvdata(pdev);
|
||||
struct cafe_priv *cafe = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct cafe_priv *cafe = nand_get_controller_data(chip);
|
||||
|
||||
/* Start off by resetting the NAND controller completely */
|
||||
cafe_writel(cafe, 1, NAND_RESET);
|
||||
|
|
|
@ -53,7 +53,7 @@ static struct mtd_partition partition_info[] = {
|
|||
|
||||
static u_char cmx270_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
return (readl(this->IO_ADDR_R) >> 16);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ static u_char cmx270_read_byte(struct mtd_info *mtd)
|
|||
static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
writel((*buf++ << 16), this->IO_ADDR_W);
|
||||
|
@ -70,7 +70,7 @@ static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
*buf++ = readl(this->IO_ADDR_R) >> 16;
|
||||
|
@ -94,7 +94,7 @@ static void nand_cs_off(void)
|
|||
static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip* this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
|
||||
|
||||
dsb();
|
||||
|
@ -160,10 +160,8 @@ static int __init cmx270_init(void)
|
|||
gpio_direction_input(GPIO_NAND_RB);
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
if (!cmx270_nand_mtd) {
|
||||
this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!this) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc;
|
||||
}
|
||||
|
@ -175,12 +173,10 @@ static int __init cmx270_init(void)
|
|||
goto err_ioremap;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *)(&cmx270_nand_mtd[1]);
|
||||
cmx270_nand_mtd = nand_to_mtd(this);
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
cmx270_nand_mtd->owner = THIS_MODULE;
|
||||
cmx270_nand_mtd->priv = this;
|
||||
|
||||
/* insert callbacks */
|
||||
this->IO_ADDR_R = cmx270_nand_io;
|
||||
|
@ -216,7 +212,7 @@ static int __init cmx270_init(void)
|
|||
err_scan:
|
||||
iounmap(cmx270_nand_io);
|
||||
err_ioremap:
|
||||
kfree(cmx270_nand_mtd);
|
||||
kfree(this);
|
||||
err_kzalloc:
|
||||
gpio_free(GPIO_NAND_RB);
|
||||
err_gpio_request:
|
||||
|
@ -240,8 +236,7 @@ static void __exit cmx270_cleanup(void)
|
|||
|
||||
iounmap(cmx270_nand_io);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (cmx270_nand_mtd);
|
||||
kfree(mtd_to_nand(cmx270_nand_mtd));
|
||||
}
|
||||
module_exit(cmx270_cleanup);
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
|
||||
static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
while (unlikely(len > 0x800)) {
|
||||
memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
|
||||
|
@ -109,7 +109,7 @@ static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
while (unlikely(len > 0x800)) {
|
||||
memcpy_toio(this->IO_ADDR_R, buf, 0x800);
|
||||
|
@ -121,13 +121,13 @@ static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
|
||||
static unsigned char cs553x_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
return readb(this->IO_ADDR_R);
|
||||
}
|
||||
|
||||
static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int i = 100000;
|
||||
|
||||
while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
|
||||
|
@ -140,7 +140,7 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
|
|||
static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
|
||||
|
@ -152,7 +152,7 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
|
|||
|
||||
static int cs553x_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
unsigned char foo = readb(mmio_base + MM_NAND_STS);
|
||||
|
||||
|
@ -161,7 +161,7 @@ static int cs553x_device_ready(struct mtd_info *mtd)
|
|||
|
||||
static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
|
||||
writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
|
||||
|
@ -170,7 +170,7 @@ static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
uint32_t ecc;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
|
||||
ecc = readl(mmio_base + MM_NAND_STS);
|
||||
|
@ -197,17 +197,15 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
|||
}
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!new_mtd) {
|
||||
this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!this) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *)(&new_mtd[1]);
|
||||
new_mtd = nand_to_mtd(this);
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
new_mtd->priv = this;
|
||||
new_mtd->owner = THIS_MODULE;
|
||||
|
||||
/* map physical address */
|
||||
|
@ -257,7 +255,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
|||
out_ior:
|
||||
iounmap(this->IO_ADDR_R);
|
||||
out_mtd:
|
||||
kfree(new_mtd);
|
||||
kfree(this);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -337,19 +335,19 @@ static void __exit cs553x_cleanup(void)
|
|||
if (!mtd)
|
||||
continue;
|
||||
|
||||
this = cs553x_mtd[i]->priv;
|
||||
this = mtd_to_nand(mtd);
|
||||
mmio_base = this->IO_ADDR_R;
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release(cs553x_mtd[i]);
|
||||
kfree(cs553x_mtd[i]->name);
|
||||
nand_release(mtd);
|
||||
kfree(mtd->name);
|
||||
cs553x_mtd[i] = NULL;
|
||||
|
||||
/* unmap physical address */
|
||||
iounmap(mmio_base);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree(mtd);
|
||||
kfree(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
* outputs in a "wire-AND" configuration, with no per-chip signals.
|
||||
*/
|
||||
struct davinci_nand_info {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
struct nand_ecclayout ecclayout;
|
||||
|
||||
|
@ -80,8 +79,10 @@ struct davinci_nand_info {
|
|||
static DEFINE_SPINLOCK(davinci_nand_lock);
|
||||
static bool ecc4_busy;
|
||||
|
||||
#define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd)
|
||||
|
||||
static inline struct davinci_nand_info *to_davinci_nand(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct davinci_nand_info, chip);
|
||||
}
|
||||
|
||||
static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info,
|
||||
int offset)
|
||||
|
@ -106,7 +107,7 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
|
|||
{
|
||||
struct davinci_nand_info *info = to_davinci_nand(mtd);
|
||||
uint32_t addr = info->current_cs;
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
|
||||
/* Did the control lines change? */
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
|
@ -192,7 +193,7 @@ static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
|
|||
static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) |
|
||||
(read_ecc[2] << 16);
|
||||
uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) |
|
||||
|
@ -206,7 +207,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
|
|||
dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7);
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
} else if (!(diff & (diff - 1))) {
|
||||
/* Single bit ECC error in the ECC itself,
|
||||
|
@ -214,7 +215,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
|
|||
return 1;
|
||||
} else {
|
||||
/* Uncorrectable error */
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -316,14 +317,6 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
|
|||
unsigned num_errors, corrected;
|
||||
unsigned long timeo;
|
||||
|
||||
/* All bytes 0xff? It's an erased page; ignore its ECC. */
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (ecc_code[i] != 0xff)
|
||||
goto compare;
|
||||
}
|
||||
return 0;
|
||||
|
||||
compare:
|
||||
/* Unpack ten bytes into eight 10 bit values. We know we're
|
||||
* little-endian, and use type punning for less shifting/masking.
|
||||
*/
|
||||
|
@ -390,7 +383,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
|
|||
return 0;
|
||||
case 1: /* five or more errors detected */
|
||||
davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
|
||||
return -EIO;
|
||||
return -EBADMSG;
|
||||
case 2: /* error addresses computed */
|
||||
case 3:
|
||||
num_errors = 1 + ((fsr >> 16) & 0x03);
|
||||
|
@ -447,7 +440,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
|
|||
*/
|
||||
static void nand_davinci_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);
|
||||
|
||||
if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
|
||||
ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
|
||||
|
@ -460,7 +453,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
static void nand_davinci_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);
|
||||
|
||||
if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
|
||||
iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
|
||||
|
@ -636,6 +629,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
uint32_t val;
|
||||
nand_ecc_modes_t ecc_mode;
|
||||
struct mtd_info *mtd;
|
||||
|
||||
pdata = nand_davinci_get_pdata(pdev);
|
||||
if (IS_ERR(pdata))
|
||||
|
@ -682,8 +676,9 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
info->base = base;
|
||||
info->vaddr = vaddr;
|
||||
|
||||
info->mtd.priv = &info->chip;
|
||||
info->mtd.dev.parent = &pdev->dev;
|
||||
mtd = nand_to_mtd(&info->chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
nand_set_flash_node(&info->chip, pdev->dev.of_node);
|
||||
|
||||
info->chip.IO_ADDR_R = vaddr;
|
||||
info->chip.IO_ADDR_W = vaddr;
|
||||
|
@ -746,6 +741,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
info->chip.ecc.correct = nand_davinci_correct_4bit;
|
||||
info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
|
||||
info->chip.ecc.bytes = 10;
|
||||
info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
|
||||
} else {
|
||||
info->chip.ecc.calculate = nand_davinci_calculate_1bit;
|
||||
info->chip.ecc.correct = nand_davinci_correct_1bit;
|
||||
|
@ -784,7 +780,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
spin_unlock_irq(&davinci_nand_lock);
|
||||
|
||||
/* Scan to find existence of the device(s) */
|
||||
ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL);
|
||||
ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
|
||||
goto err;
|
||||
|
@ -796,9 +792,9 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
* usable: 10 bytes are needed, not 6.
|
||||
*/
|
||||
if (pdata->ecc_bits == 4) {
|
||||
int chunks = info->mtd.writesize / 512;
|
||||
int chunks = mtd->writesize / 512;
|
||||
|
||||
if (!chunks || info->mtd.oobsize < 16) {
|
||||
if (!chunks || mtd->oobsize < 16) {
|
||||
dev_dbg(&pdev->dev, "too small\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
|
@ -810,8 +806,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
*/
|
||||
if (chunks == 1) {
|
||||
info->ecclayout = hwecc4_small;
|
||||
info->ecclayout.oobfree[1].length =
|
||||
info->mtd.oobsize - 16;
|
||||
info->ecclayout.oobfree[1].length = mtd->oobsize - 16;
|
||||
goto syndrome_done;
|
||||
}
|
||||
if (chunks == 4) {
|
||||
|
@ -832,20 +827,15 @@ static int nand_davinci_probe(struct platform_device *pdev)
|
|||
info->chip.ecc.layout = &info->ecclayout;
|
||||
}
|
||||
|
||||
ret = nand_scan_tail(&info->mtd);
|
||||
ret = nand_scan_tail(mtd);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (pdata->parts)
|
||||
ret = mtd_device_parse_register(&info->mtd, NULL, NULL,
|
||||
ret = mtd_device_parse_register(mtd, NULL, NULL,
|
||||
pdata->parts, pdata->nr_parts);
|
||||
else {
|
||||
struct mtd_part_parser_data ppdata;
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
ret = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
|
||||
NULL, 0);
|
||||
}
|
||||
else
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
|
@ -875,7 +865,7 @@ static int nand_davinci_remove(struct platform_device *pdev)
|
|||
ecc4_busy = false;
|
||||
spin_unlock_irq(&davinci_nand_lock);
|
||||
|
||||
nand_release(&info->mtd);
|
||||
nand_release(nand_to_mtd(&info->chip));
|
||||
|
||||
clk_disable_unprepare(info->clk);
|
||||
|
||||
|
|
|
@ -75,7 +75,10 @@ MODULE_PARM_DESC(onfi_timing_mode,
|
|||
* this macro allows us to convert from an MTD structure to our own
|
||||
* device context (denali) structure.
|
||||
*/
|
||||
#define mtd_to_denali(m) container_of(m, struct denali_nand_info, mtd)
|
||||
static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
|
||||
}
|
||||
|
||||
/*
|
||||
* These constants are defined by the driver to enable common driver
|
||||
|
@ -986,6 +989,8 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
|
|||
* than one NAND connected.
|
||||
*/
|
||||
if (err_byte < ECC_SECTOR_SIZE) {
|
||||
struct mtd_info *mtd =
|
||||
nand_to_mtd(&denali->nand);
|
||||
int offset;
|
||||
|
||||
offset = (err_sector *
|
||||
|
@ -995,7 +1000,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
|
|||
err_device;
|
||||
/* correct the ECC error */
|
||||
buf[offset] ^= err_correction_value;
|
||||
denali->mtd.ecc_stats.corrected++;
|
||||
mtd->ecc_stats.corrected++;
|
||||
bitflips++;
|
||||
}
|
||||
} else {
|
||||
|
@ -1062,7 +1067,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
{
|
||||
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
||||
dma_addr_t addr = denali->buf.dma_buf;
|
||||
size_t size = denali->mtd.writesize + denali->mtd.oobsize;
|
||||
size_t size = mtd->writesize + mtd->oobsize;
|
||||
uint32_t irq_status;
|
||||
uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP |
|
||||
INTR_STATUS__PROGRAM_FAIL;
|
||||
|
@ -1160,7 +1165,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
||||
|
||||
dma_addr_t addr = denali->buf.dma_buf;
|
||||
size_t size = denali->mtd.writesize + denali->mtd.oobsize;
|
||||
size_t size = mtd->writesize + mtd->oobsize;
|
||||
|
||||
uint32_t irq_status;
|
||||
uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE |
|
||||
|
@ -1193,14 +1198,14 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
denali_enable_dma(denali, false);
|
||||
|
||||
if (check_erased_page) {
|
||||
read_oob_data(&denali->mtd, chip->oob_poi, denali->page);
|
||||
read_oob_data(mtd, chip->oob_poi, denali->page);
|
||||
|
||||
/* check ECC failures that may have occurred on erased pages */
|
||||
if (check_erased_page) {
|
||||
if (!is_erased(buf, denali->mtd.writesize))
|
||||
denali->mtd.ecc_stats.failed++;
|
||||
if (!is_erased(buf, denali->mtd.oobsize))
|
||||
denali->mtd.ecc_stats.failed++;
|
||||
if (!is_erased(buf, mtd->writesize))
|
||||
mtd->ecc_stats.failed++;
|
||||
if (!is_erased(buf, mtd->oobsize))
|
||||
mtd->ecc_stats.failed++;
|
||||
}
|
||||
}
|
||||
return max_bitflips;
|
||||
|
@ -1211,7 +1216,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
{
|
||||
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
||||
dma_addr_t addr = denali->buf.dma_buf;
|
||||
size_t size = denali->mtd.writesize + denali->mtd.oobsize;
|
||||
size_t size = mtd->writesize + mtd->oobsize;
|
||||
uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
|
||||
|
||||
if (page != denali->page) {
|
||||
|
@ -1428,6 +1433,7 @@ static void denali_drv_init(struct denali_nand_info *denali)
|
|||
|
||||
int denali_init(struct denali_nand_info *denali)
|
||||
{
|
||||
struct mtd_info *mtd = nand_to_mtd(&denali->nand);
|
||||
int ret;
|
||||
|
||||
if (denali->platform == INTEL_CE4100) {
|
||||
|
@ -1447,7 +1453,7 @@ int denali_init(struct denali_nand_info *denali)
|
|||
if (!denali->buf.buf)
|
||||
return -ENOMEM;
|
||||
|
||||
denali->mtd.dev.parent = denali->dev;
|
||||
mtd->dev.parent = denali->dev;
|
||||
denali_hw_init(denali);
|
||||
denali_drv_init(denali);
|
||||
|
||||
|
@ -1463,8 +1469,7 @@ int denali_init(struct denali_nand_info *denali)
|
|||
|
||||
/* now that our ISR is registered, we can enable interrupts */
|
||||
denali_set_intr_modes(denali, true);
|
||||
denali->mtd.name = "denali-nand";
|
||||
denali->mtd.priv = &denali->nand;
|
||||
mtd->name = "denali-nand";
|
||||
|
||||
/* register the driver with the NAND core subsystem */
|
||||
denali->nand.select_chip = denali_select_chip;
|
||||
|
@ -1477,7 +1482,7 @@ int denali_init(struct denali_nand_info *denali)
|
|||
* this is the first stage in a two step process to register
|
||||
* with the nand subsystem
|
||||
*/
|
||||
if (nand_scan_ident(&denali->mtd, denali->max_banks, NULL)) {
|
||||
if (nand_scan_ident(mtd, denali->max_banks, NULL)) {
|
||||
ret = -ENXIO;
|
||||
goto failed_req_irq;
|
||||
}
|
||||
|
@ -1485,7 +1490,7 @@ int denali_init(struct denali_nand_info *denali)
|
|||
/* allocate the right size buffer now */
|
||||
devm_kfree(denali->dev, denali->buf.buf);
|
||||
denali->buf.buf = devm_kzalloc(denali->dev,
|
||||
denali->mtd.writesize + denali->mtd.oobsize,
|
||||
mtd->writesize + mtd->oobsize,
|
||||
GFP_KERNEL);
|
||||
if (!denali->buf.buf) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -1500,7 +1505,7 @@ int denali_init(struct denali_nand_info *denali)
|
|||
}
|
||||
|
||||
denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
|
||||
denali->mtd.writesize + denali->mtd.oobsize,
|
||||
mtd->writesize + mtd->oobsize,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
|
||||
dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
|
||||
|
@ -1521,10 +1526,10 @@ int denali_init(struct denali_nand_info *denali)
|
|||
denali->nand.bbt_erase_shift += (denali->devnum - 1);
|
||||
denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift;
|
||||
denali->nand.chip_shift += (denali->devnum - 1);
|
||||
denali->mtd.writesize <<= (denali->devnum - 1);
|
||||
denali->mtd.oobsize <<= (denali->devnum - 1);
|
||||
denali->mtd.erasesize <<= (denali->devnum - 1);
|
||||
denali->mtd.size = denali->nand.numchips * denali->nand.chipsize;
|
||||
mtd->writesize <<= (denali->devnum - 1);
|
||||
mtd->oobsize <<= (denali->devnum - 1);
|
||||
mtd->erasesize <<= (denali->devnum - 1);
|
||||
mtd->size = denali->nand.numchips * denali->nand.chipsize;
|
||||
denali->bbtskipbytes *= denali->devnum;
|
||||
|
||||
/*
|
||||
|
@ -1551,16 +1556,16 @@ int denali_init(struct denali_nand_info *denali)
|
|||
* SLC if possible.
|
||||
* */
|
||||
if (!nand_is_slc(&denali->nand) &&
|
||||
(denali->mtd.oobsize > (denali->bbtskipbytes +
|
||||
ECC_15BITS * (denali->mtd.writesize /
|
||||
(mtd->oobsize > (denali->bbtskipbytes +
|
||||
ECC_15BITS * (mtd->writesize /
|
||||
ECC_SECTOR_SIZE)))) {
|
||||
/* if MLC OOB size is large enough, use 15bit ECC*/
|
||||
denali->nand.ecc.strength = 15;
|
||||
denali->nand.ecc.layout = &nand_15bit_oob;
|
||||
denali->nand.ecc.bytes = ECC_15BITS;
|
||||
iowrite32(15, denali->flash_reg + ECC_CORRECTION);
|
||||
} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
|
||||
ECC_8BITS * (denali->mtd.writesize /
|
||||
} else if (mtd->oobsize < (denali->bbtskipbytes +
|
||||
ECC_8BITS * (mtd->writesize /
|
||||
ECC_SECTOR_SIZE))) {
|
||||
pr_err("Your NAND chip OOB is not large enough to contain 8bit ECC correction codes");
|
||||
goto failed_req_irq;
|
||||
|
@ -1574,11 +1579,11 @@ int denali_init(struct denali_nand_info *denali)
|
|||
denali->nand.ecc.bytes *= denali->devnum;
|
||||
denali->nand.ecc.strength *= denali->devnum;
|
||||
denali->nand.ecc.layout->eccbytes *=
|
||||
denali->mtd.writesize / ECC_SECTOR_SIZE;
|
||||
mtd->writesize / ECC_SECTOR_SIZE;
|
||||
denali->nand.ecc.layout->oobfree[0].offset =
|
||||
denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes;
|
||||
denali->nand.ecc.layout->oobfree[0].length =
|
||||
denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes -
|
||||
mtd->oobsize - denali->nand.ecc.layout->eccbytes -
|
||||
denali->bbtskipbytes;
|
||||
|
||||
/*
|
||||
|
@ -1586,7 +1591,7 @@ int denali_init(struct denali_nand_info *denali)
|
|||
* contained by each nand chip. blksperchip will help driver to
|
||||
* know how many blocks is taken by FW.
|
||||
*/
|
||||
denali->totalblks = denali->mtd.size >> denali->nand.phys_erase_shift;
|
||||
denali->totalblks = mtd->size >> denali->nand.phys_erase_shift;
|
||||
denali->blksperchip = denali->totalblks / denali->nand.numchips;
|
||||
|
||||
/* override the default read operations */
|
||||
|
@ -1599,12 +1604,12 @@ int denali_init(struct denali_nand_info *denali)
|
|||
denali->nand.ecc.write_oob = denali_write_oob;
|
||||
denali->nand.erase = denali_erase;
|
||||
|
||||
if (nand_scan_tail(&denali->mtd)) {
|
||||
if (nand_scan_tail(mtd)) {
|
||||
ret = -ENXIO;
|
||||
goto failed_req_irq;
|
||||
}
|
||||
|
||||
ret = mtd_device_register(&denali->mtd, NULL, 0);
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
|
||||
ret);
|
||||
|
@ -1622,9 +1627,17 @@ EXPORT_SYMBOL(denali_init);
|
|||
/* driver exit point */
|
||||
void denali_remove(struct denali_nand_info *denali)
|
||||
{
|
||||
struct mtd_info *mtd = nand_to_mtd(&denali->nand);
|
||||
/*
|
||||
* Pre-compute DMA buffer size to avoid any problems in case
|
||||
* nand_release() ever changes in a way that mtd->writesize and
|
||||
* mtd->oobsize are not reliable after this call.
|
||||
*/
|
||||
int bufsize = mtd->writesize + mtd->oobsize;
|
||||
|
||||
nand_release(mtd);
|
||||
denali_irq_cleanup(denali->irq, denali);
|
||||
dma_unmap_single(denali->dev, denali->buf.dma_buf,
|
||||
denali->mtd.writesize + denali->mtd.oobsize,
|
||||
dma_unmap_single(denali->dev, denali->buf.dma_buf, bufsize,
|
||||
DMA_BIDIRECTIONAL);
|
||||
}
|
||||
EXPORT_SYMBOL(denali_remove);
|
||||
|
|
|
@ -450,7 +450,6 @@ struct nand_buf {
|
|||
#define DT 3
|
||||
|
||||
struct denali_nand_info {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip nand;
|
||||
int flash_bank; /* currently selected chip */
|
||||
int status;
|
||||
|
|
|
@ -74,10 +74,6 @@ struct doc_priv {
|
|||
int (*late_init)(struct mtd_info *mtd);
|
||||
};
|
||||
|
||||
/* This is the syndrome computed by the HW ecc generator upon reading an empty
|
||||
page, one with all 0xff for data and stored ecc code. */
|
||||
static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
|
||||
|
||||
/* This is the ecc value computed by the HW ecc generator upon writing an empty
|
||||
page, one with all 0xff for data. */
|
||||
static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
|
||||
|
@ -299,8 +295,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc)
|
|||
|
||||
static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
if (debug)
|
||||
|
@ -311,8 +307,8 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
|
|||
|
||||
static u_char doc2000_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
u_char ret;
|
||||
|
||||
|
@ -326,8 +322,8 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
if (debug)
|
||||
|
@ -343,8 +339,8 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
|
||||
static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
|
||||
|
@ -358,8 +354,8 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
|
||||
|
@ -379,8 +375,8 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
uint16_t ret;
|
||||
|
||||
doc200x_select_chip(mtd, nr);
|
||||
|
@ -425,8 +421,8 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
|
|||
|
||||
static void __init doc2000_count_chips(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
uint16_t mfrid;
|
||||
int i;
|
||||
|
||||
|
@ -447,7 +443,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd)
|
|||
|
||||
static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
|
||||
{
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
|
||||
int status;
|
||||
|
||||
|
@ -461,8 +457,8 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
|
|||
|
||||
static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
WriteDOC(datum, docptr, CDSNSlowIO);
|
||||
|
@ -472,8 +468,8 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
|
|||
|
||||
static u_char doc2001_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
//ReadDOC(docptr, CDSNSlowIO);
|
||||
|
@ -486,8 +482,8 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
|
||||
|
@ -499,8 +495,8 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
|
||||
static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
|
||||
|
@ -516,8 +512,8 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static u_char doc2001plus_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
u_char ret;
|
||||
|
||||
|
@ -531,8 +527,8 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
|
||||
|
@ -549,8 +545,8 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le
|
|||
|
||||
static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
|
||||
|
@ -580,8 +576,8 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int floor = 0;
|
||||
|
||||
|
@ -607,8 +603,8 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
|
|||
|
||||
static void doc200x_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int floor = 0;
|
||||
|
||||
|
@ -638,8 +634,8 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
|
|||
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
|
@ -661,8 +657,8 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
|
|||
|
||||
static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
/*
|
||||
|
@ -767,8 +763,8 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
|
|||
|
||||
static int doc200x_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
if (DoC_is_MillenniumPlus(doc)) {
|
||||
|
@ -807,8 +803,8 @@ static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|||
|
||||
static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
/* Prime the ECC engine */
|
||||
|
@ -826,8 +822,8 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
|
||||
static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
/* Prime the ECC engine */
|
||||
|
@ -846,8 +842,8 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
/* This code is only called on write */
|
||||
static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i;
|
||||
int emptymatch = 1;
|
||||
|
@ -907,12 +903,11 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
|
|||
u_char *read_ecc, u_char *isnull)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
uint8_t calc_ecc[6];
|
||||
volatile u_char dummy;
|
||||
int emptymatch = 1;
|
||||
|
||||
/* flush the pipeline */
|
||||
if (DoC_is_2000(doc)) {
|
||||
|
@ -936,36 +931,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
|
|||
calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
|
||||
else
|
||||
calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
|
||||
if (calc_ecc[i] != empty_read_syndrome[i])
|
||||
emptymatch = 0;
|
||||
}
|
||||
/* If emptymatch=1, the read syndrome is consistent with an
|
||||
all-0xff data and stored ecc block. Check the stored ecc. */
|
||||
if (emptymatch) {
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (read_ecc[i] == 0xff)
|
||||
continue;
|
||||
emptymatch = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If emptymatch still =1, check the data block. */
|
||||
if (emptymatch) {
|
||||
/* Note: this somewhat expensive test should not be triggered
|
||||
often. It could be optimized away by examining the data in
|
||||
the readbuf routine, and remembering the result. */
|
||||
for (i = 0; i < 512; i++) {
|
||||
if (dat[i] == 0xff)
|
||||
continue;
|
||||
emptymatch = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If emptymatch still =1, this is almost certainly a freshly-
|
||||
erased block, in which case the ECC will not come out right.
|
||||
We'll suppress the error and tell the caller everything's
|
||||
OK. Because it is. */
|
||||
if (!emptymatch)
|
||||
|
||||
ret = doc_ecc_decode(rs_decoder, dat, calc_ecc);
|
||||
if (ret > 0)
|
||||
printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
|
||||
|
@ -1007,8 +974,8 @@ static struct nand_ecclayout doc200x_oobinfo = {
|
|||
mh1_page in the DOC private structure. */
|
||||
static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
unsigned offs;
|
||||
int ret;
|
||||
size_t retlen;
|
||||
|
@ -1050,8 +1017,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
|
|||
|
||||
static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
int ret = 0;
|
||||
u_char *buf;
|
||||
struct NFTLMediaHeader *mh;
|
||||
|
@ -1152,8 +1119,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
|
|||
/* This is a stripped-down copy of the code in inftlmount.c */
|
||||
static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
int ret = 0;
|
||||
u_char *buf;
|
||||
struct INFTLMediaHeader *mh;
|
||||
|
@ -1272,8 +1239,8 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
|
|||
static int __init nftl_scan_bbt(struct mtd_info *mtd)
|
||||
{
|
||||
int ret, numparts;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
struct mtd_partition parts[2];
|
||||
|
||||
memset((char *)parts, 0, sizeof(parts));
|
||||
|
@ -1307,8 +1274,8 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd)
|
|||
static int __init inftl_scan_bbt(struct mtd_info *mtd)
|
||||
{
|
||||
int ret, numparts;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
struct mtd_partition parts[5];
|
||||
|
||||
if (this->numchips > doc->chips_per_floor) {
|
||||
|
@ -1360,8 +1327,8 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
|
|||
|
||||
static inline int __init doc2000_init(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
|
||||
this->read_byte = doc2000_read_byte;
|
||||
this->write_buf = doc2000_writebuf;
|
||||
|
@ -1376,8 +1343,8 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
|
|||
|
||||
static inline int __init doc2001_init(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
|
||||
this->read_byte = doc2001_read_byte;
|
||||
this->write_buf = doc2001_writebuf;
|
||||
|
@ -1406,8 +1373,8 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
|
|||
|
||||
static inline int __init doc2001plus_init(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct doc_priv *doc = nand_get_controller_data(this);
|
||||
|
||||
this->read_byte = doc2001plus_read_byte;
|
||||
this->write_buf = doc2001plus_writebuf;
|
||||
|
@ -1523,8 +1490,8 @@ static int __init doc_probe(unsigned long physadr)
|
|||
for (mtd = doclist; mtd; mtd = doc->nextdoc) {
|
||||
unsigned char oldval;
|
||||
unsigned char newval;
|
||||
nand = mtd->priv;
|
||||
doc = nand->priv;
|
||||
nand = mtd_to_nand(mtd);
|
||||
doc = nand_get_controller_data(nand);
|
||||
/* Use the alias resolution register to determine if this is
|
||||
in fact the same DOC aliased to a new address. If writes
|
||||
to one chip's alias resolution register change the value on
|
||||
|
@ -1556,23 +1523,22 @@ static int __init doc_probe(unsigned long physadr)
|
|||
|
||||
printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr);
|
||||
|
||||
len = sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
|
||||
mtd = kzalloc(len, GFP_KERNEL);
|
||||
if (!mtd) {
|
||||
len = sizeof(struct nand_chip) + sizeof(struct doc_priv) +
|
||||
(2 * sizeof(struct nand_bbt_descr));
|
||||
nand = kzalloc(len, GFP_KERNEL);
|
||||
if (!nand) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nand = (struct nand_chip *) (mtd + 1);
|
||||
mtd = nand_to_mtd(nand);
|
||||
doc = (struct doc_priv *) (nand + 1);
|
||||
nand->bbt_td = (struct nand_bbt_descr *) (doc + 1);
|
||||
nand->bbt_md = nand->bbt_td + 1;
|
||||
|
||||
mtd->priv = nand;
|
||||
mtd->owner = THIS_MODULE;
|
||||
|
||||
nand->priv = doc;
|
||||
nand_set_controller_data(nand, doc);
|
||||
nand->select_chip = doc200x_select_chip;
|
||||
nand->cmd_ctrl = doc200x_hwcontrol;
|
||||
nand->dev_ready = doc200x_dev_ready;
|
||||
|
@ -1587,6 +1553,7 @@ static int __init doc_probe(unsigned long physadr)
|
|||
nand->ecc.size = 512;
|
||||
nand->ecc.bytes = 6;
|
||||
nand->ecc.strength = 2;
|
||||
nand->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
|
||||
nand->bbt_options = NAND_BBT_USE_FLASH;
|
||||
/* Skip the automatic BBT scan so we can run it manually */
|
||||
nand->options |= NAND_SKIP_BBTSCAN;
|
||||
|
@ -1615,7 +1582,7 @@ static int __init doc_probe(unsigned long physadr)
|
|||
haven't yet added it. This is handled without incident by
|
||||
mtd_device_unregister, as far as I can tell. */
|
||||
nand_release(mtd);
|
||||
kfree(mtd);
|
||||
kfree(nand);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1643,14 +1610,14 @@ static void release_nanddoc(void)
|
|||
struct doc_priv *doc;
|
||||
|
||||
for (mtd = doclist; mtd; mtd = nextmtd) {
|
||||
nand = mtd->priv;
|
||||
doc = nand->priv;
|
||||
nand = mtd_to_nand(mtd);
|
||||
doc = nand_get_controller_data(nand);
|
||||
|
||||
nextmtd = doc->nextdoc;
|
||||
nand_release(mtd);
|
||||
iounmap(doc->virtadr);
|
||||
release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
|
||||
kfree(mtd);
|
||||
kfree(nand);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ static inline void write_nop(void __iomem *docptr)
|
|||
static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
uint16_t *p = (uint16_t *) buf;
|
||||
len >>= 1;
|
||||
|
||||
|
@ -253,7 +253,7 @@ static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
uint16_t *p = (uint16_t *) buf;
|
||||
len >>= 1;
|
||||
|
||||
|
@ -297,7 +297,7 @@ static int poll_status(struct docg4_priv *doc)
|
|||
static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand)
|
||||
{
|
||||
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
int status = NAND_STATUS_WP; /* inverse logic?? */
|
||||
dev_dbg(doc->dev, "%s...\n", __func__);
|
||||
|
||||
|
@ -318,8 +318,8 @@ static void docg4_select_chip(struct mtd_info *mtd, int chip)
|
|||
* Select among multiple cascaded chips ("floors"). Multiple floors are
|
||||
* not yet supported, so the only valid non-negative value is 0.
|
||||
*/
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
dev_dbg(doc->dev, "%s: chip %d\n", __func__, chip);
|
||||
|
@ -337,8 +337,8 @@ static void reset(struct mtd_info *mtd)
|
|||
{
|
||||
/* full device reset */
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN,
|
||||
|
@ -375,8 +375,8 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
|
|||
* Up to four bitflips can be corrected.
|
||||
*/
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int i, numerrs, errpos[4];
|
||||
const uint8_t blank_read_hwecc[8] = {
|
||||
|
@ -464,8 +464,8 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
|
|||
|
||||
static uint8_t docg4_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
|
||||
dev_dbg(doc->dev, "%s\n", __func__);
|
||||
|
||||
|
@ -545,8 +545,8 @@ static int pageprog(struct mtd_info *mtd)
|
|||
* internal buffer out to the flash array, or some such.
|
||||
*/
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
int retval = 0;
|
||||
|
||||
|
@ -582,8 +582,8 @@ static void sequence_reset(struct mtd_info *mtd)
|
|||
{
|
||||
/* common starting sequence for all operations */
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL);
|
||||
|
@ -599,8 +599,8 @@ static void read_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr)
|
|||
{
|
||||
/* first step in reading a page */
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
dev_dbg(doc->dev,
|
||||
|
@ -626,8 +626,8 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr)
|
|||
{
|
||||
/* first step in writing a page */
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
dev_dbg(doc->dev,
|
||||
|
@ -691,8 +691,8 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
|
|||
{
|
||||
/* handle standard nand commands */
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
|
||||
|
||||
dev_dbg(doc->dev, "%s %x, page_addr=%x, column=%x\n",
|
||||
|
@ -756,7 +756,7 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
|
|||
static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
|
||||
uint8_t *buf, int page, bool use_ecc)
|
||||
{
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
uint16_t status, edc_err, *buf16;
|
||||
int bits_corrected = 0;
|
||||
|
@ -836,7 +836,7 @@ static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
|
|||
static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
|
||||
int page)
|
||||
{
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
uint16_t status;
|
||||
|
||||
|
@ -874,8 +874,8 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
|
|||
|
||||
static int docg4_erase_block(struct mtd_info *mtd, int page)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
uint16_t g4_page;
|
||||
|
||||
|
@ -923,7 +923,7 @@ static int docg4_erase_block(struct mtd_info *mtd, int page)
|
|||
static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
|
||||
const uint8_t *buf, bool use_ecc)
|
||||
{
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
uint8_t ecc_buf[8];
|
||||
|
||||
|
@ -1003,7 +1003,7 @@ static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
|
|||
*/
|
||||
|
||||
/* note that bytes 7..14 are hw generated hamming/ecc and overwritten */
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
doc->oob_page = page;
|
||||
memcpy(doc->oob_buf, nand->oob_poi, 16);
|
||||
return 0;
|
||||
|
@ -1016,8 +1016,8 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
|
|||
* update the memory-based bbt accordingly.
|
||||
*/
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
|
||||
uint8_t *buf;
|
||||
int i, block;
|
||||
|
@ -1089,8 +1089,8 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|||
|
||||
int ret, i;
|
||||
uint8_t *buf;
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
struct nand_bbt_descr *bbtd = nand->badblock_pattern;
|
||||
int page = (int)(ofs >> nand->page_shift);
|
||||
uint32_t g4_addr = mtd_to_docg4_address(page, 0);
|
||||
|
@ -1202,8 +1202,8 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
|
|||
* things as well, such as call nand_set_defaults().
|
||||
*/
|
||||
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
|
||||
mtd->size = DOCG4_CHIP_SIZE;
|
||||
mtd->name = "Msys_Diskonchip_G4";
|
||||
|
@ -1261,8 +1261,8 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
|
|||
|
||||
static int __init read_id_reg(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct docg4_priv *doc = nand_get_controller_data(nand);
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
uint16_t id1, id2;
|
||||
|
||||
|
@ -1305,17 +1305,16 @@ static int __init probe_docg4(struct platform_device *pdev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
len = sizeof(struct mtd_info) + sizeof(struct nand_chip) +
|
||||
sizeof(struct docg4_priv);
|
||||
mtd = kzalloc(len, GFP_KERNEL);
|
||||
if (mtd == NULL) {
|
||||
len = sizeof(struct nand_chip) + sizeof(struct docg4_priv);
|
||||
nand = kzalloc(len, GFP_KERNEL);
|
||||
if (nand == NULL) {
|
||||
retval = -ENOMEM;
|
||||
goto fail;
|
||||
goto fail_unmap;
|
||||
}
|
||||
nand = (struct nand_chip *) (mtd + 1);
|
||||
|
||||
mtd = nand_to_mtd(nand);
|
||||
doc = (struct docg4_priv *) (nand + 1);
|
||||
mtd->priv = nand;
|
||||
nand->priv = doc;
|
||||
nand_set_controller_data(nand, doc);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
doc->virtadr = virtadr;
|
||||
doc->dev = dev;
|
||||
|
@ -1354,15 +1353,12 @@ static int __init probe_docg4(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
iounmap(virtadr);
|
||||
if (mtd) {
|
||||
/* re-declarations avoid compiler warning */
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct docg4_priv *doc = nand->priv;
|
||||
nand_release(mtd); /* deletes partitions and mtd devices */
|
||||
free_bch(doc->bch);
|
||||
kfree(mtd);
|
||||
}
|
||||
kfree(nand);
|
||||
|
||||
fail_unmap:
|
||||
iounmap(virtadr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1372,7 +1368,7 @@ static int __exit cleanup_docg4(struct platform_device *pdev)
|
|||
struct docg4_priv *doc = platform_get_drvdata(pdev);
|
||||
nand_release(doc->mtd);
|
||||
free_bch(doc->bch);
|
||||
kfree(doc->mtd);
|
||||
kfree(mtd_to_nand(doc->mtd));
|
||||
iounmap(doc->virtadr);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
/* mtd information per set */
|
||||
|
||||
struct fsl_elbc_mtd {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
struct fsl_lbc_ctrl *ctrl;
|
||||
|
||||
|
@ -144,8 +143,8 @@ static struct nand_bbt_descr bbt_mirror_descr = {
|
|||
*/
|
||||
static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
|
||||
|
@ -195,8 +194,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
|
|||
*/
|
||||
static int fsl_elbc_run_command(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
|
@ -268,7 +267,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
|
|||
|
||||
static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
|
||||
{
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
|
||||
|
@ -300,8 +299,8 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
|
|||
static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
|
@ -525,8 +524,8 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
|
|||
*/
|
||||
static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
|
||||
unsigned int bufsize = mtd->writesize + mtd->oobsize;
|
||||
|
||||
|
@ -563,8 +562,8 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
|
|||
*/
|
||||
static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
|
||||
|
||||
/* If there are still bytes in the FCM, then use the next byte. */
|
||||
|
@ -580,8 +579,8 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
|
|||
*/
|
||||
static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
|
||||
int avail;
|
||||
|
||||
|
@ -605,7 +604,7 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
|||
*/
|
||||
static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||
{
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
|
||||
|
||||
if (elbc_fcm_ctrl->status != LTESR_CC)
|
||||
|
@ -619,8 +618,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|||
|
||||
static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
unsigned int al;
|
||||
|
@ -697,7 +696,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
|
|||
static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct fsl_elbc_mtd *priv = chip->priv;
|
||||
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
|
||||
|
||||
|
@ -742,12 +741,13 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
|
|||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
|
||||
struct nand_chip *chip = &priv->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
|
||||
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
|
||||
|
||||
/* Fill in fsl_elbc_mtd structure */
|
||||
priv->mtd.priv = chip;
|
||||
priv->mtd.dev.parent = priv->dev;
|
||||
mtd->dev.parent = priv->dev;
|
||||
nand_set_flash_node(chip, priv->dev->of_node);
|
||||
|
||||
/* set timeout to maximum */
|
||||
priv->fmr = 15 << FMR_CWTO_SHIFT;
|
||||
|
@ -770,7 +770,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
|
|||
chip->bbt_options = NAND_BBT_USE_FLASH;
|
||||
|
||||
chip->controller = &elbc_fcm_ctrl->controller;
|
||||
chip->priv = priv;
|
||||
nand_set_controller_data(chip, priv);
|
||||
|
||||
chip->ecc.read_page = fsl_elbc_read_page;
|
||||
chip->ecc.write_page = fsl_elbc_write_page;
|
||||
|
@ -797,9 +797,11 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
|
|||
static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
|
||||
{
|
||||
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
|
||||
nand_release(&priv->mtd);
|
||||
struct mtd_info *mtd = nand_to_mtd(&priv->chip);
|
||||
|
||||
kfree(priv->mtd.name);
|
||||
nand_release(mtd);
|
||||
|
||||
kfree(mtd->name);
|
||||
|
||||
if (priv->vbase)
|
||||
iounmap(priv->vbase);
|
||||
|
@ -823,9 +825,8 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
|
|||
int bank;
|
||||
struct device *dev;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct mtd_info *mtd;
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
lbc = fsl_lbc_ctrl_dev->regs;
|
||||
|
@ -887,8 +888,9 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
|
||||
if (!priv->mtd.name) {
|
||||
mtd = nand_to_mtd(&priv->chip);
|
||||
mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
|
||||
if (!nand_to_mtd(&priv->chip)->name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
@ -897,21 +899,21 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nand_scan_ident(&priv->mtd, 1, NULL);
|
||||
ret = nand_scan_ident(mtd, 1, NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = fsl_elbc_chip_init_tail(&priv->mtd);
|
||||
ret = fsl_elbc_chip_init_tail(mtd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nand_scan_tail(&priv->mtd);
|
||||
ret = nand_scan_tail(mtd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* First look for RedBoot table or partitions on the command
|
||||
* line, these take precedence over device tree information */
|
||||
mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
|
||||
mtd_device_parse_register(mtd, part_probe_types, NULL,
|
||||
NULL, 0);
|
||||
|
||||
printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
|
||||
|
|
|
@ -40,7 +40,6 @@ struct fsl_ifc_ctrl;
|
|||
|
||||
/* mtd information per set */
|
||||
struct fsl_ifc_mtd {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
struct fsl_ifc_ctrl *ctrl;
|
||||
|
||||
|
@ -230,8 +229,8 @@ static struct nand_bbt_descr bbt_mirror_descr = {
|
|||
*/
|
||||
static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
|
||||
int buf_num;
|
||||
|
@ -253,8 +252,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
|
|||
|
||||
static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
|
||||
u32 __iomem *mainarea = (u32 __iomem *)addr;
|
||||
u8 __iomem *oob = addr + mtd->writesize;
|
||||
|
@ -292,8 +291,8 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
|
|||
*/
|
||||
static void fsl_ifc_run_command(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
|
||||
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
|
||||
|
@ -370,7 +369,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
|
|||
int oob,
|
||||
struct mtd_info *mtd)
|
||||
{
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
|
||||
|
||||
|
@ -409,8 +408,8 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
|
|||
/* cmdfunc send commands to the IFC NAND Machine */
|
||||
static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr) {
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
|
||||
|
||||
|
@ -624,8 +623,8 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
|
|||
*/
|
||||
static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
unsigned int bufsize = mtd->writesize + mtd->oobsize;
|
||||
|
||||
if (len <= 0) {
|
||||
|
@ -650,8 +649,8 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
|
|||
*/
|
||||
static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
unsigned int offset;
|
||||
|
||||
/*
|
||||
|
@ -673,8 +672,8 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
|
|||
*/
|
||||
static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
uint16_t data;
|
||||
|
||||
/*
|
||||
|
@ -696,8 +695,8 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
|
|||
*/
|
||||
static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
int avail;
|
||||
|
||||
if (len < 0) {
|
||||
|
@ -722,7 +721,7 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
|||
*/
|
||||
static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||
{
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
|
||||
u32 nand_fsr;
|
||||
|
@ -751,7 +750,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|||
static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
|
||||
|
||||
|
@ -782,8 +781,8 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
|
||||
static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
|
||||
|
||||
dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
|
||||
chip->numchips);
|
||||
|
@ -877,12 +876,13 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
|
|||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
|
||||
struct nand_chip *chip = &priv->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(&priv->chip);
|
||||
struct nand_ecclayout *layout;
|
||||
u32 csor;
|
||||
|
||||
/* Fill in fsl_ifc_mtd structure */
|
||||
priv->mtd.priv = chip;
|
||||
priv->mtd.dev.parent = priv->dev;
|
||||
mtd->dev.parent = priv->dev;
|
||||
nand_set_flash_node(chip, priv->dev->of_node);
|
||||
|
||||
/* fill in nand_chip structure */
|
||||
/* set up function call table */
|
||||
|
@ -914,7 +914,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
|
|||
}
|
||||
|
||||
chip->controller = &ifc_nand_ctrl->controller;
|
||||
chip->priv = priv;
|
||||
nand_set_controller_data(chip, priv);
|
||||
|
||||
chip->ecc.read_page = fsl_ifc_read_page;
|
||||
chip->ecc.write_page = fsl_ifc_write_page;
|
||||
|
@ -993,9 +993,11 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
|
|||
|
||||
static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
|
||||
{
|
||||
nand_release(&priv->mtd);
|
||||
struct mtd_info *mtd = nand_to_mtd(&priv->chip);
|
||||
|
||||
kfree(priv->mtd.name);
|
||||
nand_release(mtd);
|
||||
|
||||
kfree(mtd->name);
|
||||
|
||||
if (priv->vbase)
|
||||
iounmap(priv->vbase);
|
||||
|
@ -1030,9 +1032,8 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
|
|||
int ret;
|
||||
int bank;
|
||||
struct device_node *node = dev->dev.of_node;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct mtd_info *mtd;
|
||||
|
||||
ppdata.of_node = dev->dev.of_node;
|
||||
if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
ifc = fsl_ifc_ctrl_dev->regs;
|
||||
|
@ -1104,8 +1105,10 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
|
|||
IFC_NAND_EVTER_INTR_FTOERIR_EN |
|
||||
IFC_NAND_EVTER_INTR_WPERIR_EN,
|
||||
&ifc->ifc_nand.nand_evter_intr_en);
|
||||
priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
|
||||
if (!priv->mtd.name) {
|
||||
|
||||
mtd = nand_to_mtd(&priv->chip);
|
||||
mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
|
||||
if (!mtd->name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
@ -1114,22 +1117,21 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nand_scan_ident(&priv->mtd, 1, NULL);
|
||||
ret = nand_scan_ident(mtd, 1, NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = fsl_ifc_chip_init_tail(&priv->mtd);
|
||||
ret = fsl_ifc_chip_init_tail(mtd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nand_scan_tail(&priv->mtd);
|
||||
ret = nand_scan_tail(mtd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* First look for RedBoot table or partitions on the command
|
||||
* line, these take precedence over device tree information */
|
||||
mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
|
||||
NULL, 0);
|
||||
mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0);
|
||||
|
||||
dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n",
|
||||
(unsigned long long)res.start, priv->bank);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
struct fsl_upm_nand {
|
||||
struct device *dev;
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
int last_ctrl;
|
||||
struct mtd_partition *parts;
|
||||
|
@ -49,7 +48,8 @@ struct fsl_upm_nand {
|
|||
|
||||
static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo)
|
||||
{
|
||||
return container_of(mtdinfo, struct fsl_upm_nand, mtd);
|
||||
return container_of(mtd_to_nand(mtdinfo), struct fsl_upm_nand,
|
||||
chip);
|
||||
}
|
||||
|
||||
static int fun_chip_ready(struct mtd_info *mtd)
|
||||
|
@ -66,9 +66,10 @@ static int fun_chip_ready(struct mtd_info *mtd)
|
|||
static void fun_wait_rnb(struct fsl_upm_nand *fun)
|
||||
{
|
||||
if (fun->rnb_gpio[fun->mchip_number] >= 0) {
|
||||
struct mtd_info *mtd = nand_to_mtd(&fun->chip);
|
||||
int cnt = 1000000;
|
||||
|
||||
while (--cnt && !fun_chip_ready(&fun->mtd))
|
||||
while (--cnt && !fun_chip_ready(mtd))
|
||||
cpu_relax();
|
||||
if (!cnt)
|
||||
dev_err(fun->dev, "tired waiting for RNB\n");
|
||||
|
@ -79,7 +80,7 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
|
|||
|
||||
static void fun_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);
|
||||
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
|
||||
u32 mar;
|
||||
|
||||
|
@ -109,7 +110,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
|||
|
||||
static void fun_select_chip(struct mtd_info *mtd, int mchip_nr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
|
||||
|
||||
if (mchip_nr == -1) {
|
||||
|
@ -157,9 +158,9 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
|
|||
const struct device_node *upm_np,
|
||||
const struct resource *io_res)
|
||||
{
|
||||
struct mtd_info *mtd = nand_to_mtd(&fun->chip);
|
||||
int ret;
|
||||
struct device_node *flash_np;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
|
||||
fun->chip.IO_ADDR_R = fun->io_base;
|
||||
fun->chip.IO_ADDR_W = fun->io_base;
|
||||
|
@ -175,30 +176,29 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
|
|||
if (fun->rnb_gpio[0] >= 0)
|
||||
fun->chip.dev_ready = fun_chip_ready;
|
||||
|
||||
fun->mtd.priv = &fun->chip;
|
||||
fun->mtd.dev.parent = fun->dev;
|
||||
mtd->dev.parent = fun->dev;
|
||||
|
||||
flash_np = of_get_next_child(upm_np, NULL);
|
||||
if (!flash_np)
|
||||
return -ENODEV;
|
||||
|
||||
fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start,
|
||||
nand_set_flash_node(&fun->chip, flash_np);
|
||||
mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start,
|
||||
flash_np->name);
|
||||
if (!fun->mtd.name) {
|
||||
if (!mtd->name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = nand_scan(&fun->mtd, fun->mchip_count);
|
||||
ret = nand_scan(mtd, fun->mchip_count);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ppdata.of_node = flash_np;
|
||||
ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
err:
|
||||
of_node_put(flash_np);
|
||||
if (ret)
|
||||
kfree(fun->mtd.name);
|
||||
kfree(mtd->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -322,10 +322,11 @@ static int fun_probe(struct platform_device *ofdev)
|
|||
static int fun_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
|
||||
struct mtd_info *mtd = nand_to_mtd(&fun->chip);
|
||||
int i;
|
||||
|
||||
nand_release(&fun->mtd);
|
||||
kfree(fun->mtd.name);
|
||||
nand_release(mtd);
|
||||
kfree(mtd->name);
|
||||
|
||||
for (i = 0; i < fun->mchip_count; i++) {
|
||||
if (fun->rnb_gpio[i] < 0)
|
||||
|
|
|
@ -299,7 +299,6 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
|
|||
*/
|
||||
struct fsmc_nand_data {
|
||||
u32 pid;
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip nand;
|
||||
struct mtd_partition *partitions;
|
||||
unsigned int nr_partitions;
|
||||
|
@ -326,13 +325,18 @@ struct fsmc_nand_data {
|
|||
void (*select_chip)(uint32_t bank, uint32_t busw);
|
||||
};
|
||||
|
||||
static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand);
|
||||
}
|
||||
|
||||
/* Assert CS signal based on chipnr */
|
||||
static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsmc_nand_data *host;
|
||||
|
||||
host = container_of(mtd, struct fsmc_nand_data, mtd);
|
||||
host = mtd_to_fsmc(mtd);
|
||||
|
||||
switch (chipnr) {
|
||||
case -1:
|
||||
|
@ -358,9 +362,8 @@ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
|
|||
*/
|
||||
static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct fsmc_nand_data *host = container_of(mtd,
|
||||
struct fsmc_nand_data, mtd);
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
void __iomem *regs = host->regs_va;
|
||||
unsigned int bank = host->bank;
|
||||
|
||||
|
@ -445,8 +448,7 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
|
|||
*/
|
||||
static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct fsmc_nand_data *host = container_of(mtd,
|
||||
struct fsmc_nand_data, mtd);
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
void __iomem *regs = host->regs_va;
|
||||
uint32_t bank = host->bank;
|
||||
|
||||
|
@ -466,8 +468,7 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
|
||||
uint8_t *ecc)
|
||||
{
|
||||
struct fsmc_nand_data *host = container_of(mtd,
|
||||
struct fsmc_nand_data, mtd);
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
void __iomem *regs = host->regs_va;
|
||||
uint32_t bank = host->bank;
|
||||
uint32_t ecc_tmp;
|
||||
|
@ -517,8 +518,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
|
|||
static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
|
||||
uint8_t *ecc)
|
||||
{
|
||||
struct fsmc_nand_data *host = container_of(mtd,
|
||||
struct fsmc_nand_data, mtd);
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
void __iomem *regs = host->regs_va;
|
||||
uint32_t bank = host->bank;
|
||||
uint32_t ecc_tmp;
|
||||
|
@ -629,7 +629,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
|
|||
static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
|
||||
IS_ALIGNED(len, sizeof(uint32_t))) {
|
||||
|
@ -652,7 +652,7 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||
static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
|
||||
IS_ALIGNED(len, sizeof(uint32_t))) {
|
||||
|
@ -674,9 +674,8 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
*/
|
||||
static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct fsmc_nand_data *host;
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
|
||||
host = container_of(mtd, struct fsmc_nand_data, mtd);
|
||||
dma_xfer(host, buf, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
|
@ -689,9 +688,8 @@ static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
|
||||
int len)
|
||||
{
|
||||
struct fsmc_nand_data *host;
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
|
||||
host = container_of(mtd, struct fsmc_nand_data, mtd);
|
||||
dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
|
@ -712,8 +710,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
|
|||
static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct fsmc_nand_data *host = container_of(mtd,
|
||||
struct fsmc_nand_data, mtd);
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
struct fsmc_eccplace *ecc_place = host->ecc_place;
|
||||
int i, j, s, stat, eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
|
@ -782,9 +779,8 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
|
||||
uint8_t *read_ecc, uint8_t *calc_ecc)
|
||||
{
|
||||
struct fsmc_nand_data *host = container_of(mtd,
|
||||
struct fsmc_nand_data, mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
|
||||
void __iomem *regs = host->regs_va;
|
||||
unsigned int bank = host->bank;
|
||||
uint32_t err_idx[8];
|
||||
|
@ -926,7 +922,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device_node __maybe_unused *np = pdev->dev.of_node;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
struct fsmc_nand_data *host;
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand;
|
||||
|
@ -1012,12 +1007,12 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
init_completion(&host->dma_access_complete);
|
||||
|
||||
/* Link all private pointers */
|
||||
mtd = &host->mtd;
|
||||
mtd = nand_to_mtd(&host->nand);
|
||||
nand = &host->nand;
|
||||
mtd->priv = nand;
|
||||
nand->priv = host;
|
||||
nand_set_controller_data(nand, host);
|
||||
nand_set_flash_node(nand, np);
|
||||
|
||||
host->mtd.dev.parent = &pdev->dev;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
nand->IO_ADDR_R = host->data_va;
|
||||
nand->IO_ADDR_W = host->data_va;
|
||||
nand->cmd_ctrl = fsmc_cmd_ctrl;
|
||||
|
@ -1033,7 +1028,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
nand->options = pdata->options;
|
||||
nand->select_chip = fsmc_select_chip;
|
||||
nand->badblockbits = 7;
|
||||
nand->flash_node = np;
|
||||
nand_set_flash_node(nand, np);
|
||||
|
||||
if (pdata->width == FSMC_NAND_BW16)
|
||||
nand->options |= NAND_BUSWIDTH_16;
|
||||
|
@ -1080,14 +1075,14 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
/*
|
||||
* Scan to find existence of the device
|
||||
*/
|
||||
if (nand_scan_ident(&host->mtd, 1, NULL)) {
|
||||
if (nand_scan_ident(mtd, 1, NULL)) {
|
||||
ret = -ENXIO;
|
||||
dev_err(&pdev->dev, "No NAND Device found!\n");
|
||||
goto err_scan_ident;
|
||||
}
|
||||
|
||||
if (AMBA_REV_BITS(host->pid) >= 8) {
|
||||
switch (host->mtd.oobsize) {
|
||||
switch (mtd->oobsize) {
|
||||
case 16:
|
||||
nand->ecc.layout = &fsmc_ecc4_16_layout;
|
||||
host->ecc_place = &fsmc_ecc4_sp_place;
|
||||
|
@ -1138,7 +1133,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
* generated later in nand_bch_init() later.
|
||||
*/
|
||||
if (nand->ecc.mode != NAND_ECC_SOFT_BCH) {
|
||||
switch (host->mtd.oobsize) {
|
||||
switch (mtd->oobsize) {
|
||||
case 16:
|
||||
nand->ecc.layout = &fsmc_ecc1_16_layout;
|
||||
break;
|
||||
|
@ -1159,7 +1154,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Second stage of scan to fill MTD data-structures */
|
||||
if (nand_scan_tail(&host->mtd)) {
|
||||
if (nand_scan_tail(mtd)) {
|
||||
ret = -ENXIO;
|
||||
goto err_probe;
|
||||
}
|
||||
|
@ -1174,10 +1169,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
/*
|
||||
* Check for partition info passed
|
||||
*/
|
||||
host->mtd.name = "nand";
|
||||
ppdata.of_node = np;
|
||||
ret = mtd_device_parse_register(&host->mtd, NULL, &ppdata,
|
||||
host->partitions, host->nr_partitions);
|
||||
mtd->name = "nand";
|
||||
ret = mtd_device_register(mtd, host->partitions, host->nr_partitions);
|
||||
if (ret)
|
||||
goto err_probe;
|
||||
|
||||
|
@ -1207,7 +1200,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
|
|||
struct fsmc_nand_data *host = platform_get_drvdata(pdev);
|
||||
|
||||
if (host) {
|
||||
nand_release(&host->mtd);
|
||||
nand_release(nand_to_mtd(&host->nand));
|
||||
|
||||
if (host->mode == USE_DMA_ACCESS) {
|
||||
dma_release_channel(host->write_dma_chan);
|
||||
|
|
|
@ -35,12 +35,14 @@
|
|||
|
||||
struct gpiomtd {
|
||||
void __iomem *io_sync;
|
||||
struct mtd_info mtd_info;
|
||||
struct nand_chip nand_chip;
|
||||
struct gpio_nand_platdata plat;
|
||||
};
|
||||
|
||||
#define gpio_nand_getpriv(x) container_of(x, struct gpiomtd, mtd_info)
|
||||
static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct gpiomtd, nand_chip);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
|
@ -195,7 +197,7 @@ static int gpio_nand_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
|
||||
|
||||
nand_release(&gpiomtd->mtd_info);
|
||||
nand_release(nand_to_mtd(&gpiomtd->nand_chip));
|
||||
|
||||
if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
|
||||
gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
|
||||
|
@ -208,8 +210,8 @@ static int gpio_nand_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct gpiomtd *gpiomtd;
|
||||
struct nand_chip *chip;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
int ret = 0;
|
||||
|
||||
if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev))
|
||||
|
@ -268,32 +270,30 @@ static int gpio_nand_probe(struct platform_device *pdev)
|
|||
chip->dev_ready = gpio_nand_devready;
|
||||
}
|
||||
|
||||
nand_set_flash_node(chip, pdev->dev.of_node);
|
||||
chip->IO_ADDR_W = chip->IO_ADDR_R;
|
||||
chip->ecc.mode = NAND_ECC_SOFT;
|
||||
chip->options = gpiomtd->plat.options;
|
||||
chip->chip_delay = gpiomtd->plat.chip_delay;
|
||||
chip->cmd_ctrl = gpio_nand_cmd_ctrl;
|
||||
|
||||
gpiomtd->mtd_info.priv = chip;
|
||||
gpiomtd->mtd_info.dev.parent = &pdev->dev;
|
||||
mtd = nand_to_mtd(chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, gpiomtd);
|
||||
|
||||
if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
|
||||
gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
|
||||
|
||||
if (nand_scan(&gpiomtd->mtd_info, 1)) {
|
||||
if (nand_scan(mtd, 1)) {
|
||||
ret = -ENXIO;
|
||||
goto err_wp;
|
||||
}
|
||||
|
||||
if (gpiomtd->plat.adjust_parts)
|
||||
gpiomtd->plat.adjust_parts(&gpiomtd->plat,
|
||||
gpiomtd->mtd_info.size);
|
||||
gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size);
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata,
|
||||
gpiomtd->plat.parts,
|
||||
ret = mtd_device_register(mtd, gpiomtd->plat.parts,
|
||||
gpiomtd->plat.num_parts);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
|
|
@ -919,7 +919,7 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
|
|||
{
|
||||
struct resources *r = &this->resources;
|
||||
struct nand_chip *nand = &this->nand;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(nand);
|
||||
uint8_t *feature;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
|
|
@ -107,7 +107,7 @@ static irqreturn_t bch_irq(int irq, void *cookie)
|
|||
static inline int get_ecc_strength(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&this->nand);
|
||||
int ecc_strength;
|
||||
|
||||
ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
|
||||
|
@ -139,8 +139,8 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
|
|||
static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
struct nand_oobfree *of = gpmi_hw_ecclayout.oobfree;
|
||||
unsigned int block_mark_bit_offset;
|
||||
|
||||
|
@ -257,7 +257,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this)
|
|||
static int legacy_set_geometry(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&this->nand);
|
||||
unsigned int metadata_size;
|
||||
unsigned int status_size;
|
||||
unsigned int block_mark_bit_offset;
|
||||
|
@ -804,7 +804,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
|
|||
{
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
struct device *dev = this->dev;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&this->nand);
|
||||
|
||||
/* [1] Allocate a command buffer. PAGE_SIZE is enough. */
|
||||
this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
|
||||
|
@ -856,8 +856,8 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
|
|||
|
||||
static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -890,16 +890,16 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
|
|||
|
||||
static int gpmi_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
|
||||
return gpmi_is_ready(this, this->current_chip);
|
||||
}
|
||||
|
||||
static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
|
||||
if ((this->current_chip < 0) && (chipnr >= 0))
|
||||
gpmi_begin(this);
|
||||
|
@ -911,8 +911,8 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
|
|||
|
||||
static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
|
||||
dev_dbg(this->dev, "len is %d\n", len);
|
||||
this->upper_buf = buf;
|
||||
|
@ -923,8 +923,8 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
|
||||
static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
|
||||
dev_dbg(this->dev, "len is %d\n", len);
|
||||
this->upper_buf = (uint8_t *)buf;
|
||||
|
@ -935,8 +935,8 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||
|
||||
static uint8_t gpmi_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
uint8_t *buf = this->data_buffer_dma;
|
||||
|
||||
gpmi_read_buf(mtd, buf, 1);
|
||||
|
@ -994,7 +994,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this,
|
|||
static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
struct bch_geometry *nfc_geo = &this->bch_geometry;
|
||||
void *payload_virt;
|
||||
dma_addr_t payload_phys;
|
||||
|
@ -1074,7 +1074,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint32_t offs, uint32_t len, uint8_t *buf, int page)
|
||||
{
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
void __iomem *bch_regs = this->resources.bch_regs;
|
||||
struct bch_geometry old_geo = this->bch_geometry;
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
|
@ -1162,7 +1162,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
const uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
struct bch_geometry *nfc_geo = &this->bch_geometry;
|
||||
const void *payload_virt;
|
||||
dma_addr_t payload_phys;
|
||||
|
@ -1298,7 +1298,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int page)
|
||||
{
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
|
||||
dev_dbg(this->dev, "page number is %d\n", page);
|
||||
/* clear the OOB buffer */
|
||||
|
@ -1359,7 +1359,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
|
|||
struct nand_chip *chip, uint8_t *buf,
|
||||
int oob_required, int page)
|
||||
{
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
struct bch_geometry *nfc_geo = &this->bch_geometry;
|
||||
int eccsize = nfc_geo->ecc_chunk_size;
|
||||
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
|
||||
|
@ -1448,7 +1448,7 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
|
|||
const uint8_t *buf,
|
||||
int oob_required, int page)
|
||||
{
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
struct bch_geometry *nfc_geo = &this->bch_geometry;
|
||||
int eccsize = nfc_geo->ecc_chunk_size;
|
||||
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
|
||||
|
@ -1538,8 +1538,8 @@ static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
|
||||
static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct gpmi_nand_data *this = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
int ret = 0;
|
||||
uint8_t *block_mark;
|
||||
int column, page, status, chipnr;
|
||||
|
@ -1600,8 +1600,8 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
|
|||
{
|
||||
struct boot_rom_geometry *rom_geo = &this->rom_geometry;
|
||||
struct device *dev = this->dev;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
unsigned int search_area_size_in_strides;
|
||||
unsigned int stride;
|
||||
unsigned int page;
|
||||
|
@ -1655,8 +1655,8 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
|
|||
{
|
||||
struct device *dev = this->dev;
|
||||
struct boot_rom_geometry *rom_geo = &this->rom_geometry;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
unsigned int block_size_in_pages;
|
||||
unsigned int search_area_size_in_strides;
|
||||
unsigned int search_area_size_in_pages;
|
||||
|
@ -1735,7 +1735,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
|
|||
{
|
||||
struct device *dev = this->dev;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
unsigned int block_count;
|
||||
unsigned int block;
|
||||
int chipnr;
|
||||
|
@ -1831,14 +1831,13 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
|
|||
|
||||
static void gpmi_nand_exit(struct gpmi_nand_data *this)
|
||||
{
|
||||
nand_release(&this->mtd);
|
||||
nand_release(nand_to_mtd(&this->nand));
|
||||
gpmi_free_dma_buffer(this);
|
||||
}
|
||||
|
||||
static int gpmi_init_last(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
struct bch_geometry *bch_geo = &this->bch_geometry;
|
||||
int ret;
|
||||
|
@ -1886,21 +1885,20 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
|
|||
|
||||
static int gpmi_nand_init(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct mtd_info *mtd = &this->mtd;
|
||||
struct nand_chip *chip = &this->nand;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
int ret;
|
||||
|
||||
/* init current chip */
|
||||
this->current_chip = -1;
|
||||
|
||||
/* init the MTD data structures */
|
||||
mtd->priv = chip;
|
||||
mtd->name = "gpmi-nand";
|
||||
mtd->dev.parent = this->dev;
|
||||
|
||||
/* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
|
||||
chip->priv = this;
|
||||
nand_set_controller_data(chip, this);
|
||||
nand_set_flash_node(chip, this->pdev->dev.of_node);
|
||||
chip->select_chip = gpmi_select_chip;
|
||||
chip->cmd_ctrl = gpmi_cmd_ctrl;
|
||||
chip->dev_ready = gpmi_dev_ready;
|
||||
|
@ -1954,8 +1952,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
|
|||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
ppdata.of_node = this->pdev->dev.of_node;
|
||||
ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
return 0;
|
||||
|
|
|
@ -160,7 +160,6 @@ struct gpmi_nand_data {
|
|||
|
||||
/* MTD / NAND */
|
||||
struct nand_chip nand;
|
||||
struct mtd_info mtd;
|
||||
|
||||
/* General-use Variables */
|
||||
int current_chip;
|
||||
|
|
|
@ -134,7 +134,6 @@
|
|||
|
||||
struct hinfc_host {
|
||||
struct nand_chip chip;
|
||||
struct mtd_info mtd;
|
||||
struct device *dev;
|
||||
void __iomem *iobase;
|
||||
void __iomem *mmio;
|
||||
|
@ -189,8 +188,8 @@ static void wait_controller_finished(struct hinfc_host *host)
|
|||
|
||||
static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = &host->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
|
@ -262,7 +261,7 @@ static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host)
|
|||
|
||||
static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
||||
|
||||
if ((host->addr_value[0] == host->cache_addr_value[0]) &&
|
||||
(host->addr_value[1] == host->cache_addr_value[1]))
|
||||
|
@ -357,8 +356,8 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect)
|
|||
|
||||
static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
|
||||
if (chipselect < 0)
|
||||
return;
|
||||
|
@ -368,8 +367,8 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
|
|||
|
||||
static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
|
||||
if (host->command == NAND_CMD_STATUS)
|
||||
return *(uint8_t *)(host->mmio);
|
||||
|
@ -384,8 +383,8 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static u16 hisi_nfc_read_word(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
|
||||
host->offset += 2;
|
||||
return *(u16 *)(host->buffer + host->offset - 2);
|
||||
|
@ -394,8 +393,8 @@ static u16 hisi_nfc_read_word(struct mtd_info *mtd)
|
|||
static void
|
||||
hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
|
||||
memcpy(host->buffer + host->offset, buf, len);
|
||||
host->offset += len;
|
||||
|
@ -403,8 +402,8 @@ hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||
|
||||
static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
|
||||
memcpy(buf, host->buffer + host->offset, len);
|
||||
host->offset += len;
|
||||
|
@ -412,8 +411,8 @@ static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
|
||||
static void set_addr(struct mtd_info *mtd, int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
unsigned int command = host->command;
|
||||
|
||||
host->addr_cycle = 0;
|
||||
|
@ -448,8 +447,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr)
|
|||
static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column,
|
||||
int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
int is_cache_invalid = 1;
|
||||
unsigned int flag = 0;
|
||||
|
||||
|
@ -543,7 +542,7 @@ static irqreturn_t hinfc_irq_handle(int irq, void *devid)
|
|||
static int hisi_nand_read_page_hwecc(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc;
|
||||
int stat_1, stat_2;
|
||||
|
||||
|
@ -575,7 +574,7 @@ static int hisi_nand_read_page_hwecc(struct mtd_info *mtd,
|
|||
static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int page)
|
||||
{
|
||||
struct hinfc_host *host = chip->priv;
|
||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
|
@ -643,7 +642,7 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host)
|
|||
int size, strength, ecc_bits;
|
||||
struct device *dev = host->dev;
|
||||
struct nand_chip *chip = &host->chip;
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
struct device_node *np = host->dev->of_node;
|
||||
|
||||
size = of_get_nand_ecc_step_size(np);
|
||||
|
@ -704,7 +703,6 @@ static int hisi_nfc_probe(struct platform_device *pdev)
|
|||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
|
||||
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host)
|
||||
|
@ -713,7 +711,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, host);
|
||||
chip = &host->chip;
|
||||
mtd = &host->mtd;
|
||||
mtd = nand_to_mtd(chip);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
|
@ -737,11 +735,11 @@ static int hisi_nfc_probe(struct platform_device *pdev)
|
|||
goto err_res;
|
||||
}
|
||||
|
||||
mtd->priv = chip;
|
||||
mtd->name = "hisi_nand";
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
chip->priv = host;
|
||||
nand_set_controller_data(chip, host);
|
||||
nand_set_flash_node(chip, np);
|
||||
chip->cmdfunc = hisi_nfc_cmdfunc;
|
||||
chip->select_chip = hisi_nfc_select_chip;
|
||||
chip->read_byte = hisi_nfc_read_byte;
|
||||
|
@ -805,8 +803,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
|
|||
goto err_res;
|
||||
}
|
||||
|
||||
ppdata.of_node = np;
|
||||
ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Err MTD partition=%d\n", ret);
|
||||
goto err_mtd;
|
||||
|
@ -823,7 +820,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
|
|||
static int hisi_nfc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct hinfc_host *host = platform_get_drvdata(pdev);
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
||||
|
||||
nand_release(mtd);
|
||||
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
|
||||
|
||||
struct jz_nand {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
void __iomem *base;
|
||||
struct resource *mem;
|
||||
|
@ -76,13 +75,13 @@ struct jz_nand {
|
|||
|
||||
static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd, struct jz_nand, mtd);
|
||||
return container_of(mtd_to_nand(mtd), struct jz_nand, chip);
|
||||
}
|
||||
|
||||
static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
{
|
||||
struct jz_nand *nand = mtd_to_jz_nand(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
uint32_t ctrl;
|
||||
int banknr;
|
||||
|
||||
|
@ -104,7 +103,7 @@ static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|||
static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
|
||||
{
|
||||
struct jz_nand *nand = mtd_to_jz_nand(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
uint32_t reg;
|
||||
void __iomem *bank_base = nand->bank_base[nand->selected_bank];
|
||||
|
||||
|
@ -225,24 +224,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
|
|||
uint32_t t;
|
||||
unsigned int timeout = 1000;
|
||||
|
||||
t = read_ecc[0];
|
||||
|
||||
if (t == 0xff) {
|
||||
for (i = 1; i < 9; ++i)
|
||||
t &= read_ecc[i];
|
||||
|
||||
t &= dat[0];
|
||||
t &= dat[nand->chip.ecc.size / 2];
|
||||
t &= dat[nand->chip.ecc.size - 1];
|
||||
|
||||
if (t == 0xff) {
|
||||
for (i = 1; i < nand->chip.ecc.size - 1; ++i)
|
||||
t &= dat[i];
|
||||
if (t == 0xff)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; ++i)
|
||||
writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
|
||||
|
||||
|
@ -255,7 +236,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
|
|||
} while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout);
|
||||
|
||||
if (timeout == 0)
|
||||
return -1;
|
||||
return -ETIMEDOUT;
|
||||
|
||||
reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
|
||||
reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
|
||||
|
@ -263,7 +244,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
|
|||
|
||||
if (status & JZ_NAND_STATUS_ERROR) {
|
||||
if (status & JZ_NAND_STATUS_UNCOR_ERROR)
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
|
||||
error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
|
||||
|
||||
|
@ -334,8 +315,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
|
|||
char gpio_name[9];
|
||||
char res_name[6];
|
||||
uint32_t ctrl;
|
||||
struct mtd_info *mtd = &nand->mtd;
|
||||
struct nand_chip *chip = &nand->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
|
||||
/* Request GPIO port. */
|
||||
gpio = JZ_GPIO_MEM_CS0 + bank - 1;
|
||||
|
@ -432,9 +413,8 @@ static int jz_nand_probe(struct platform_device *pdev)
|
|||
goto err_iounmap_mmio;
|
||||
}
|
||||
|
||||
mtd = &nand->mtd;
|
||||
chip = &nand->chip;
|
||||
mtd->priv = chip;
|
||||
mtd = nand_to_mtd(chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
mtd->name = "jz4740-nand";
|
||||
|
||||
|
@ -445,6 +425,7 @@ static int jz_nand_probe(struct platform_device *pdev)
|
|||
chip->ecc.size = 512;
|
||||
chip->ecc.bytes = 9;
|
||||
chip->ecc.strength = 4;
|
||||
chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
|
||||
|
||||
if (pdata)
|
||||
chip->ecc.layout = pdata->ecc_layout;
|
||||
|
@ -543,7 +524,7 @@ static int jz_nand_remove(struct platform_device *pdev)
|
|||
struct jz_nand *nand = platform_get_drvdata(pdev);
|
||||
size_t i;
|
||||
|
||||
nand_release(&nand->mtd);
|
||||
nand_release(nand_to_mtd(&nand->chip));
|
||||
|
||||
/* Deassert and disable all chips */
|
||||
writel(0, nand->base + JZ_REG_NAND_CTRL);
|
||||
|
|
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* JZ4780 BCH controller
|
||||
*
|
||||
* Copyright (c) 2015 Imagination Technologies
|
||||
* Author: Alex Smith <alex.smith@imgtec.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "jz4780_bch.h"
|
||||
|
||||
#define BCH_BHCR 0x0
|
||||
#define BCH_BHCCR 0x8
|
||||
#define BCH_BHCNT 0xc
|
||||
#define BCH_BHDR 0x10
|
||||
#define BCH_BHPAR0 0x14
|
||||
#define BCH_BHERR0 0x84
|
||||
#define BCH_BHINT 0x184
|
||||
#define BCH_BHINTES 0x188
|
||||
#define BCH_BHINTEC 0x18c
|
||||
#define BCH_BHINTE 0x190
|
||||
|
||||
#define BCH_BHCR_BSEL_SHIFT 4
|
||||
#define BCH_BHCR_BSEL_MASK (0x7f << BCH_BHCR_BSEL_SHIFT)
|
||||
#define BCH_BHCR_ENCE BIT(2)
|
||||
#define BCH_BHCR_INIT BIT(1)
|
||||
#define BCH_BHCR_BCHE BIT(0)
|
||||
|
||||
#define BCH_BHCNT_PARITYSIZE_SHIFT 16
|
||||
#define BCH_BHCNT_PARITYSIZE_MASK (0x7f << BCH_BHCNT_PARITYSIZE_SHIFT)
|
||||
#define BCH_BHCNT_BLOCKSIZE_SHIFT 0
|
||||
#define BCH_BHCNT_BLOCKSIZE_MASK (0x7ff << BCH_BHCNT_BLOCKSIZE_SHIFT)
|
||||
|
||||
#define BCH_BHERR_MASK_SHIFT 16
|
||||
#define BCH_BHERR_MASK_MASK (0xffff << BCH_BHERR_MASK_SHIFT)
|
||||
#define BCH_BHERR_INDEX_SHIFT 0
|
||||
#define BCH_BHERR_INDEX_MASK (0x7ff << BCH_BHERR_INDEX_SHIFT)
|
||||
|
||||
#define BCH_BHINT_ERRC_SHIFT 24
|
||||
#define BCH_BHINT_ERRC_MASK (0x7f << BCH_BHINT_ERRC_SHIFT)
|
||||
#define BCH_BHINT_TERRC_SHIFT 16
|
||||
#define BCH_BHINT_TERRC_MASK (0x7f << BCH_BHINT_TERRC_SHIFT)
|
||||
#define BCH_BHINT_DECF BIT(3)
|
||||
#define BCH_BHINT_ENCF BIT(2)
|
||||
#define BCH_BHINT_UNCOR BIT(1)
|
||||
#define BCH_BHINT_ERR BIT(0)
|
||||
|
||||
#define BCH_CLK_RATE (200 * 1000 * 1000)
|
||||
|
||||
/* Timeout for BCH calculation/correction. */
|
||||
#define BCH_TIMEOUT_US 100000
|
||||
|
||||
struct jz4780_bch {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static void jz4780_bch_init(struct jz4780_bch *bch,
|
||||
struct jz4780_bch_params *params, bool encode)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* Clear interrupt status. */
|
||||
writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT);
|
||||
|
||||
/* Set up BCH count register. */
|
||||
reg = params->size << BCH_BHCNT_BLOCKSIZE_SHIFT;
|
||||
reg |= params->bytes << BCH_BHCNT_PARITYSIZE_SHIFT;
|
||||
writel(reg, bch->base + BCH_BHCNT);
|
||||
|
||||
/* Initialise and enable BCH. */
|
||||
reg = BCH_BHCR_BCHE | BCH_BHCR_INIT;
|
||||
reg |= params->strength << BCH_BHCR_BSEL_SHIFT;
|
||||
if (encode)
|
||||
reg |= BCH_BHCR_ENCE;
|
||||
writel(reg, bch->base + BCH_BHCR);
|
||||
}
|
||||
|
||||
static void jz4780_bch_disable(struct jz4780_bch *bch)
|
||||
{
|
||||
writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT);
|
||||
writel(BCH_BHCR_BCHE, bch->base + BCH_BHCCR);
|
||||
}
|
||||
|
||||
static void jz4780_bch_write_data(struct jz4780_bch *bch, const void *buf,
|
||||
size_t size)
|
||||
{
|
||||
size_t size32 = size / sizeof(u32);
|
||||
size_t size8 = size % sizeof(u32);
|
||||
const u32 *src32;
|
||||
const u8 *src8;
|
||||
|
||||
src32 = (const u32 *)buf;
|
||||
while (size32--)
|
||||
writel(*src32++, bch->base + BCH_BHDR);
|
||||
|
||||
src8 = (const u8 *)src32;
|
||||
while (size8--)
|
||||
writeb(*src8++, bch->base + BCH_BHDR);
|
||||
}
|
||||
|
||||
static void jz4780_bch_read_parity(struct jz4780_bch *bch, void *buf,
|
||||
size_t size)
|
||||
{
|
||||
size_t size32 = size / sizeof(u32);
|
||||
size_t size8 = size % sizeof(u32);
|
||||
u32 *dest32;
|
||||
u8 *dest8;
|
||||
u32 val, offset = 0;
|
||||
|
||||
dest32 = (u32 *)buf;
|
||||
while (size32--) {
|
||||
*dest32++ = readl(bch->base + BCH_BHPAR0 + offset);
|
||||
offset += sizeof(u32);
|
||||
}
|
||||
|
||||
dest8 = (u8 *)dest32;
|
||||
val = readl(bch->base + BCH_BHPAR0 + offset);
|
||||
switch (size8) {
|
||||
case 3:
|
||||
dest8[2] = (val >> 16) & 0xff;
|
||||
case 2:
|
||||
dest8[1] = (val >> 8) & 0xff;
|
||||
case 1:
|
||||
dest8[0] = val & 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool jz4780_bch_wait_complete(struct jz4780_bch *bch, unsigned int irq,
|
||||
u32 *status)
|
||||
{
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* While we could use interrupts here and sleep until the operation
|
||||
* completes, the controller works fairly quickly (usually a few
|
||||
* microseconds) and so the overhead of sleeping until we get an
|
||||
* interrupt quite noticeably decreases performance.
|
||||
*/
|
||||
ret = readl_poll_timeout(bch->base + BCH_BHINT, reg,
|
||||
(reg & irq) == irq, 0, BCH_TIMEOUT_US);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if (status)
|
||||
*status = reg;
|
||||
|
||||
writel(reg, bch->base + BCH_BHINT);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* jz4780_bch_calculate() - calculate ECC for a data buffer
|
||||
* @bch: BCH device.
|
||||
* @params: BCH parameters.
|
||||
* @buf: input buffer with raw data.
|
||||
* @ecc_code: output buffer with ECC.
|
||||
*
|
||||
* Return: 0 on success, -ETIMEDOUT if timed out while waiting for BCH
|
||||
* controller.
|
||||
*/
|
||||
int jz4780_bch_calculate(struct jz4780_bch *bch, struct jz4780_bch_params *params,
|
||||
const u8 *buf, u8 *ecc_code)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&bch->lock);
|
||||
jz4780_bch_init(bch, params, true);
|
||||
jz4780_bch_write_data(bch, buf, params->size);
|
||||
|
||||
if (jz4780_bch_wait_complete(bch, BCH_BHINT_ENCF, NULL)) {
|
||||
jz4780_bch_read_parity(bch, ecc_code, params->bytes);
|
||||
} else {
|
||||
dev_err(bch->dev, "timed out while calculating ECC\n");
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
jz4780_bch_disable(bch);
|
||||
mutex_unlock(&bch->lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(jz4780_bch_calculate);
|
||||
|
||||
/**
|
||||
* jz4780_bch_correct() - detect and correct bit errors
|
||||
* @bch: BCH device.
|
||||
* @params: BCH parameters.
|
||||
* @buf: raw data read from the chip.
|
||||
* @ecc_code: ECC read from the chip.
|
||||
*
|
||||
* Given the raw data and the ECC read from the NAND device, detects and
|
||||
* corrects errors in the data.
|
||||
*
|
||||
* Return: the number of bit errors corrected, -EBADMSG if there are too many
|
||||
* errors to correct or -ETIMEDOUT if we timed out waiting for the controller.
|
||||
*/
|
||||
int jz4780_bch_correct(struct jz4780_bch *bch, struct jz4780_bch_params *params,
|
||||
u8 *buf, u8 *ecc_code)
|
||||
{
|
||||
u32 reg, mask, index;
|
||||
int i, ret, count;
|
||||
|
||||
mutex_lock(&bch->lock);
|
||||
|
||||
jz4780_bch_init(bch, params, false);
|
||||
jz4780_bch_write_data(bch, buf, params->size);
|
||||
jz4780_bch_write_data(bch, ecc_code, params->bytes);
|
||||
|
||||
if (!jz4780_bch_wait_complete(bch, BCH_BHINT_DECF, ®)) {
|
||||
dev_err(bch->dev, "timed out while correcting data\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (reg & BCH_BHINT_UNCOR) {
|
||||
dev_warn(bch->dev, "uncorrectable ECC error\n");
|
||||
ret = -EBADMSG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Correct any detected errors. */
|
||||
if (reg & BCH_BHINT_ERR) {
|
||||
count = (reg & BCH_BHINT_ERRC_MASK) >> BCH_BHINT_ERRC_SHIFT;
|
||||
ret = (reg & BCH_BHINT_TERRC_MASK) >> BCH_BHINT_TERRC_SHIFT;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
reg = readl(bch->base + BCH_BHERR0 + (i * 4));
|
||||
mask = (reg & BCH_BHERR_MASK_MASK) >>
|
||||
BCH_BHERR_MASK_SHIFT;
|
||||
index = (reg & BCH_BHERR_INDEX_MASK) >>
|
||||
BCH_BHERR_INDEX_SHIFT;
|
||||
buf[(index * 2) + 0] ^= mask;
|
||||
buf[(index * 2) + 1] ^= mask >> 8;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
jz4780_bch_disable(bch);
|
||||
mutex_unlock(&bch->lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(jz4780_bch_correct);
|
||||
|
||||
/**
|
||||
* jz4780_bch_get() - get the BCH controller device
|
||||
* @np: BCH device tree node.
|
||||
*
|
||||
* Gets the BCH controller device from the specified device tree node. The
|
||||
* device must be released with jz4780_bch_release() when it is no longer being
|
||||
* used.
|
||||
*
|
||||
* Return: a pointer to jz4780_bch, errors are encoded into the pointer.
|
||||
* PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet.
|
||||
*/
|
||||
static struct jz4780_bch *jz4780_bch_get(struct device_node *np)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct jz4780_bch *bch;
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev || !platform_get_drvdata(pdev))
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
get_device(&pdev->dev);
|
||||
|
||||
bch = platform_get_drvdata(pdev);
|
||||
clk_prepare_enable(bch->clk);
|
||||
|
||||
bch->dev = &pdev->dev;
|
||||
return bch;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_jz4780_bch_get() - get the BCH controller from a DT node
|
||||
* @of_node: the node that contains a bch-controller property.
|
||||
*
|
||||
* Get the bch-controller property from the given device tree
|
||||
* node and pass it to jz4780_bch_get to do the work.
|
||||
*
|
||||
* Return: a pointer to jz4780_bch, errors are encoded into the pointer.
|
||||
* PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet.
|
||||
*/
|
||||
struct jz4780_bch *of_jz4780_bch_get(struct device_node *of_node)
|
||||
{
|
||||
struct jz4780_bch *bch = NULL;
|
||||
struct device_node *np;
|
||||
|
||||
np = of_parse_phandle(of_node, "ingenic,bch-controller", 0);
|
||||
|
||||
if (np) {
|
||||
bch = jz4780_bch_get(np);
|
||||
of_node_put(np);
|
||||
}
|
||||
return bch;
|
||||
}
|
||||
EXPORT_SYMBOL(of_jz4780_bch_get);
|
||||
|
||||
/**
|
||||
* jz4780_bch_release() - release the BCH controller device
|
||||
* @bch: BCH device.
|
||||
*/
|
||||
void jz4780_bch_release(struct jz4780_bch *bch)
|
||||
{
|
||||
clk_disable_unprepare(bch->clk);
|
||||
put_device(bch->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(jz4780_bch_release);
|
||||
|
||||
static int jz4780_bch_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct jz4780_bch *bch;
|
||||
struct resource *res;
|
||||
|
||||
bch = devm_kzalloc(dev, sizeof(*bch), GFP_KERNEL);
|
||||
if (!bch)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
bch->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(bch->base))
|
||||
return PTR_ERR(bch->base);
|
||||
|
||||
jz4780_bch_disable(bch);
|
||||
|
||||
bch->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(bch->clk)) {
|
||||
dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(bch->clk));
|
||||
return PTR_ERR(bch->clk);
|
||||
}
|
||||
|
||||
clk_set_rate(bch->clk, BCH_CLK_RATE);
|
||||
|
||||
mutex_init(&bch->lock);
|
||||
|
||||
bch->dev = dev;
|
||||
platform_set_drvdata(pdev, bch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id jz4780_bch_dt_match[] = {
|
||||
{ .compatible = "ingenic,jz4780-bch" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, jz4780_bch_dt_match);
|
||||
|
||||
static struct platform_driver jz4780_bch_driver = {
|
||||
.probe = jz4780_bch_probe,
|
||||
.driver = {
|
||||
.name = "jz4780-bch",
|
||||
.of_match_table = of_match_ptr(jz4780_bch_dt_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(jz4780_bch_driver);
|
||||
|
||||
MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
|
||||
MODULE_AUTHOR("Harvey Hunt <harvey.hunt@imgtec.com>");
|
||||
MODULE_DESCRIPTION("Ingenic JZ4780 BCH error correction driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* JZ4780 BCH controller
|
||||
*
|
||||
* Copyright (c) 2015 Imagination Technologies
|
||||
* Author: Alex Smith <alex.smith@imgtec.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_MTD_NAND_JZ4780_BCH_H__
|
||||
#define __DRIVERS_MTD_NAND_JZ4780_BCH_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
struct device_node;
|
||||
struct jz4780_bch;
|
||||
|
||||
/**
|
||||
* struct jz4780_bch_params - BCH parameters
|
||||
* @size: data bytes per ECC step.
|
||||
* @bytes: ECC bytes per step.
|
||||
* @strength: number of correctable bits per ECC step.
|
||||
*/
|
||||
struct jz4780_bch_params {
|
||||
int size;
|
||||
int bytes;
|
||||
int strength;
|
||||
};
|
||||
|
||||
int jz4780_bch_calculate(struct jz4780_bch *bch,
|
||||
struct jz4780_bch_params *params,
|
||||
const u8 *buf, u8 *ecc_code);
|
||||
int jz4780_bch_correct(struct jz4780_bch *bch,
|
||||
struct jz4780_bch_params *params, u8 *buf,
|
||||
u8 *ecc_code);
|
||||
|
||||
void jz4780_bch_release(struct jz4780_bch *bch);
|
||||
struct jz4780_bch *of_jz4780_bch_get(struct device_node *np);
|
||||
|
||||
#endif /* __DRIVERS_MTD_NAND_JZ4780_BCH_H__ */
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* JZ4780 NAND driver
|
||||
*
|
||||
* Copyright (c) 2015 Imagination Technologies
|
||||
* Author: Alex Smith <alex.smith@imgtec.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_mtd.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <linux/jz4780-nemc.h>
|
||||
|
||||
#include "jz4780_bch.h"
|
||||
|
||||
#define DRV_NAME "jz4780-nand"
|
||||
|
||||
#define OFFSET_DATA 0x00000000
|
||||
#define OFFSET_CMD 0x00400000
|
||||
#define OFFSET_ADDR 0x00800000
|
||||
|
||||
/* Command delay when there is no R/B pin. */
|
||||
#define RB_DELAY_US 100
|
||||
|
||||
struct jz4780_nand_cs {
|
||||
unsigned int bank;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
struct jz4780_nand_controller {
|
||||
struct device *dev;
|
||||
struct jz4780_bch *bch;
|
||||
struct nand_hw_control controller;
|
||||
unsigned int num_banks;
|
||||
struct list_head chips;
|
||||
int selected;
|
||||
struct jz4780_nand_cs cs[];
|
||||
};
|
||||
|
||||
struct jz4780_nand_chip {
|
||||
struct nand_chip chip;
|
||||
struct list_head chip_list;
|
||||
|
||||
struct nand_ecclayout ecclayout;
|
||||
|
||||
struct gpio_desc *busy_gpio;
|
||||
struct gpio_desc *wp_gpio;
|
||||
unsigned int reading: 1;
|
||||
};
|
||||
|
||||
static inline struct jz4780_nand_chip *to_jz4780_nand_chip(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct jz4780_nand_chip, chip);
|
||||
}
|
||||
|
||||
static inline struct jz4780_nand_controller *to_jz4780_nand_controller(struct nand_hw_control *ctrl)
|
||||
{
|
||||
return container_of(ctrl, struct jz4780_nand_controller, controller);
|
||||
}
|
||||
|
||||
static void jz4780_nand_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
{
|
||||
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
|
||||
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
|
||||
struct jz4780_nand_cs *cs;
|
||||
|
||||
/* Ensure the currently selected chip is deasserted. */
|
||||
if (chipnr == -1 && nfc->selected >= 0) {
|
||||
cs = &nfc->cs[nfc->selected];
|
||||
jz4780_nemc_assert(nfc->dev, cs->bank, false);
|
||||
}
|
||||
|
||||
nfc->selected = chipnr;
|
||||
}
|
||||
|
||||
static void jz4780_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
|
||||
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
|
||||
struct jz4780_nand_cs *cs;
|
||||
|
||||
if (WARN_ON(nfc->selected < 0))
|
||||
return;
|
||||
|
||||
cs = &nfc->cs[nfc->selected];
|
||||
|
||||
jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE);
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
if (ctrl & NAND_ALE)
|
||||
writeb(cmd, cs->base + OFFSET_ADDR);
|
||||
else if (ctrl & NAND_CLE)
|
||||
writeb(cmd, cs->base + OFFSET_CMD);
|
||||
}
|
||||
|
||||
static int jz4780_nand_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
|
||||
|
||||
return !gpiod_get_value_cansleep(nand->busy_gpio);
|
||||
}
|
||||
|
||||
static void jz4780_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
|
||||
|
||||
nand->reading = (mode == NAND_ECC_READ);
|
||||
}
|
||||
|
||||
static int jz4780_nand_ecc_calculate(struct mtd_info *mtd, const u8 *dat,
|
||||
u8 *ecc_code)
|
||||
{
|
||||
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
|
||||
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
|
||||
struct jz4780_bch_params params;
|
||||
|
||||
/*
|
||||
* Don't need to generate the ECC when reading, BCH does it for us as
|
||||
* part of decoding/correction.
|
||||
*/
|
||||
if (nand->reading)
|
||||
return 0;
|
||||
|
||||
params.size = nand->chip.ecc.size;
|
||||
params.bytes = nand->chip.ecc.bytes;
|
||||
params.strength = nand->chip.ecc.strength;
|
||||
|
||||
return jz4780_bch_calculate(nfc->bch, ¶ms, dat, ecc_code);
|
||||
}
|
||||
|
||||
static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat,
|
||||
u8 *read_ecc, u8 *calc_ecc)
|
||||
{
|
||||
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
|
||||
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
|
||||
struct jz4780_bch_params params;
|
||||
|
||||
params.size = nand->chip.ecc.size;
|
||||
params.bytes = nand->chip.ecc.bytes;
|
||||
params.strength = nand->chip.ecc.strength;
|
||||
|
||||
return jz4780_bch_correct(nfc->bch, ¶ms, dat, read_ecc);
|
||||
}
|
||||
|
||||
static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev)
|
||||
{
|
||||
struct nand_chip *chip = &nand->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller);
|
||||
struct nand_ecclayout *layout = &nand->ecclayout;
|
||||
u32 start, i;
|
||||
|
||||
chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) *
|
||||
(chip->ecc.strength / 8);
|
||||
|
||||
switch (chip->ecc.mode) {
|
||||
case NAND_ECC_HW:
|
||||
if (!nfc->bch) {
|
||||
dev_err(dev, "HW BCH selected, but BCH controller not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chip->ecc.hwctl = jz4780_nand_ecc_hwctl;
|
||||
chip->ecc.calculate = jz4780_nand_ecc_calculate;
|
||||
chip->ecc.correct = jz4780_nand_ecc_correct;
|
||||
/* fall through */
|
||||
case NAND_ECC_SOFT:
|
||||
case NAND_ECC_SOFT_BCH:
|
||||
dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n",
|
||||
(nfc->bch) ? "hardware BCH" : "software ECC",
|
||||
chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
|
||||
break;
|
||||
case NAND_ECC_NONE:
|
||||
dev_info(dev, "not using ECC\n");
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "ECC mode %d not supported\n", chip->ecc.mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The NAND core will generate the ECC layout for SW ECC */
|
||||
if (chip->ecc.mode != NAND_ECC_HW)
|
||||
return 0;
|
||||
|
||||
/* Generate ECC layout. ECC codes are right aligned in the OOB area. */
|
||||
layout->eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes;
|
||||
|
||||
if (layout->eccbytes > mtd->oobsize - 2) {
|
||||
dev_err(dev,
|
||||
"invalid ECC config: required %d ECC bytes, but only %d are available",
|
||||
layout->eccbytes, mtd->oobsize - 2);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
start = mtd->oobsize - layout->eccbytes;
|
||||
for (i = 0; i < layout->eccbytes; i++)
|
||||
layout->eccpos[i] = start + i;
|
||||
|
||||
layout->oobfree[0].offset = 2;
|
||||
layout->oobfree[0].length = mtd->oobsize - layout->eccbytes - 2;
|
||||
|
||||
chip->ecc.layout = layout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4780_nand_init_chip(struct platform_device *pdev,
|
||||
struct jz4780_nand_controller *nfc,
|
||||
struct device_node *np,
|
||||
unsigned int chipnr)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct jz4780_nand_chip *nand;
|
||||
struct jz4780_nand_cs *cs;
|
||||
struct resource *res;
|
||||
struct nand_chip *chip;
|
||||
struct mtd_info *mtd;
|
||||
const __be32 *reg;
|
||||
int ret = 0;
|
||||
|
||||
cs = &nfc->cs[chipnr];
|
||||
|
||||
reg = of_get_property(np, "reg", NULL);
|
||||
if (!reg)
|
||||
return -EINVAL;
|
||||
|
||||
cs->bank = be32_to_cpu(*reg);
|
||||
|
||||
jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr);
|
||||
cs->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(cs->base))
|
||||
return PTR_ERR(cs->base);
|
||||
|
||||
nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL);
|
||||
if (!nand)
|
||||
return -ENOMEM;
|
||||
|
||||
nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN);
|
||||
|
||||
if (IS_ERR(nand->busy_gpio)) {
|
||||
ret = PTR_ERR(nand->busy_gpio);
|
||||
dev_err(dev, "failed to request busy GPIO: %d\n", ret);
|
||||
return ret;
|
||||
} else if (nand->busy_gpio) {
|
||||
nand->chip.dev_ready = jz4780_nand_dev_ready;
|
||||
}
|
||||
|
||||
nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW);
|
||||
|
||||
if (IS_ERR(nand->wp_gpio)) {
|
||||
ret = PTR_ERR(nand->wp_gpio);
|
||||
dev_err(dev, "failed to request WP GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
chip = &nand->chip;
|
||||
mtd = nand_to_mtd(chip);
|
||||
mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
|
||||
cs->bank);
|
||||
if (!mtd->name)
|
||||
return -ENOMEM;
|
||||
mtd->dev.parent = dev;
|
||||
|
||||
chip->IO_ADDR_R = cs->base + OFFSET_DATA;
|
||||
chip->IO_ADDR_W = cs->base + OFFSET_DATA;
|
||||
chip->chip_delay = RB_DELAY_US;
|
||||
chip->options = NAND_NO_SUBPAGE_WRITE;
|
||||
chip->select_chip = jz4780_nand_select_chip;
|
||||
chip->cmd_ctrl = jz4780_nand_cmd_ctrl;
|
||||
chip->ecc.mode = NAND_ECC_HW;
|
||||
chip->controller = &nfc->controller;
|
||||
nand_set_flash_node(chip, np);
|
||||
|
||||
ret = nand_scan_ident(mtd, 1, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = jz4780_nand_init_ecc(nand, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nand_scan_tail(mtd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
nand_release(mtd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&nand->chip_list, &nfc->chips);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc)
|
||||
{
|
||||
struct jz4780_nand_chip *chip;
|
||||
|
||||
while (!list_empty(&nfc->chips)) {
|
||||
chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list);
|
||||
nand_release(nand_to_mtd(&chip->chip));
|
||||
list_del(&chip->chip_list);
|
||||
}
|
||||
}
|
||||
|
||||
static int jz4780_nand_init_chips(struct jz4780_nand_controller *nfc,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np;
|
||||
int i = 0;
|
||||
int ret;
|
||||
int num_chips = of_get_child_count(dev->of_node);
|
||||
|
||||
if (num_chips > nfc->num_banks) {
|
||||
dev_err(dev, "found %d chips but only %d banks\n", num_chips, nfc->num_banks);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for_each_child_of_node(dev->of_node, np) {
|
||||
ret = jz4780_nand_init_chip(pdev, nfc, np, i);
|
||||
if (ret) {
|
||||
jz4780_nand_cleanup_chips(nfc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4780_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
unsigned int num_banks;
|
||||
struct jz4780_nand_controller *nfc;
|
||||
int ret;
|
||||
|
||||
num_banks = jz4780_nemc_num_banks(dev);
|
||||
if (num_banks == 0) {
|
||||
dev_err(dev, "no banks found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
nfc = devm_kzalloc(dev, sizeof(*nfc) + (sizeof(nfc->cs[0]) * num_banks), GFP_KERNEL);
|
||||
if (!nfc)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Check for BCH HW before we call nand_scan_ident, to prevent us from
|
||||
* having to call it again if the BCH driver returns -EPROBE_DEFER.
|
||||
*/
|
||||
nfc->bch = of_jz4780_bch_get(dev->of_node);
|
||||
if (IS_ERR(nfc->bch))
|
||||
return PTR_ERR(nfc->bch);
|
||||
|
||||
nfc->dev = dev;
|
||||
nfc->num_banks = num_banks;
|
||||
|
||||
spin_lock_init(&nfc->controller.lock);
|
||||
INIT_LIST_HEAD(&nfc->chips);
|
||||
init_waitqueue_head(&nfc->controller.wq);
|
||||
|
||||
ret = jz4780_nand_init_chips(nfc, pdev);
|
||||
if (ret) {
|
||||
if (nfc->bch)
|
||||
jz4780_bch_release(nfc->bch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, nfc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4780_nand_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct jz4780_nand_controller *nfc = platform_get_drvdata(pdev);
|
||||
|
||||
if (nfc->bch)
|
||||
jz4780_bch_release(nfc->bch);
|
||||
|
||||
jz4780_nand_cleanup_chips(nfc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id jz4780_nand_dt_match[] = {
|
||||
{ .compatible = "ingenic,jz4780-nand" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, jz4780_nand_dt_match);
|
||||
|
||||
static struct platform_driver jz4780_nand_driver = {
|
||||
.probe = jz4780_nand_probe,
|
||||
.remove = jz4780_nand_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = of_match_ptr(jz4780_nand_dt_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(jz4780_nand_driver);
|
||||
|
||||
MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
|
||||
MODULE_AUTHOR("Harvey Hunt <harvey.hunt@imgtec.com>");
|
||||
MODULE_DESCRIPTION("Ingenic JZ4780 NAND driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -173,7 +173,6 @@ struct lpc32xx_nand_host {
|
|||
struct nand_chip nand_chip;
|
||||
struct lpc32xx_mlc_platform_data *pdata;
|
||||
struct clk *clk;
|
||||
struct mtd_info mtd;
|
||||
void __iomem *io_base;
|
||||
int irq;
|
||||
struct lpc32xx_nand_cfg_mlc *ncfg;
|
||||
|
@ -275,8 +274,8 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
|
|||
static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (cmd != NAND_CMD_NONE) {
|
||||
if (ctrl & NAND_CLE)
|
||||
|
@ -291,8 +290,8 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
|||
*/
|
||||
static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if ((readb(MLC_ISR(host->io_base)) &
|
||||
(MLCISR_CONTROLLER_READY | MLCISR_NAND_READY)) ==
|
||||
|
@ -318,7 +317,7 @@ static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host)
|
|||
|
||||
static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
if (readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY)
|
||||
goto exit;
|
||||
|
@ -338,7 +337,7 @@ static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip)
|
|||
static int lpc32xx_waitfunc_controller(struct mtd_info *mtd,
|
||||
struct nand_chip *chip)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
if (readb(MLC_ISR(host->io_base)) & MLCISR_CONTROLLER_READY)
|
||||
goto exit;
|
||||
|
@ -389,8 +388,8 @@ static void lpc32xx_dma_complete_func(void *completion)
|
|||
static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
|
||||
enum dma_transfer_direction dir)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
|
||||
int res;
|
||||
|
@ -431,7 +430,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
|
|||
static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
int i, j;
|
||||
uint8_t *oobbuf = chip->oob_poi;
|
||||
uint32_t mlc_isr;
|
||||
|
@ -498,7 +497,7 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
|
|||
const uint8_t *buf, int oob_required,
|
||||
int page)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
const uint8_t *oobbuf = chip->oob_poi;
|
||||
uint8_t *dma_buf = (uint8_t *)buf;
|
||||
int res;
|
||||
|
@ -543,7 +542,7 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
|
|||
static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int page)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
/* Read whole page - necessary with MLC controller! */
|
||||
lpc32xx_read_page(mtd, chip, host->dummy_buf, 1, page);
|
||||
|
@ -566,7 +565,7 @@ static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode)
|
|||
|
||||
static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
|
||||
dma_cap_mask_t mask;
|
||||
|
||||
if (!host->pdata || !host->pdata->dma_filter) {
|
||||
|
@ -647,7 +646,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
struct nand_chip *nand_chip;
|
||||
struct resource *rc;
|
||||
int res;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
|
||||
|
@ -661,8 +659,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
|
||||
host->io_base_phy = rc->start;
|
||||
|
||||
mtd = &host->mtd;
|
||||
nand_chip = &host->nand_chip;
|
||||
mtd = nand_to_mtd(nand_chip);
|
||||
if (pdev->dev.of_node)
|
||||
host->ncfg = lpc32xx_parse_dt(&pdev->dev);
|
||||
if (!host->ncfg) {
|
||||
|
@ -681,8 +679,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
|
||||
host->pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
nand_chip->priv = host; /* link the private data structures */
|
||||
mtd->priv = nand_chip;
|
||||
/* link the private data structures */
|
||||
nand_set_controller_data(nand_chip, host);
|
||||
nand_set_flash_node(nand_chip, pdev->dev.of_node);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
/* Get NAND clock */
|
||||
|
@ -786,8 +785,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
|
||||
mtd->name = DRV_NAME;
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
|
||||
res = mtd_device_register(mtd, host->ncfg->parts,
|
||||
host->ncfg->num_parts);
|
||||
if (!res)
|
||||
return res;
|
||||
|
@ -815,7 +813,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
static int lpc32xx_nand_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
|
||||
|
||||
nand_release(mtd);
|
||||
free_irq(host->irq, host);
|
||||
|
|
|
@ -204,7 +204,6 @@ struct lpc32xx_nand_host {
|
|||
struct nand_chip nand_chip;
|
||||
struct lpc32xx_slc_platform_data *pdata;
|
||||
struct clk *clk;
|
||||
struct mtd_info mtd;
|
||||
void __iomem *io_base;
|
||||
struct lpc32xx_nand_cfg_slc *ncfg;
|
||||
|
||||
|
@ -260,8 +259,8 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
|||
unsigned int ctrl)
|
||||
{
|
||||
uint32_t tmp;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
/* Does CE state need to be changed? */
|
||||
tmp = readl(SLC_CFG(host->io_base));
|
||||
|
@ -284,8 +283,8 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
|||
*/
|
||||
static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
int rdy = 0;
|
||||
|
||||
if ((readl(SLC_STAT(host->io_base)) & SLCSTAT_NAND_READY) != 0)
|
||||
|
@ -339,8 +338,8 @@ static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd,
|
|||
*/
|
||||
static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
return (uint8_t)readl(SLC_DATA(host->io_base));
|
||||
}
|
||||
|
@ -350,8 +349,8 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
|
|||
*/
|
||||
static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
/* Direct device read with no ECC */
|
||||
while (len-- > 0)
|
||||
|
@ -363,8 +362,8 @@ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
*/
|
||||
static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
|
||||
/* Direct device write with no ECC */
|
||||
while (len-- > 0)
|
||||
|
@ -428,8 +427,8 @@ static void lpc32xx_dma_complete_func(void *completion)
|
|||
static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
|
||||
void *mem, int len, enum dma_transfer_direction dir)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
|
||||
int res;
|
||||
|
@ -488,8 +487,8 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
|
|||
static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages,
|
||||
int read)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
int i, status = 0;
|
||||
unsigned long timeout;
|
||||
int res;
|
||||
|
@ -604,7 +603,7 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
|
|||
struct nand_chip *chip, uint8_t *buf,
|
||||
int oob_required, int page)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
int stat, i, status;
|
||||
uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE];
|
||||
|
||||
|
@ -666,7 +665,7 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
|
|||
const uint8_t *buf,
|
||||
int oob_required, int page)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = chip->priv;
|
||||
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
|
||||
uint8_t *pb = chip->oob_poi + chip->ecc.layout->eccpos[0];
|
||||
int error;
|
||||
|
||||
|
@ -703,7 +702,7 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
|
|||
|
||||
static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host)
|
||||
{
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
|
||||
dma_cap_mask_t mask;
|
||||
|
||||
if (!host->pdata || !host->pdata->dma_filter) {
|
||||
|
@ -763,7 +762,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
struct mtd_info *mtd;
|
||||
struct nand_chip *chip;
|
||||
struct resource *rc;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
int res;
|
||||
|
||||
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@ -800,10 +798,10 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
|
||||
host->pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
mtd = &host->mtd;
|
||||
chip = &host->nand_chip;
|
||||
chip->priv = host;
|
||||
mtd->priv = chip;
|
||||
mtd = nand_to_mtd(chip);
|
||||
nand_set_controller_data(chip, host);
|
||||
nand_set_flash_node(chip, pdev->dev.of_node);
|
||||
mtd->owner = THIS_MODULE;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
|
@ -908,8 +906,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
mtd->name = "nxp_lpc3220_slc";
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
|
||||
res = mtd_device_register(mtd, host->ncfg->parts,
|
||||
host->ncfg->num_parts);
|
||||
if (!res)
|
||||
return res;
|
||||
|
@ -933,7 +930,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
|
|||
{
|
||||
uint32_t tmp;
|
||||
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
|
||||
struct mtd_info *mtd = &host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
|
||||
|
||||
nand_release(mtd);
|
||||
dma_release_channel(host->dma_chan);
|
||||
|
|
|
@ -118,7 +118,6 @@
|
|||
#define NFC_TIMEOUT (HZ / 10) /* 1/10 s */
|
||||
|
||||
struct mpc5121_nfc_prv {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
int irq;
|
||||
void __iomem *regs;
|
||||
|
@ -135,8 +134,8 @@ static void mpc5121_nfc_done(struct mtd_info *mtd);
|
|||
/* Read NFC register */
|
||||
static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
|
||||
return in_be16(prv->regs + reg);
|
||||
}
|
||||
|
@ -144,8 +143,8 @@ static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
|
|||
/* Write NFC register */
|
||||
static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
|
||||
out_be16(prv->regs + reg, val);
|
||||
}
|
||||
|
@ -214,8 +213,8 @@ static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd)
|
|||
static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
|
||||
{
|
||||
struct mtd_info *mtd = data;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
|
||||
nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK);
|
||||
wake_up(&prv->irq_waitq);
|
||||
|
@ -226,8 +225,8 @@ static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
|
|||
/* Wait for operation complete */
|
||||
static void mpc5121_nfc_done(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
int rv;
|
||||
|
||||
if ((nfc_read(mtd, NFC_CONFIG2) & NFC_INT) == 0) {
|
||||
|
@ -246,7 +245,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd)
|
|||
/* Do address cycle(s) */
|
||||
static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u32 pagemask = chip->pagemask;
|
||||
|
||||
if (column != -1) {
|
||||
|
@ -281,8 +280,8 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
|
|||
/* Init external chip select logic on ADS5121 board */
|
||||
static int ads5121_chipselect_init(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
struct device_node *dn;
|
||||
|
||||
dn = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld");
|
||||
|
@ -303,8 +302,8 @@ static int ads5121_chipselect_init(struct mtd_info *mtd)
|
|||
/* Control chips select signal on ADS5121 board */
|
||||
static void ads5121_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
|
||||
u8 v;
|
||||
|
||||
v = in_8(prv->csreg);
|
||||
|
@ -333,8 +332,8 @@ static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
|
|||
static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
|
||||
int column, int page)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
|
||||
prv->column = (column >= 0) ? column : 0;
|
||||
prv->spareonly = 0;
|
||||
|
@ -406,8 +405,8 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
|
|||
static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
|
||||
u8 *buffer, uint size, int wr)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = nand->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
|
||||
uint o, s, sbsize, blksize;
|
||||
|
||||
/*
|
||||
|
@ -458,8 +457,8 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
|
|||
static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len,
|
||||
int wr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
uint c = prv->column;
|
||||
uint l;
|
||||
|
||||
|
@ -536,8 +535,8 @@ static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
|
|||
*/
|
||||
static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
struct mpc512x_reset_module *rm;
|
||||
struct device_node *rmnode;
|
||||
uint rcw_pagesize = 0;
|
||||
|
@ -615,8 +614,8 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
|
|||
/* Free driver resources */
|
||||
static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mpc5121_nfc_prv *prv = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
|
||||
if (prv->clk)
|
||||
clk_disable_unprepare(prv->clk);
|
||||
|
@ -639,7 +638,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
|
|||
int resettime = 0;
|
||||
int retval = 0;
|
||||
int rev, len;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
|
||||
/*
|
||||
* Check SoC revision. This driver supports only NFC
|
||||
|
@ -655,12 +653,12 @@ static int mpc5121_nfc_probe(struct platform_device *op)
|
|||
if (!prv)
|
||||
return -ENOMEM;
|
||||
|
||||
mtd = &prv->mtd;
|
||||
chip = &prv->chip;
|
||||
mtd = nand_to_mtd(chip);
|
||||
|
||||
mtd->priv = chip;
|
||||
mtd->dev.parent = dev;
|
||||
chip->priv = prv;
|
||||
nand_set_controller_data(chip, prv);
|
||||
nand_set_flash_node(chip, dn);
|
||||
prv->dev = dev;
|
||||
|
||||
/* Read NFC configuration from Reset Config Word */
|
||||
|
@ -703,7 +701,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
|
|||
}
|
||||
|
||||
mtd->name = "MPC5121 NAND";
|
||||
ppdata.of_node = dn;
|
||||
chip->dev_ready = mpc5121_nfc_dev_ready;
|
||||
chip->cmdfunc = mpc5121_nfc_command;
|
||||
chip->read_byte = mpc5121_nfc_read_byte;
|
||||
|
@ -815,7 +812,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
|
|||
dev_set_drvdata(dev, mtd);
|
||||
|
||||
/* Register device in MTD */
|
||||
retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
|
||||
retval = mtd_device_register(mtd, NULL, 0);
|
||||
if (retval) {
|
||||
dev_err(dev, "Error adding MTD device!\n");
|
||||
goto error;
|
||||
|
|
|
@ -173,7 +173,6 @@ struct mxc_nand_devtype_data {
|
|||
};
|
||||
|
||||
struct mxc_nand_host {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip nand;
|
||||
struct device *dev;
|
||||
|
||||
|
@ -532,8 +531,8 @@ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islas
|
|||
|
||||
static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = readl(NFC_V3_CONFIG1);
|
||||
|
@ -548,8 +547,8 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
|
|||
|
||||
static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
/* NANDFC buffer 0 is used for page read/write */
|
||||
writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
|
||||
|
@ -562,8 +561,8 @@ static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
|
|||
|
||||
static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
int bufs, i;
|
||||
|
||||
if (mtd->writesize > 512)
|
||||
|
@ -663,8 +662,8 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
/*
|
||||
* 1-Bit errors are automatically corrected in HW. No need for
|
||||
|
@ -675,7 +674,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
|
|||
|
||||
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
|
||||
pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -684,8 +683,8 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
|
|||
static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
u32 ecc_stat, err;
|
||||
int no_subpages = 1;
|
||||
int ret = 0;
|
||||
|
@ -702,7 +701,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
|
|||
err = ecc_stat & ecc_bit_mask;
|
||||
if (err > err_limit) {
|
||||
printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
} else {
|
||||
ret += err;
|
||||
}
|
||||
|
@ -722,8 +721,8 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
|
|||
|
||||
static u_char mxc_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
uint8_t ret;
|
||||
|
||||
/* Check for status request */
|
||||
|
@ -746,8 +745,8 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
uint16_t ret;
|
||||
|
||||
ret = *(uint16_t *)(host->data_buf + host->buf_start);
|
||||
|
@ -762,8 +761,8 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
|
|||
static void mxc_nand_write_buf(struct mtd_info *mtd,
|
||||
const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
u16 col = host->buf_start;
|
||||
int n = mtd->oobsize + mtd->writesize - col;
|
||||
|
||||
|
@ -780,8 +779,8 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
|
|||
*/
|
||||
static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
u16 col = host->buf_start;
|
||||
int n = mtd->oobsize + mtd->writesize - col;
|
||||
|
||||
|
@ -796,8 +795,8 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
* deselect of the NAND chip */
|
||||
static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (chip == -1) {
|
||||
/* Disable the NFC clock */
|
||||
|
@ -817,8 +816,8 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
|
|||
|
||||
static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
if (chip == -1) {
|
||||
/* Disable the NFC clock */
|
||||
|
@ -850,8 +849,8 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
|
|||
*/
|
||||
static void copy_spare(struct mtd_info *mtd, bool bfrom)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct mxc_nand_host *host = this->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(this);
|
||||
u16 i, oob_chunk_size;
|
||||
u16 num_chunks = mtd->writesize / 512;
|
||||
|
||||
|
@ -893,8 +892,8 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
|
|||
*/
|
||||
static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
/* Write out column address, if necessary */
|
||||
if (column != -1) {
|
||||
|
@ -979,8 +978,8 @@ static void ecc_8bit_layout_4k(struct nand_ecclayout *layout)
|
|||
|
||||
static void preset_v1(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
uint16_t config1 = 0;
|
||||
|
||||
if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize)
|
||||
|
@ -1007,8 +1006,8 @@ static void preset_v1(struct mtd_info *mtd)
|
|||
|
||||
static void preset_v2(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
uint16_t config1 = 0;
|
||||
|
||||
config1 |= NFC_V2_CONFIG1_FP_INT;
|
||||
|
@ -1053,8 +1052,8 @@ static void preset_v2(struct mtd_info *mtd)
|
|||
|
||||
static void preset_v3(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct mxc_nand_host *host = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(chip);
|
||||
uint32_t config2, config3;
|
||||
int i, addr_phases;
|
||||
|
||||
|
@ -1067,8 +1066,7 @@ static void preset_v3(struct mtd_info *mtd)
|
|||
|
||||
/* Blocks to be unlocked */
|
||||
for (i = 0; i < NAND_MAX_CHIPS; i++)
|
||||
writel(0x0 | (0xffff << 16),
|
||||
NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
|
||||
writel(0xffff << 16, NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
|
||||
|
||||
writel(0, NFC_V3_IPC);
|
||||
|
||||
|
@ -1125,8 +1123,8 @@ static void preset_v3(struct mtd_info *mtd)
|
|||
static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct mxc_nand_host *host = nand_chip->priv;
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||
|
||||
pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
|
||||
command, column, page_addr);
|
||||
|
@ -1515,15 +1513,15 @@ static int mxcnd_probe(struct platform_device *pdev)
|
|||
host->dev = &pdev->dev;
|
||||
/* structures must be linked */
|
||||
this = &host->nand;
|
||||
mtd = &host->mtd;
|
||||
mtd->priv = this;
|
||||
mtd = nand_to_mtd(this);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
mtd->name = DRIVER_NAME;
|
||||
|
||||
/* 50 us command delay time */
|
||||
this->chip_delay = 5;
|
||||
|
||||
this->priv = host;
|
||||
nand_set_controller_data(this, host);
|
||||
nand_set_flash_node(this, pdev->dev.of_node),
|
||||
this->dev_ready = mxc_nand_dev_ready;
|
||||
this->cmdfunc = mxc_nand_command;
|
||||
this->read_byte = mxc_nand_read_byte;
|
||||
|
@ -1683,9 +1681,7 @@ static int mxcnd_probe(struct platform_device *pdev)
|
|||
|
||||
/* Register the partitions */
|
||||
mtd_device_parse_register(mtd, part_probes,
|
||||
&(struct mtd_part_parser_data){
|
||||
.of_node = pdev->dev.of_node,
|
||||
},
|
||||
NULL,
|
||||
host->pdata.parts,
|
||||
host->pdata.nr_parts);
|
||||
|
||||
|
@ -1704,7 +1700,7 @@ static int mxcnd_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct mxc_nand_host *host = platform_get_drvdata(pdev);
|
||||
|
||||
nand_release(&host->mtd);
|
||||
nand_release(nand_to_mtd(&host->nand));
|
||||
if (host->clk_act)
|
||||
clk_disable_unprepare(host->clk);
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ DEFINE_LED_TRIGGER(nand_led_trigger);
|
|||
static int check_offs_len(struct mtd_info *mtd,
|
||||
loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int ret = 0;
|
||||
|
||||
/* Start address must align on block boundary */
|
||||
|
@ -132,7 +132,7 @@ static int check_offs_len(struct mtd_info *mtd,
|
|||
*/
|
||||
static void nand_release_device(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
/* Release the controller and the chip */
|
||||
spin_lock(&chip->controller->lock);
|
||||
|
@ -150,7 +150,7 @@ static void nand_release_device(struct mtd_info *mtd)
|
|||
*/
|
||||
static uint8_t nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
return readb(chip->IO_ADDR_R);
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
|
|||
*/
|
||||
static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
|||
*/
|
||||
static u16 nand_read_word(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
return readw(chip->IO_ADDR_R);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ static u16 nand_read_word(struct mtd_info *mtd)
|
|||
*/
|
||||
static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
switch (chipnr) {
|
||||
case -1:
|
||||
|
@ -211,7 +211,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|||
*/
|
||||
static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
chip->write_buf(mtd, &byte, 1);
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
|
|||
*/
|
||||
static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
uint16_t word = byte;
|
||||
|
||||
/*
|
||||
|
@ -257,7 +257,7 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
|
|||
*/
|
||||
static void 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);
|
||||
|
||||
iowrite8_rep(chip->IO_ADDR_W, buf, len);
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||
*/
|
||||
static void 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);
|
||||
|
||||
ioread8_rep(chip->IO_ADDR_R, buf, len);
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
*/
|
||||
static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u16 *p = (u16 *) buf;
|
||||
|
||||
iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
|
||||
|
@ -303,7 +303,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||
*/
|
||||
static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u16 *p = (u16 *) buf;
|
||||
|
||||
ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
|
||||
|
@ -320,7 +320,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
||||
{
|
||||
int page, chipnr, res = 0, i = 0;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u16 bad;
|
||||
|
||||
if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
|
||||
|
@ -380,7 +380,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|||
*/
|
||||
static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mtd_oob_ops ops;
|
||||
uint8_t buf[2] = { 0, 0 };
|
||||
int ret = 0, res, i = 0;
|
||||
|
@ -430,7 +430,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|||
*/
|
||||
static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int res, ret = 0;
|
||||
|
||||
if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
|
||||
|
@ -471,7 +471,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
|
|||
*/
|
||||
static int nand_check_wp(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
/* Broken xD cards report WP despite being writable */
|
||||
if (chip->options & NAND_BROKEN_XD)
|
||||
|
@ -491,7 +491,7 @@ static int nand_check_wp(struct mtd_info *mtd)
|
|||
*/
|
||||
static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (!chip->bbt)
|
||||
return 0;
|
||||
|
@ -512,7 +512,7 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
|
|||
static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
||||
int allowbbt)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (!chip->bbt)
|
||||
return chip->block_bad(mtd, ofs, getchip);
|
||||
|
@ -531,7 +531,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|||
*/
|
||||
static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int i;
|
||||
|
||||
/* Wait for the device to get ready */
|
||||
|
@ -551,7 +551,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
|
|||
*/
|
||||
void nand_wait_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
unsigned long timeo = 400;
|
||||
|
||||
if (in_interrupt() || oops_in_progress)
|
||||
|
@ -582,7 +582,7 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
|
|||
*/
|
||||
static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
|
||||
{
|
||||
register struct nand_chip *chip = mtd->priv;
|
||||
register struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
timeo = jiffies + msecs_to_jiffies(timeo);
|
||||
do {
|
||||
|
@ -605,7 +605,7 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
|
|||
static void nand_command(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
register struct nand_chip *chip = mtd->priv;
|
||||
register struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
|
||||
|
||||
/* Write out the command to the device */
|
||||
|
@ -708,7 +708,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|||
static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
register struct nand_chip *chip = mtd->priv;
|
||||
register struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
/* Emulate NAND_CMD_READOOB */
|
||||
if (command == NAND_CMD_READOOB) {
|
||||
|
@ -832,7 +832,7 @@ static void panic_nand_get_device(struct nand_chip *chip,
|
|||
static int
|
||||
nand_get_device(struct mtd_info *mtd, int new_state)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
spinlock_t *lock = &chip->controller->lock;
|
||||
wait_queue_head_t *wq = &chip->controller->wq;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
@ -952,7 +952,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
|
|||
{
|
||||
int ret = 0;
|
||||
int status, page;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
/* Submit address of first page to unlock */
|
||||
page = ofs >> chip->page_shift;
|
||||
|
@ -987,7 +987,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|||
{
|
||||
int ret = 0;
|
||||
int chipnr;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
pr_debug("%s: start = 0x%012llx, len = %llu\n",
|
||||
__func__, (unsigned long long)ofs, len);
|
||||
|
@ -1050,7 +1050,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|||
{
|
||||
int ret = 0;
|
||||
int chipnr, status, page;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
pr_debug("%s: start = 0x%012llx, len = %llu\n",
|
||||
__func__, (unsigned long long)ofs, len);
|
||||
|
@ -1426,6 +1426,16 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
|
||||
stat = chip->ecc.correct(mtd, p,
|
||||
&chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
|
||||
if (stat == -EBADMSG &&
|
||||
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
||||
/* check for empty pages with bitflips */
|
||||
stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
|
||||
&chip->buffers->ecccode[i],
|
||||
chip->ecc.bytes,
|
||||
NULL, 0,
|
||||
chip->ecc.strength);
|
||||
}
|
||||
|
||||
if (stat < 0) {
|
||||
mtd->ecc_stats.failed++;
|
||||
} else {
|
||||
|
@ -1475,6 +1485,15 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
int stat;
|
||||
|
||||
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
|
||||
if (stat == -EBADMSG &&
|
||||
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
||||
/* check for empty pages with bitflips */
|
||||
stat = nand_check_erased_ecc_chunk(p, eccsize,
|
||||
&ecc_code[i], eccbytes,
|
||||
NULL, 0,
|
||||
chip->ecc.strength);
|
||||
}
|
||||
|
||||
if (stat < 0) {
|
||||
mtd->ecc_stats.failed++;
|
||||
} else {
|
||||
|
@ -1527,6 +1546,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
|||
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
|
||||
|
||||
stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
|
||||
if (stat == -EBADMSG &&
|
||||
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
||||
/* check for empty pages with bitflips */
|
||||
stat = nand_check_erased_ecc_chunk(p, eccsize,
|
||||
&ecc_code[i], eccbytes,
|
||||
NULL, 0,
|
||||
chip->ecc.strength);
|
||||
}
|
||||
|
||||
if (stat < 0) {
|
||||
mtd->ecc_stats.failed++;
|
||||
} else {
|
||||
|
@ -1554,6 +1582,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
int i, eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
int eccsteps = chip->ecc.steps;
|
||||
int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
|
||||
uint8_t *p = buf;
|
||||
uint8_t *oob = chip->oob_poi;
|
||||
unsigned int max_bitflips = 0;
|
||||
|
@ -1573,19 +1602,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
chip->read_buf(mtd, oob, eccbytes);
|
||||
stat = chip->ecc.correct(mtd, p, oob, NULL);
|
||||
|
||||
if (stat < 0) {
|
||||
mtd->ecc_stats.failed++;
|
||||
} else {
|
||||
mtd->ecc_stats.corrected += stat;
|
||||
max_bitflips = max_t(unsigned int, max_bitflips, stat);
|
||||
}
|
||||
|
||||
oob += eccbytes;
|
||||
|
||||
if (chip->ecc.postpad) {
|
||||
chip->read_buf(mtd, oob, chip->ecc.postpad);
|
||||
oob += chip->ecc.postpad;
|
||||
}
|
||||
|
||||
if (stat == -EBADMSG &&
|
||||
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
||||
/* check for empty pages with bitflips */
|
||||
stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
|
||||
oob - eccpadbytes,
|
||||
eccpadbytes,
|
||||
NULL, 0,
|
||||
chip->ecc.strength);
|
||||
}
|
||||
|
||||
if (stat < 0) {
|
||||
mtd->ecc_stats.failed++;
|
||||
} else {
|
||||
mtd->ecc_stats.corrected += stat;
|
||||
max_bitflips = max_t(unsigned int, max_bitflips, stat);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate remaining oob bytes */
|
||||
|
@ -1655,7 +1694,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
|||
*/
|
||||
static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
pr_debug("setting READ RETRY mode %d\n", retry_mode);
|
||||
|
||||
|
@ -1680,7 +1719,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
int chipnr, page, realpage, col, bytes, aligned, oob_required;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int ret = 0;
|
||||
uint32_t readlen = ops->len;
|
||||
uint32_t oobreadlen = ops->ooblen;
|
||||
|
@ -2024,7 +2063,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
int page, realpage, chipnr;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mtd_ecc_stats stats;
|
||||
int readlen = ops->ooblen;
|
||||
int len;
|
||||
|
@ -2472,7 +2511,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
|
||||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
/*
|
||||
* Initialise to all 0xFF, to avoid the possibility of left over OOB
|
||||
|
@ -2532,7 +2571,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
int chipnr, realpage, page, blockmask, column;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
uint32_t writelen = ops->len;
|
||||
|
||||
uint32_t oobwritelen = ops->ooblen;
|
||||
|
@ -2662,7 +2701,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|||
static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
size_t *retlen, const uint8_t *buf)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mtd_oob_ops ops;
|
||||
int ret;
|
||||
|
||||
|
@ -2722,7 +2761,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|||
struct mtd_oob_ops *ops)
|
||||
{
|
||||
int chipnr, page, status, len;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
pr_debug("%s: to = 0x%08x, len = %i\n",
|
||||
__func__, (unsigned int)to, (int)ops->ooblen);
|
||||
|
@ -2847,7 +2886,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
|
|||
*/
|
||||
static int single_erase(struct mtd_info *mtd, int page)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
/* Send commands to erase a block */
|
||||
chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
|
||||
chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
|
||||
|
@ -2879,7 +2918,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|||
int allowbbt)
|
||||
{
|
||||
int page, status, pages_per_block, ret, chipnr;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
loff_t len;
|
||||
|
||||
pr_debug("%s: start = 0x%012llx, len = %llu\n",
|
||||
|
@ -3094,7 +3133,7 @@ static int nand_suspend(struct mtd_info *mtd)
|
|||
*/
|
||||
static void nand_resume(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (chip->state == FL_PM_SUSPENDED)
|
||||
nand_release_device(mtd);
|
||||
|
@ -3266,7 +3305,7 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
|
|||
|
||||
static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
|
||||
|
||||
return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
|
||||
|
@ -3937,11 +3976,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|||
return type;
|
||||
}
|
||||
|
||||
static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
struct device_node *dn)
|
||||
static int nand_dt_init(struct nand_chip *chip)
|
||||
{
|
||||
struct device_node *dn = nand_get_flash_node(chip);
|
||||
int ecc_mode, ecc_strength, ecc_step;
|
||||
|
||||
if (!dn)
|
||||
return 0;
|
||||
|
||||
if (of_get_nand_bus_width(dn) == 16)
|
||||
chip->options |= NAND_BUSWIDTH_16;
|
||||
|
||||
|
@ -3985,15 +4027,16 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
|||
struct nand_flash_dev *table)
|
||||
{
|
||||
int i, nand_maf_id, nand_dev_id;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nand_flash_dev *type;
|
||||
int ret;
|
||||
|
||||
if (chip->flash_node) {
|
||||
ret = nand_dt_init(mtd, chip, chip->flash_node);
|
||||
ret = nand_dt_init(chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!mtd->name && mtd->dev.parent)
|
||||
mtd->name = dev_name(mtd->dev.parent);
|
||||
|
||||
/* Set the default functions */
|
||||
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
|
||||
|
@ -4053,7 +4096,7 @@ EXPORT_SYMBOL(nand_scan_ident);
|
|||
*/
|
||||
static bool nand_ecc_strength_good(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
int corr, ds_corr;
|
||||
|
||||
|
@ -4082,7 +4125,7 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
|
|||
int nand_scan_tail(struct mtd_info *mtd)
|
||||
{
|
||||
int i;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
struct nand_buffers *nbuf;
|
||||
|
||||
|
@ -4166,7 +4209,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||
ecc->write_oob = nand_write_oob_std;
|
||||
if (!ecc->read_subpage)
|
||||
ecc->read_subpage = nand_read_subpage;
|
||||
if (!ecc->write_subpage)
|
||||
if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
|
||||
ecc->write_subpage = nand_write_subpage_hwecc;
|
||||
|
||||
case NAND_ECC_HW_SYNDROME:
|
||||
|
@ -4426,7 +4469,7 @@ EXPORT_SYMBOL(nand_scan);
|
|||
*/
|
||||
void nand_release(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
|
||||
nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
|
||||
|
|
|
@ -172,7 +172,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
|||
struct nand_bbt_descr *td, int offs)
|
||||
{
|
||||
int res, ret = 0, i, j, act = 0;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
size_t retlen, len, totlen;
|
||||
loff_t from;
|
||||
int bits = td->options & NAND_BBT_NRBITS_MSK;
|
||||
|
@ -263,7 +263,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
|||
*/
|
||||
static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int res = 0, i;
|
||||
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
|
@ -388,7 +388,7 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||
static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
/* Read the primary version, if available */
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
|
@ -454,7 +454,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
|||
static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
struct nand_bbt_descr *bd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int i, numblocks, numpages;
|
||||
int startblock;
|
||||
loff_t from;
|
||||
|
@ -523,7 +523,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||
*/
|
||||
static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int i, chips;
|
||||
int startblock, block, dir;
|
||||
int scanlen = mtd->writesize + mtd->oobsize;
|
||||
|
@ -618,7 +618,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
|
||||
int chipsel)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct erase_info einfo;
|
||||
int i, res, chip = 0;
|
||||
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
|
||||
|
@ -819,7 +819,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||
*/
|
||||
static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
|
||||
return create_bbt(mtd, this->buffers->databuf, bd, -1);
|
||||
}
|
||||
|
@ -838,7 +838,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
|
|||
static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
|
||||
{
|
||||
int i, chips, writeops, create, chipsel, res, res2;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct nand_bbt_descr *td = this->bbt_td;
|
||||
struct nand_bbt_descr *md = this->bbt_md;
|
||||
struct nand_bbt_descr *rd, *rd2;
|
||||
|
@ -962,7 +962,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||
*/
|
||||
static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int i, j, chips, block, nrblocks, update;
|
||||
uint8_t oldval;
|
||||
|
||||
|
@ -1022,7 +1022,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||
*/
|
||||
static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
u32 pattern_len;
|
||||
u32 bits;
|
||||
u32 table_size;
|
||||
|
@ -1074,7 +1074,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||
*/
|
||||
static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int len, res;
|
||||
uint8_t *buf;
|
||||
struct nand_bbt_descr *td = this->bbt_td;
|
||||
|
@ -1147,7 +1147,7 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||
*/
|
||||
static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int len, res = 0;
|
||||
int chip, chipsel;
|
||||
uint8_t *buf;
|
||||
|
@ -1281,7 +1281,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
|
|||
*/
|
||||
int nand_default_bbt(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int ret;
|
||||
|
||||
/* Is a flash based bad block table requested? */
|
||||
|
@ -1317,7 +1317,7 @@ int nand_default_bbt(struct mtd_info *mtd)
|
|||
*/
|
||||
int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int block;
|
||||
|
||||
block = (int)(offs >> this->bbt_erase_shift);
|
||||
|
@ -1332,7 +1332,7 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
|
|||
*/
|
||||
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int block, res;
|
||||
|
||||
block = (int)(offs >> this->bbt_erase_shift);
|
||||
|
@ -1359,7 +1359,7 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
|
|||
*/
|
||||
int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
int block, ret = 0;
|
||||
|
||||
block = (int)(offs >> this->bbt_erase_shift);
|
||||
|
|
|
@ -52,7 +52,7 @@ struct nand_bch_control {
|
|||
int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
|
||||
unsigned char *code)
|
||||
{
|
||||
const struct nand_chip *chip = mtd->priv;
|
||||
const struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nand_bch_control *nbc = chip->ecc.priv;
|
||||
unsigned int i;
|
||||
|
||||
|
@ -79,7 +79,7 @@ EXPORT_SYMBOL(nand_bch_calculate_ecc);
|
|||
int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
|
||||
unsigned char *read_ecc, unsigned char *calc_ecc)
|
||||
{
|
||||
const struct nand_chip *chip = mtd->priv;
|
||||
const struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nand_bch_control *nbc = chip->ecc.priv;
|
||||
unsigned int *errloc = nbc->errloc;
|
||||
int i, count;
|
||||
|
@ -98,7 +98,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
|
|||
}
|
||||
} else if (count < 0) {
|
||||
printk(KERN_ERR "ecc unrecoverable error\n");
|
||||
count = -1;
|
||||
count = -EBADMSG;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -424,7 +424,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
|
|||
unsigned char *code)
|
||||
{
|
||||
__nand_calculate_ecc(buf,
|
||||
((struct nand_chip *)mtd->priv)->ecc.size, code);
|
||||
mtd_to_nand(mtd)->ecc.size, code);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *buf,
|
|||
return 1; /* error in ECC data; no action needed */
|
||||
|
||||
pr_err("%s: uncorrectable ECC error\n", __func__);
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
EXPORT_SYMBOL(__nand_correct_data);
|
||||
|
||||
|
@ -524,7 +524,7 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
|
|||
unsigned char *read_ecc, unsigned char *calc_ecc)
|
||||
{
|
||||
return __nand_correct_data(buf, read_ecc, calc_ecc,
|
||||
((struct nand_chip *)mtd->priv)->ecc.size);
|
||||
mtd_to_nand(mtd)->ecc.size);
|
||||
}
|
||||
EXPORT_SYMBOL(nand_correct_data);
|
||||
|
||||
|
|
|
@ -666,8 +666,8 @@ static char *get_partition_name(int i)
|
|||
*/
|
||||
static int init_nandsim(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nandsim *ns = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
int i, ret = 0;
|
||||
uint64_t remains;
|
||||
uint64_t next_offset;
|
||||
|
@ -1908,7 +1908,8 @@ static void switch_state(struct nandsim *ns)
|
|||
|
||||
static u_char ns_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
u_char outb = 0x00;
|
||||
|
||||
/* Sanity and correctness checks */
|
||||
|
@ -1969,7 +1970,8 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
|
||||
/* Sanity and correctness checks */
|
||||
if (!ns->lines.ce) {
|
||||
|
@ -2123,7 +2125,8 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
|
|||
|
||||
static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
|
||||
ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
|
||||
ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
|
||||
|
@ -2141,7 +2144,7 @@ static int ns_device_ready(struct mtd_info *mtd)
|
|||
|
||||
static uint16_t ns_nand_read_word(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
NS_DBG("read_word\n");
|
||||
|
||||
|
@ -2150,7 +2153,8 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd)
|
|||
|
||||
static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
|
||||
/* Check that chip is expecting data input */
|
||||
if (!(ns->state & STATE_DATAIN_MASK)) {
|
||||
|
@ -2177,7 +2181,8 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
|
||||
static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
|
||||
/* Sanity and correctness checks */
|
||||
if (!ns->lines.ce) {
|
||||
|
@ -2198,7 +2203,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd);
|
||||
buf[i] = mtd_to_nand(mtd)->read_byte(mtd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -2236,16 +2241,15 @@ static int __init ns_init_module(void)
|
|||
}
|
||||
|
||||
/* Allocate and initialize mtd_info, nand_chip and nandsim structures */
|
||||
nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
|
||||
+ sizeof(struct nandsim), GFP_KERNEL);
|
||||
if (!nsmtd) {
|
||||
chip = kzalloc(sizeof(struct nand_chip) + sizeof(struct nandsim),
|
||||
GFP_KERNEL);
|
||||
if (!chip) {
|
||||
NS_ERR("unable to allocate core structures.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
chip = (struct nand_chip *)(nsmtd + 1);
|
||||
nsmtd->priv = (void *)chip;
|
||||
nsmtd = nand_to_mtd(chip);
|
||||
nand = (struct nandsim *)(chip + 1);
|
||||
chip->priv = (void *)nand;
|
||||
nand_set_controller_data(chip, (void *)nand);
|
||||
|
||||
/*
|
||||
* Register simulator's callbacks.
|
||||
|
@ -2392,7 +2396,7 @@ static int __init ns_init_module(void)
|
|||
for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
|
||||
kfree(nand->partitions[i].name);
|
||||
error:
|
||||
kfree(nsmtd);
|
||||
kfree(chip);
|
||||
free_lists();
|
||||
|
||||
return retval;
|
||||
|
@ -2405,7 +2409,8 @@ module_init(ns_init_module);
|
|||
*/
|
||||
static void __exit ns_cleanup_module(void)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(nsmtd);
|
||||
struct nandsim *ns = nand_get_controller_data(chip);
|
||||
int i;
|
||||
|
||||
nandsim_debugfs_remove(ns);
|
||||
|
@ -2413,7 +2418,7 @@ static void __exit ns_cleanup_module(void)
|
|||
nand_release(nsmtd); /* Unregister driver */
|
||||
for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
|
||||
kfree(ns->partitions[i].name);
|
||||
kfree(nsmtd); /* Free other structures */
|
||||
kfree(mtd_to_nand(nsmtd)); /* Free other structures */
|
||||
free_lists();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
struct ndfc_controller {
|
||||
struct platform_device *ofdev;
|
||||
void __iomem *ndfcbase;
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
int chip_select;
|
||||
struct nand_hw_control ndfc_control;
|
||||
|
@ -48,8 +47,8 @@ static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
|
|||
static void ndfc_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
uint32_t ccr;
|
||||
struct nand_chip *nchip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = nchip->priv;
|
||||
struct nand_chip *nchip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(nchip);
|
||||
|
||||
ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
|
||||
if (chip >= 0) {
|
||||
|
@ -62,8 +61,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
|
|||
|
||||
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
@ -76,8 +75,8 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
|||
|
||||
static int ndfc_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
|
||||
|
||||
return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
|
||||
}
|
||||
|
@ -85,8 +84,8 @@ static int ndfc_ready(struct mtd_info *mtd)
|
|||
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
uint32_t ccr;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
|
||||
|
||||
ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
|
||||
ccr |= NDFC_CCR_RESET_ECC;
|
||||
|
@ -97,8 +96,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
static int ndfc_calculate_ecc(struct mtd_info *mtd,
|
||||
const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
|
||||
uint32_t ecc;
|
||||
uint8_t *p = (uint8_t *)&ecc;
|
||||
|
||||
|
@ -121,8 +120,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
|
|||
*/
|
||||
static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
|
||||
uint32_t *p = (uint32_t *) buf;
|
||||
|
||||
for(;len > 0; len -= 4)
|
||||
|
@ -131,8 +130,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
|
||||
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct ndfc_controller *ndfc = chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
|
||||
uint32_t *p = (uint32_t *) buf;
|
||||
|
||||
for(;len > 0; len -= 4)
|
||||
|
@ -147,7 +146,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
|
|||
{
|
||||
struct device_node *flash_np;
|
||||
struct nand_chip *chip = &ndfc->chip;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
int ret;
|
||||
|
||||
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
|
||||
|
@ -166,33 +165,32 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
|
|||
chip->ecc.size = 256;
|
||||
chip->ecc.bytes = 3;
|
||||
chip->ecc.strength = 1;
|
||||
chip->priv = ndfc;
|
||||
nand_set_controller_data(chip, ndfc);
|
||||
|
||||
ndfc->mtd.priv = chip;
|
||||
ndfc->mtd.dev.parent = &ndfc->ofdev->dev;
|
||||
mtd->dev.parent = &ndfc->ofdev->dev;
|
||||
|
||||
flash_np = of_get_next_child(node, NULL);
|
||||
if (!flash_np)
|
||||
return -ENODEV;
|
||||
nand_set_flash_node(chip, flash_np);
|
||||
|
||||
ppdata.of_node = flash_np;
|
||||
ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
|
||||
dev_name(&ndfc->ofdev->dev), flash_np->name);
|
||||
if (!ndfc->mtd.name) {
|
||||
mtd->name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev),
|
||||
flash_np->name);
|
||||
if (!mtd->name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = nand_scan(&ndfc->mtd, 1);
|
||||
ret = nand_scan(mtd, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0);
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
|
||||
err:
|
||||
of_node_put(flash_np);
|
||||
if (ret)
|
||||
kfree(ndfc->mtd.name);
|
||||
kfree(mtd->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -259,9 +257,10 @@ static int ndfc_probe(struct platform_device *ofdev)
|
|||
static int ndfc_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
|
||||
struct mtd_info *mtd = nand_to_mtd(&ndfc->chip);
|
||||
|
||||
nand_release(&ndfc->mtd);
|
||||
kfree(ndfc->mtd.name);
|
||||
nand_release(mtd);
|
||||
kfree(mtd->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,13 +55,17 @@
|
|||
__raw_writel((val), (dev)->reg + REG_SMADDR)
|
||||
|
||||
struct nuc900_nand {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
void __iomem *reg;
|
||||
struct clk *clk;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static inline struct nuc900_nand *mtd_to_nuc900(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct nuc900_nand, chip);
|
||||
}
|
||||
|
||||
static const struct mtd_partition partitions[] = {
|
||||
{
|
||||
.name = "NAND FS 0",
|
||||
|
@ -78,9 +82,7 @@ static const struct mtd_partition partitions[] = {
|
|||
static unsigned char nuc900_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
unsigned char ret;
|
||||
struct nuc900_nand *nand;
|
||||
|
||||
nand = container_of(mtd, struct nuc900_nand, mtd);
|
||||
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
|
||||
|
||||
ret = (unsigned char)read_data_reg(nand);
|
||||
|
||||
|
@ -91,9 +93,7 @@ static void nuc900_nand_read_buf(struct mtd_info *mtd,
|
|||
unsigned char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nuc900_nand *nand;
|
||||
|
||||
nand = container_of(mtd, struct nuc900_nand, mtd);
|
||||
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
buf[i] = (unsigned char)read_data_reg(nand);
|
||||
|
@ -103,9 +103,7 @@ static void nuc900_nand_write_buf(struct mtd_info *mtd,
|
|||
const unsigned char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
struct nuc900_nand *nand;
|
||||
|
||||
nand = container_of(mtd, struct nuc900_nand, mtd);
|
||||
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
write_data_reg(nand, buf[i]);
|
||||
|
@ -124,11 +122,9 @@ static int nuc900_check_rb(struct nuc900_nand *nand)
|
|||
|
||||
static int nuc900_nand_devready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nuc900_nand *nand;
|
||||
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
|
||||
int ready;
|
||||
|
||||
nand = container_of(mtd, struct nuc900_nand, mtd);
|
||||
|
||||
ready = (nuc900_check_rb(nand)) ? 1 : 0;
|
||||
return ready;
|
||||
}
|
||||
|
@ -136,10 +132,8 @@ static int nuc900_nand_devready(struct mtd_info *mtd)
|
|||
static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
register struct nand_chip *chip = mtd->priv;
|
||||
struct nuc900_nand *nand;
|
||||
|
||||
nand = container_of(mtd, struct nuc900_nand, mtd);
|
||||
register struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
|
||||
|
||||
if (command == NAND_CMD_READOOB) {
|
||||
column += mtd->writesize;
|
||||
|
@ -241,6 +235,7 @@ static int nuc900_nand_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct nuc900_nand *nuc900_nand;
|
||||
struct nand_chip *chip;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
|
||||
nuc900_nand = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_nand),
|
||||
|
@ -248,9 +243,9 @@ static int nuc900_nand_probe(struct platform_device *pdev)
|
|||
if (!nuc900_nand)
|
||||
return -ENOMEM;
|
||||
chip = &(nuc900_nand->chip);
|
||||
mtd = nand_to_mtd(chip);
|
||||
|
||||
nuc900_nand->mtd.priv = chip;
|
||||
nuc900_nand->mtd.dev.parent = &pdev->dev;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
spin_lock_init(&nuc900_nand->lock);
|
||||
|
||||
nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
|
@ -274,11 +269,10 @@ static int nuc900_nand_probe(struct platform_device *pdev)
|
|||
|
||||
nuc900_nand_enable(nuc900_nand);
|
||||
|
||||
if (nand_scan(&(nuc900_nand->mtd), 1))
|
||||
if (nand_scan(mtd, 1))
|
||||
return -ENXIO;
|
||||
|
||||
mtd_device_register(&(nuc900_nand->mtd), partitions,
|
||||
ARRAY_SIZE(partitions));
|
||||
mtd_device_register(mtd, partitions, ARRAY_SIZE(partitions));
|
||||
|
||||
platform_set_drvdata(pdev, nuc900_nand);
|
||||
|
||||
|
@ -289,7 +283,7 @@ static int nuc900_nand_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
|
||||
|
||||
nand_release(&nuc900_nand->mtd);
|
||||
nand_release(nand_to_mtd(&nuc900_nand->chip));
|
||||
clk_disable(nuc900_nand->clk);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -152,7 +152,6 @@ static struct nand_hw_control omap_gpmc_controller = {
|
|||
|
||||
struct omap_nand_info {
|
||||
struct omap_nand_platform_data *pdata;
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip nand;
|
||||
struct platform_device *pdev;
|
||||
|
||||
|
@ -177,6 +176,11 @@ struct omap_nand_info {
|
|||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct omap_nand_info, nand);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap_prefetch_enable - configures and starts prefetch transfer
|
||||
* @cs: cs (chip select) number
|
||||
|
@ -247,8 +251,7 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
|
|||
*/
|
||||
static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
|
||||
if (cmd != NAND_CMD_NONE) {
|
||||
if (ctrl & NAND_CLE)
|
||||
|
@ -270,7 +273,7 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
|||
*/
|
||||
static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
|
||||
ioread8_rep(nand->IO_ADDR_R, buf, len);
|
||||
}
|
||||
|
@ -283,8 +286,7 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
|
|||
*/
|
||||
static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
u_char *p = (u_char *)buf;
|
||||
u32 status = 0;
|
||||
|
||||
|
@ -306,7 +308,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
*/
|
||||
static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *nand = mtd->priv;
|
||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||
|
||||
ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
|
||||
}
|
||||
|
@ -319,8 +321,7 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
|
|||
*/
|
||||
static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
u16 *p = (u16 *) buf;
|
||||
u32 status = 0;
|
||||
/* FIXME try bursts of writesw() or DMA ... */
|
||||
|
@ -344,8 +345,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
|
|||
*/
|
||||
static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
uint32_t r_count = 0;
|
||||
int ret = 0;
|
||||
u32 *p = (u32 *)buf;
|
||||
|
@ -392,8 +392,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
|
|||
static void omap_write_buf_pref(struct mtd_info *mtd,
|
||||
const u_char *buf, int len)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
uint32_t w_count = 0;
|
||||
int i = 0, ret = 0;
|
||||
u16 *p = (u16 *)buf;
|
||||
|
@ -458,8 +457,7 @@ static void omap_nand_dma_callback(void *data)
|
|||
static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
|
||||
unsigned int len, int is_write)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
enum dma_data_direction dir = is_write ? DMA_TO_DEVICE :
|
||||
DMA_FROM_DEVICE;
|
||||
|
@ -623,8 +621,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
|
|||
*/
|
||||
static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
int ret = 0;
|
||||
|
||||
if (len <= mtd->oobsize) {
|
||||
|
@ -671,8 +668,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
|
|||
static void omap_write_buf_irq_pref(struct mtd_info *mtd,
|
||||
const u_char *buf, int len)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
int ret = 0;
|
||||
unsigned long tim, limit;
|
||||
u32 val;
|
||||
|
@ -830,12 +826,12 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
|
|||
case 1:
|
||||
/* Uncorrectable error */
|
||||
pr_debug("ECC UNCORRECTED_ERROR 1\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
|
||||
case 11:
|
||||
/* UN-Correctable error */
|
||||
pr_debug("ECC UNCORRECTED_ERROR B\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
|
||||
case 12:
|
||||
/* Correctable error */
|
||||
|
@ -865,7 +861,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
|
|||
return 0;
|
||||
}
|
||||
pr_debug("UNCORRECTED_ERROR default\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -886,8 +882,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
|
|||
static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
int blockCnt = 0, i = 0, ret = 0;
|
||||
int stat = 0;
|
||||
|
||||
|
@ -928,8 +923,7 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
|
|||
static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
|
||||
u_char *ecc_code)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
u32 val;
|
||||
|
||||
val = readl(info->reg.gpmc_ecc_config);
|
||||
|
@ -953,9 +947,8 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
|
|||
*/
|
||||
static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
|
||||
u32 val;
|
||||
|
||||
|
@ -1001,9 +994,8 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
|
|||
*/
|
||||
static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
unsigned long timeo = jiffies;
|
||||
int status, state = this->state;
|
||||
|
||||
|
@ -1031,8 +1023,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|||
static int omap_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
|
||||
val = readl(info->reg.gpmc_status);
|
||||
|
||||
|
@ -1058,10 +1049,9 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
|
|||
{
|
||||
unsigned int bch_type;
|
||||
unsigned int dev_width, nsectors;
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
enum omap_ecc ecc_opt = info->ecc_opt;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u32 val, wr_mode;
|
||||
unsigned int ecc_size1, ecc_size0;
|
||||
|
||||
|
@ -1162,8 +1152,7 @@ static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
|
|||
static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
|
||||
const u_char *dat, u_char *ecc_calc)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
int eccbytes = info->nand.ecc.bytes;
|
||||
struct gpmc_nand_regs *gpmc_regs = &info->reg;
|
||||
u8 *ecc_code;
|
||||
|
@ -1334,8 +1323,7 @@ static int erased_sector_bitflips(u_char *data, u_char *oob,
|
|||
static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
struct nand_ecc_ctrl *ecc = &info->nand.ecc;
|
||||
int eccsteps = info->nand.ecc.steps;
|
||||
int i , j, stat = 0;
|
||||
|
@ -1663,7 +1651,6 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
unsigned sig;
|
||||
unsigned oob_index;
|
||||
struct resource *res;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (pdata == NULL) {
|
||||
|
@ -1683,11 +1670,11 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
info->reg = pdata->reg;
|
||||
info->of_node = pdata->of_node;
|
||||
info->ecc_opt = pdata->ecc_opt;
|
||||
mtd = &info->mtd;
|
||||
mtd->priv = &info->nand;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
nand_chip = &info->nand;
|
||||
mtd = nand_to_mtd(nand_chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
nand_chip->ecc.priv = NULL;
|
||||
nand_set_flash_node(nand_chip, pdata->of_node);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -1909,7 +1896,7 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
|
||||
|
||||
err = elm_config(info->elm_dev, BCH4_ECC,
|
||||
info->mtd.writesize / nand_chip->ecc.size,
|
||||
mtd->writesize / nand_chip->ecc.size,
|
||||
nand_chip->ecc.size, nand_chip->ecc.bytes);
|
||||
if (err < 0)
|
||||
goto return_error;
|
||||
|
@ -1963,7 +1950,7 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
nand_chip->ecc.write_page = omap_write_page_bch;
|
||||
|
||||
err = elm_config(info->elm_dev, BCH8_ECC,
|
||||
info->mtd.writesize / nand_chip->ecc.size,
|
||||
mtd->writesize / nand_chip->ecc.size,
|
||||
nand_chip->ecc.size, nand_chip->ecc.bytes);
|
||||
if (err < 0)
|
||||
goto return_error;
|
||||
|
@ -1993,7 +1980,7 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
nand_chip->ecc.write_page = omap_write_page_bch;
|
||||
|
||||
err = elm_config(info->elm_dev, BCH16_ECC,
|
||||
info->mtd.writesize / nand_chip->ecc.size,
|
||||
mtd->writesize / nand_chip->ecc.size,
|
||||
nand_chip->ecc.size, nand_chip->ecc.bytes);
|
||||
if (err < 0)
|
||||
goto return_error;
|
||||
|
@ -2037,9 +2024,7 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
goto return_error;
|
||||
}
|
||||
|
||||
ppdata.of_node = pdata->of_node;
|
||||
mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts,
|
||||
pdata->nr_parts);
|
||||
mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
|
||||
|
||||
platform_set_drvdata(pdev, mtd);
|
||||
|
||||
|
@ -2058,9 +2043,8 @@ static int omap_nand_probe(struct platform_device *pdev)
|
|||
static int omap_nand_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mtd_info *mtd = platform_get_drvdata(pdev);
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
|
||||
mtd);
|
||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||
struct omap_nand_info *info = mtd_to_omap(mtd);
|
||||
if (nand_chip->ecc.priv) {
|
||||
nand_bch_free(nand_chip->ecc.priv);
|
||||
nand_chip->ecc.priv = NULL;
|
||||
|
|
|
@ -414,7 +414,7 @@ static int elm_probe(struct platform_device *pdev)
|
|||
ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0,
|
||||
pdev->name, info);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failure requesting irq %i\n", irq->start);
|
||||
dev_err(&pdev->dev, "failure requesting %pr\n", irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *nc = mtd->priv;
|
||||
struct orion_nand_data *board = nc->priv;
|
||||
struct nand_chip *nc = mtd_to_nand(mtd);
|
||||
struct orion_nand_data *board = nand_get_controller_data(nc);
|
||||
u32 offs;
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
|
@ -47,7 +47,7 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
|
|||
|
||||
static void orion_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;
|
||||
uint64_t *buf64;
|
||||
int i = 0;
|
||||
|
@ -76,7 +76,6 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
static int __init orion_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mtd_info *mtd;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
struct nand_chip *nc;
|
||||
struct orion_nand_data *board;
|
||||
struct resource *res;
|
||||
|
@ -86,11 +85,11 @@ static int __init orion_nand_probe(struct platform_device *pdev)
|
|||
u32 val = 0;
|
||||
|
||||
nc = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct nand_chip) + sizeof(struct mtd_info),
|
||||
sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
if (!nc)
|
||||
return -ENOMEM;
|
||||
mtd = (struct mtd_info *)(nc + 1);
|
||||
mtd = nand_to_mtd(nc);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
io_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -123,10 +122,10 @@ static int __init orion_nand_probe(struct platform_device *pdev)
|
|||
board = dev_get_platdata(&pdev->dev);
|
||||
}
|
||||
|
||||
mtd->priv = nc;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
nc->priv = board;
|
||||
nand_set_controller_data(nc, board);
|
||||
nand_set_flash_node(nc, pdev->dev.of_node);
|
||||
nc->IO_ADDR_R = nc->IO_ADDR_W = io_base;
|
||||
nc->cmd_ctrl = orion_nand_cmd_ctrl;
|
||||
nc->read_buf = orion_nand_read_buf;
|
||||
|
@ -161,9 +160,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
mtd->name = "orion_nand";
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
ret = mtd_device_parse_register(mtd, NULL, &ppdata,
|
||||
board->parts, board->nr_parts);
|
||||
ret = mtd_device_register(mtd, board->parts, board->nr_parts);
|
||||
if (ret) {
|
||||
nand_release(mtd);
|
||||
goto no_dev;
|
||||
|
|
|
@ -45,7 +45,7 @@ static const char driver_name[] = "pasemi-nand";
|
|||
|
||||
static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
while (len > 0x800) {
|
||||
memcpy_fromio(buf, chip->IO_ADDR_R, 0x800);
|
||||
|
@ -57,7 +57,7 @@ static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
|
||||
static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
while (len > 0x800) {
|
||||
memcpy_toio(chip->IO_ADDR_R, buf, 0x800);
|
||||
|
@ -70,7 +70,7 @@ static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
static void pasemi_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 (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
@ -110,20 +110,17 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
|
|||
pr_debug("pasemi_nand at %pR\n", &res);
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!pasemi_nand_mtd) {
|
||||
chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!chip) {
|
||||
printk(KERN_WARNING
|
||||
"Unable to allocate PASEMI NAND MTD device structure\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
chip = (struct nand_chip *)&pasemi_nand_mtd[1];
|
||||
pasemi_nand_mtd = nand_to_mtd(chip);
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
pasemi_nand_mtd->priv = chip;
|
||||
pasemi_nand_mtd->dev.parent = &ofdev->dev;
|
||||
|
||||
chip->IO_ADDR_R = of_iomap(np, 0);
|
||||
|
@ -180,7 +177,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
|
|||
out_ior:
|
||||
iounmap(chip->IO_ADDR_R);
|
||||
out_mtd:
|
||||
kfree(pasemi_nand_mtd);
|
||||
kfree(chip);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -192,7 +189,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev)
|
|||
if (!pasemi_nand_mtd)
|
||||
return 0;
|
||||
|
||||
chip = pasemi_nand_mtd->priv;
|
||||
chip = mtd_to_nand(pasemi_nand_mtd);
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release(pasemi_nand_mtd);
|
||||
|
@ -202,7 +199,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev)
|
|||
iounmap(chip->IO_ADDR_R);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree(pasemi_nand_mtd);
|
||||
kfree(chip);
|
||||
|
||||
pasemi_nand_mtd = NULL;
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
struct plat_nand_data {
|
||||
struct nand_chip chip;
|
||||
struct mtd_info mtd;
|
||||
void __iomem *io_base;
|
||||
};
|
||||
|
||||
|
@ -30,8 +29,8 @@ struct plat_nand_data {
|
|||
static int plat_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct plat_nand_data *data;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
const char **part_types;
|
||||
int err = 0;
|
||||
|
@ -57,9 +56,9 @@ static int plat_nand_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(data->io_base))
|
||||
return PTR_ERR(data->io_base);
|
||||
|
||||
data->chip.priv = &data;
|
||||
data->mtd.priv = &data->chip;
|
||||
data->mtd.dev.parent = &pdev->dev;
|
||||
nand_set_flash_node(&data->chip, pdev->dev.of_node);
|
||||
mtd = nand_to_mtd(&data->chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
data->chip.IO_ADDR_R = data->io_base;
|
||||
data->chip.IO_ADDR_W = data->io_base;
|
||||
|
@ -87,22 +86,21 @@ static int plat_nand_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
|
||||
if (nand_scan(mtd, pdata->chip.nr_chips)) {
|
||||
err = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
part_types = pdata->chip.part_probe_types;
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
err = mtd_device_parse_register(&data->mtd, part_types, &ppdata,
|
||||
err = mtd_device_parse_register(mtd, part_types, NULL,
|
||||
pdata->chip.partitions,
|
||||
pdata->chip.nr_partitions);
|
||||
|
||||
if (!err)
|
||||
return err;
|
||||
|
||||
nand_release(&data->mtd);
|
||||
nand_release(mtd);
|
||||
out:
|
||||
if (pdata->ctrl.remove)
|
||||
pdata->ctrl.remove(pdev);
|
||||
|
@ -117,7 +115,7 @@ static int plat_nand_remove(struct platform_device *pdev)
|
|||
struct plat_nand_data *data = platform_get_drvdata(pdev);
|
||||
struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
nand_release(&data->mtd);
|
||||
nand_release(nand_to_mtd(&data->chip));
|
||||
if (pdata->ctrl.remove)
|
||||
pdata->ctrl.remove(pdev);
|
||||
|
||||
|
|
|
@ -30,11 +30,6 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_mtd.h>
|
||||
|
||||
#if defined(CONFIG_ARM) && (defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP))
|
||||
#define ARCH_HAS_DMA
|
||||
#endif
|
||||
|
||||
#include <linux/platform_data/mtd-nand-pxa3xx.h>
|
||||
|
||||
#define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200)
|
||||
|
@ -172,7 +167,6 @@ enum pxa3xx_nand_variant {
|
|||
|
||||
struct pxa3xx_nand_host {
|
||||
struct nand_chip chip;
|
||||
struct mtd_info *mtd;
|
||||
void *info_data;
|
||||
|
||||
/* page size of attached chip */
|
||||
|
@ -455,14 +449,15 @@ static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host,
|
|||
struct nand_chip *chip = &host->chip;
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
const struct pxa3xx_nand_flash *f = NULL;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
||||
int i, id, ntypes;
|
||||
|
||||
ntypes = ARRAY_SIZE(builtin_flash_types);
|
||||
|
||||
chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
|
||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
||||
|
||||
id = chip->read_byte(host->mtd);
|
||||
id |= chip->read_byte(host->mtd) << 0x8;
|
||||
id = chip->read_byte(mtd);
|
||||
id |= chip->read_byte(mtd) << 0x8;
|
||||
|
||||
for (i = 0; i < ntypes; i++) {
|
||||
f = &builtin_flash_types[i];
|
||||
|
@ -895,7 +890,7 @@ static void set_command_address(struct pxa3xx_nand_info *info,
|
|||
static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = info->host[info->cs];
|
||||
struct mtd_info *mtd = host->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
||||
|
||||
/* reset data and oob column point to handle data */
|
||||
info->buf_start = 0;
|
||||
|
@ -948,7 +943,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
|
|||
struct mtd_info *mtd;
|
||||
|
||||
host = info->host[info->cs];
|
||||
mtd = host->mtd;
|
||||
mtd = nand_to_mtd(&host->chip);
|
||||
addr_cycle = 0;
|
||||
exec_cmd = 1;
|
||||
|
||||
|
@ -1118,7 +1113,8 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
|
|||
static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
int exec_cmd;
|
||||
|
||||
|
@ -1166,7 +1162,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
|
|||
const unsigned command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
int exec_cmd, ext_cmd_type;
|
||||
|
||||
|
@ -1286,7 +1283,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
|
|||
struct nand_chip *chip, uint8_t *buf, int oob_required,
|
||||
int page)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
|
||||
chip->read_buf(mtd, buf, mtd->writesize);
|
||||
|
@ -1312,7 +1309,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
|
|||
|
||||
static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
char retval = 0xFF;
|
||||
|
||||
|
@ -1325,7 +1323,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
|
|||
|
||||
static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
u16 retval = 0xFFFF;
|
||||
|
||||
|
@ -1338,7 +1337,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
|
|||
|
||||
static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
|
||||
|
||||
|
@ -1349,7 +1349,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
|
||||
|
||||
|
@ -1364,7 +1365,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
|
|||
|
||||
static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
|
||||
if (info->need_wait) {
|
||||
|
@ -1387,37 +1389,53 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
|
|||
return NAND_STATUS_READY;
|
||||
}
|
||||
|
||||
static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
|
||||
static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = info->host[info->cs];
|
||||
struct platform_device *pdev = info->pdev;
|
||||
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct pxa3xx_nand_host *host = info->host[info->cs];
|
||||
struct mtd_info *mtd = host->mtd;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
const struct nand_sdr_timings *timings;
|
||||
|
||||
/* configure default flash values */
|
||||
/* Configure default flash values */
|
||||
info->chunk_size = PAGE_CHUNK_SIZE;
|
||||
info->reg_ndcr = 0x0; /* enable all interrupts */
|
||||
info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
|
||||
info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
|
||||
info->reg_ndcr |= NDCR_SPARE_EN; /* enable spare by default */
|
||||
info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
|
||||
info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
|
||||
info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
|
||||
info->reg_ndcr |= NDCR_SPARE_EN;
|
||||
|
||||
/* use the common timing to make a try */
|
||||
timings = onfi_async_timing_mode_to_sdr_timings(0);
|
||||
if (IS_ERR(timings))
|
||||
return PTR_ERR(timings);
|
||||
|
||||
pxa3xx_nand_set_sdr_timing(host, timings);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
|
||||
static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = info->host[info->cs];
|
||||
struct nand_chip *chip = &host->chip;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
|
||||
info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
|
||||
info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
|
||||
info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
|
||||
}
|
||||
|
||||
static void pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
|
||||
{
|
||||
struct platform_device *pdev = info->pdev;
|
||||
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
uint32_t ndcr = nand_readl(info, NDCR);
|
||||
|
||||
/* Set an initial chunk size */
|
||||
info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
|
||||
info->reg_ndcr = ndcr &
|
||||
~(NDCR_INT_MASK | NDCR_ND_ARB_EN | NFCV1_NDCR_ARB_CNTL);
|
||||
info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
|
||||
info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
|
||||
info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
|
||||
|
@ -1483,32 +1501,6 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
|
|||
kfree(info->data_buff);
|
||||
}
|
||||
|
||||
static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
|
||||
{
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *chip;
|
||||
const struct nand_sdr_timings *timings;
|
||||
int ret;
|
||||
|
||||
mtd = info->host[info->cs]->mtd;
|
||||
chip = mtd->priv;
|
||||
|
||||
/* use the common timing to make a try */
|
||||
timings = onfi_async_timing_mode_to_sdr_timings(0);
|
||||
if (IS_ERR(timings))
|
||||
return PTR_ERR(timings);
|
||||
|
||||
pxa3xx_nand_set_sdr_timing(host, timings);
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
|
||||
ret = chip->waitfunc(mtd, chip);
|
||||
if (ret & NAND_STATUS_FAIL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa_ecc_init(struct pxa3xx_nand_info *info,
|
||||
struct nand_ecc_ctrl *ecc,
|
||||
int strength, int ecc_stepsize, int page_size)
|
||||
|
@ -1580,34 +1572,22 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
|
|||
|
||||
static int pxa3xx_nand_scan(struct mtd_info *mtd)
|
||||
{
|
||||
struct pxa3xx_nand_host *host = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
|
||||
struct pxa3xx_nand_info *info = host->info_data;
|
||||
struct platform_device *pdev = info->pdev;
|
||||
struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
int ret;
|
||||
uint16_t ecc_strength, ecc_step;
|
||||
|
||||
if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
|
||||
goto KEEP_CONFIG;
|
||||
|
||||
/* Set a default chunk size */
|
||||
info->chunk_size = 512;
|
||||
|
||||
ret = pxa3xx_nand_config_flash(info);
|
||||
if (pdata->keep_config) {
|
||||
pxa3xx_nand_detect_config(info);
|
||||
} else {
|
||||
ret = pxa3xx_nand_config_ident(info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pxa3xx_nand_sensing(host);
|
||||
if (ret) {
|
||||
dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
|
||||
info->cs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
KEEP_CONFIG:
|
||||
info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
|
||||
if (info->reg_ndcr & NDCR_DWIDTH_M)
|
||||
chip->options |= NAND_BUSWIDTH_16;
|
||||
|
||||
|
@ -1692,11 +1672,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
|
|||
host->row_addr_cycles = 3;
|
||||
else
|
||||
host->row_addr_cycles = 2;
|
||||
|
||||
if (!pdata->keep_config)
|
||||
pxa3xx_nand_config_tail(info);
|
||||
|
||||
return nand_scan_tail(mtd);
|
||||
}
|
||||
|
||||
static int alloc_nand_resource(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct pxa3xx_nand_platform_data *pdata;
|
||||
struct pxa3xx_nand_info *info;
|
||||
struct pxa3xx_nand_host *host;
|
||||
|
@ -1708,24 +1693,27 @@ static int alloc_nand_resource(struct platform_device *pdev)
|
|||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (pdata->num_cs <= 0)
|
||||
return -ENODEV;
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info) + (sizeof(*mtd) +
|
||||
sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
|
||||
info = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*info) + sizeof(*host) * pdata->num_cs,
|
||||
GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
info->pdev = pdev;
|
||||
info->variant = pxa3xx_nand_get_variant(pdev);
|
||||
for (cs = 0; cs < pdata->num_cs; cs++) {
|
||||
mtd = (void *)&info[1] + (sizeof(*mtd) + sizeof(*host)) * cs;
|
||||
chip = (struct nand_chip *)(&mtd[1]);
|
||||
host = (struct pxa3xx_nand_host *)chip;
|
||||
host = (void *)&info[1] + sizeof(*host) * cs;
|
||||
chip = &host->chip;
|
||||
nand_set_controller_data(chip, host);
|
||||
mtd = nand_to_mtd(chip);
|
||||
info->host[cs] = host;
|
||||
host->mtd = mtd;
|
||||
host->cs = cs;
|
||||
host->info_data = info;
|
||||
mtd->priv = host;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
/* FIXME: all chips use the same device tree partitions */
|
||||
nand_set_flash_node(chip, np);
|
||||
|
||||
nand_set_controller_data(chip, host);
|
||||
chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
|
||||
chip->ecc.write_page = pxa3xx_nand_write_page_hwecc;
|
||||
chip->controller = &info->controller;
|
||||
|
@ -1845,7 +1833,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
|
|||
clk_disable_unprepare(info->clk);
|
||||
|
||||
for (cs = 0; cs < pdata->num_cs; cs++)
|
||||
nand_release(info->host[cs]->mtd);
|
||||
nand_release(nand_to_mtd(&info->host[cs]->chip));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1886,7 +1874,6 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
|
|||
static int pxa3xx_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pxa3xx_nand_platform_data *pdata;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
struct pxa3xx_nand_info *info;
|
||||
int ret, cs, probe_success, dma_available;
|
||||
|
||||
|
@ -1917,7 +1904,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
|
|||
info = platform_get_drvdata(pdev);
|
||||
probe_success = 0;
|
||||
for (cs = 0; cs < pdata->num_cs; cs++) {
|
||||
struct mtd_info *mtd = info->host[cs]->mtd;
|
||||
struct mtd_info *mtd = nand_to_mtd(&info->host[cs]->chip);
|
||||
|
||||
/*
|
||||
* The mtd name matches the one used in 'mtdparts' kernel
|
||||
|
@ -1933,9 +1920,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
|
|||
continue;
|
||||
}
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
ret = mtd_device_parse_register(mtd, NULL,
|
||||
&ppdata, pdata->parts[cs],
|
||||
ret = mtd_device_register(mtd, pdata->parts[cs],
|
||||
pdata->nr_parts[cs]);
|
||||
if (!ret)
|
||||
probe_success = 1;
|
||||
|
@ -1959,12 +1944,18 @@ static int pxa3xx_nand_suspend(struct device *dev)
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
clk_disable(info->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa3xx_nand_resume(struct device *dev)
|
||||
{
|
||||
struct pxa3xx_nand_info *info = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(info->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* We don't want to handle interrupt without calling mtd routine */
|
||||
disable_int(info, NDCR_INT_MASK);
|
||||
|
|
|
@ -64,8 +64,8 @@ static inline void r852_write_reg_dword(struct r852_device *dev,
|
|||
/* returns pointer to our private structure */
|
||||
static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
return chip->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
return nand_get_controller_data(chip);
|
||||
}
|
||||
|
||||
|
||||
|
@ -361,7 +361,7 @@ static void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl)
|
|||
*/
|
||||
static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||
{
|
||||
struct r852_device *dev = chip->priv;
|
||||
struct r852_device *dev = nand_get_controller_data(chip);
|
||||
|
||||
unsigned long timeout;
|
||||
int status;
|
||||
|
@ -477,7 +477,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
|
|||
|
||||
if (dev->dma_error) {
|
||||
dev->dma_error = 0;
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS);
|
||||
|
@ -491,7 +491,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
|
|||
/* ecc uncorrectable error */
|
||||
if (ecc_status & R852_ECC_FAIL) {
|
||||
dbg("ecc: unrecoverable error, in half %d", i);
|
||||
error = -1;
|
||||
error = -EBADMSG;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -634,25 +634,21 @@ static void r852_update_media_status(struct r852_device *dev)
|
|||
*/
|
||||
static int r852_register_nand_device(struct r852_device *dev)
|
||||
{
|
||||
dev->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
|
||||
|
||||
if (!dev->mtd)
|
||||
goto error1;
|
||||
struct mtd_info *mtd = nand_to_mtd(dev->chip);
|
||||
|
||||
WARN_ON(dev->card_registred);
|
||||
|
||||
dev->mtd->priv = dev->chip;
|
||||
dev->mtd->dev.parent = &dev->pci_dev->dev;
|
||||
mtd->dev.parent = &dev->pci_dev->dev;
|
||||
|
||||
if (dev->readonly)
|
||||
dev->chip->options |= NAND_ROM;
|
||||
|
||||
r852_engine_enable(dev);
|
||||
|
||||
if (sm_register_device(dev->mtd, dev->sm))
|
||||
goto error2;
|
||||
if (sm_register_device(mtd, dev->sm))
|
||||
goto error1;
|
||||
|
||||
if (device_create_file(&dev->mtd->dev, &dev_attr_media_type)) {
|
||||
if (device_create_file(&mtd->dev, &dev_attr_media_type)) {
|
||||
message("can't create media type sysfs attribute");
|
||||
goto error3;
|
||||
}
|
||||
|
@ -660,9 +656,7 @@ static int r852_register_nand_device(struct r852_device *dev)
|
|||
dev->card_registred = 1;
|
||||
return 0;
|
||||
error3:
|
||||
nand_release(dev->mtd);
|
||||
error2:
|
||||
kfree(dev->mtd);
|
||||
nand_release(mtd);
|
||||
error1:
|
||||
/* Force card redetect */
|
||||
dev->card_detected = 0;
|
||||
|
@ -675,15 +669,15 @@ static int r852_register_nand_device(struct r852_device *dev)
|
|||
|
||||
static void r852_unregister_nand_device(struct r852_device *dev)
|
||||
{
|
||||
struct mtd_info *mtd = nand_to_mtd(dev->chip);
|
||||
|
||||
if (!dev->card_registred)
|
||||
return;
|
||||
|
||||
device_remove_file(&dev->mtd->dev, &dev_attr_media_type);
|
||||
nand_release(dev->mtd);
|
||||
device_remove_file(&mtd->dev, &dev_attr_media_type);
|
||||
nand_release(mtd);
|
||||
r852_engine_disable(dev);
|
||||
dev->card_registred = 0;
|
||||
kfree(dev->mtd);
|
||||
dev->mtd = NULL;
|
||||
}
|
||||
|
||||
/* Card state updater */
|
||||
|
@ -885,7 +879,7 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
|
|||
if (!dev)
|
||||
goto error5;
|
||||
|
||||
chip->priv = dev;
|
||||
nand_set_controller_data(chip, dev);
|
||||
dev->chip = chip;
|
||||
dev->pci_dev = pci_dev;
|
||||
pci_set_drvdata(pci_dev, dev);
|
||||
|
@ -980,7 +974,6 @@ static void r852_remove(struct pci_dev *pci_dev)
|
|||
|
||||
/* Stop interrupts */
|
||||
r852_disable_irqs(dev);
|
||||
synchronize_irq(dev->irq);
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
/* Cleanup */
|
||||
|
@ -1032,6 +1025,7 @@ static int r852_suspend(struct device *device)
|
|||
static int r852_resume(struct device *device)
|
||||
{
|
||||
struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
|
||||
struct mtd_info *mtd = nand_to_mtd(dev->chip);
|
||||
|
||||
r852_disable_irqs(dev);
|
||||
r852_card_update_present(dev);
|
||||
|
@ -1051,9 +1045,9 @@ static int r852_resume(struct device *device)
|
|||
/* Otherwise, initialize the card */
|
||||
if (dev->card_registred) {
|
||||
r852_engine_enable(dev);
|
||||
dev->chip->select_chip(dev->mtd, 0);
|
||||
dev->chip->cmdfunc(dev->mtd, NAND_CMD_RESET, -1, -1);
|
||||
dev->chip->select_chip(dev->mtd, -1);
|
||||
dev->chip->select_chip(mtd, 0);
|
||||
dev->chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
||||
dev->chip->select_chip(mtd, -1);
|
||||
}
|
||||
|
||||
/* Program card detection IRQ */
|
||||
|
|
|
@ -108,7 +108,6 @@
|
|||
|
||||
struct r852_device {
|
||||
void __iomem *mmio; /* mmio */
|
||||
struct mtd_info *mtd; /* mtd backpointer */
|
||||
struct nand_chip *chip; /* nand chip backpointer */
|
||||
struct pci_dev *pci_dev; /* pci backpointer */
|
||||
|
||||
|
|
|
@ -104,7 +104,6 @@ struct s3c2410_nand_info;
|
|||
* @scan_res: The result from calling nand_scan_ident().
|
||||
*/
|
||||
struct s3c2410_nand_mtd {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
struct s3c2410_nand_set *set;
|
||||
struct s3c2410_nand_info *info;
|
||||
|
@ -168,7 +167,8 @@ struct s3c2410_nand_info {
|
|||
|
||||
static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd, struct s3c2410_nand_mtd, mtd);
|
||||
return container_of(mtd_to_nand(mtd), struct s3c2410_nand_mtd,
|
||||
chip);
|
||||
}
|
||||
|
||||
static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd)
|
||||
|
@ -382,10 +382,10 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
|
|||
{
|
||||
struct s3c2410_nand_info *info;
|
||||
struct s3c2410_nand_mtd *nmtd;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
unsigned long cur;
|
||||
|
||||
nmtd = this->priv;
|
||||
nmtd = nand_get_controller_data(this);
|
||||
info = nmtd->info;
|
||||
|
||||
if (chip != -1)
|
||||
|
@ -634,7 +634,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
|
|||
|
||||
static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
readsb(this->IO_ADDR_R, buf, len);
|
||||
}
|
||||
|
||||
|
@ -656,7 +656,7 @@ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|||
static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
|
||||
int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd_to_nand(mtd);
|
||||
writesb(this->IO_ADDR_W, buf, len);
|
||||
}
|
||||
|
||||
|
@ -745,7 +745,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
|
|||
|
||||
for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
|
||||
pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
|
||||
nand_release(&ptr->mtd);
|
||||
nand_release(nand_to_mtd(&ptr->chip));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,9 +762,11 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
|
|||
struct s3c2410_nand_set *set)
|
||||
{
|
||||
if (set) {
|
||||
mtd->mtd.name = set->name;
|
||||
struct mtd_info *mtdinfo = nand_to_mtd(&mtd->chip);
|
||||
|
||||
return mtd_device_parse_register(&mtd->mtd, NULL, NULL,
|
||||
mtdinfo->name = set->name;
|
||||
|
||||
return mtd_device_parse_register(mtdinfo, NULL, NULL,
|
||||
set->partitions, set->nr_partitions);
|
||||
}
|
||||
|
||||
|
@ -792,7 +794,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
|
|||
chip->read_buf = s3c2410_nand_read_buf;
|
||||
chip->select_chip = s3c2410_nand_select_chip;
|
||||
chip->chip_delay = 50;
|
||||
chip->priv = nmtd;
|
||||
nand_set_controller_data(chip, nmtd);
|
||||
chip->options = set->options;
|
||||
chip->controller = &info->controller;
|
||||
|
||||
|
@ -831,7 +833,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
|
|||
chip->IO_ADDR_R = chip->IO_ADDR_W;
|
||||
|
||||
nmtd->info = info;
|
||||
nmtd->mtd.priv = chip;
|
||||
nmtd->set = set;
|
||||
|
||||
#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
|
||||
|
@ -1012,19 +1013,21 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
|
|||
nmtd = info->mtds;
|
||||
|
||||
for (setno = 0; setno < nr_sets; setno++, nmtd++) {
|
||||
struct mtd_info *mtd = nand_to_mtd(&nmtd->chip);
|
||||
|
||||
pr_debug("initialising set %d (%p, info %p)\n",
|
||||
setno, nmtd, info);
|
||||
|
||||
nmtd->mtd.dev.parent = &pdev->dev;
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
s3c2410_nand_init_chip(info, nmtd, sets);
|
||||
|
||||
nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
|
||||
nmtd->scan_res = nand_scan_ident(mtd,
|
||||
(sets) ? sets->nr_chips : 1,
|
||||
NULL);
|
||||
|
||||
if (nmtd->scan_res == 0) {
|
||||
s3c2410_nand_update_chip(info, nmtd);
|
||||
nand_scan_tail(&nmtd->mtd);
|
||||
nand_scan_tail(mtd);
|
||||
s3c2410_nand_add_partition(info, nmtd, sets);
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
|
|||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.direction = DMA_MEM_TO_DEV;
|
||||
cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl);
|
||||
cfg.dst_addr = flctl->fifo;
|
||||
cfg.src_addr = 0;
|
||||
ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg);
|
||||
if (ret < 0)
|
||||
|
@ -176,7 +176,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
|
|||
|
||||
cfg.direction = DMA_DEV_TO_MEM;
|
||||
cfg.dst_addr = 0;
|
||||
cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl);
|
||||
cfg.src_addr = flctl->fifo;
|
||||
ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
@ -607,13 +607,13 @@ static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
|
|||
case FL_REPAIRABLE:
|
||||
dev_info(&flctl->pdev->dev,
|
||||
"applied ecc on page 0x%x", page_addr);
|
||||
flctl->mtd.ecc_stats.corrected++;
|
||||
mtd->ecc_stats.corrected++;
|
||||
break;
|
||||
case FL_ERROR:
|
||||
dev_warn(&flctl->pdev->dev,
|
||||
"page 0x%x contains corrupted data\n",
|
||||
page_addr);
|
||||
flctl->mtd.ecc_stats.failed++;
|
||||
mtd->ecc_stats.failed++;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
|
@ -1086,7 +1086,6 @@ static int flctl_probe(struct platform_device *pdev)
|
|||
struct sh_flctl_platform_data *pdata;
|
||||
int ret;
|
||||
int irq;
|
||||
struct mtd_part_parser_data ppdata = {};
|
||||
|
||||
flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL);
|
||||
if (!flctl)
|
||||
|
@ -1096,6 +1095,7 @@ static int flctl_probe(struct platform_device *pdev)
|
|||
flctl->reg = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(flctl->reg))
|
||||
return PTR_ERR(flctl->reg);
|
||||
flctl->fifo = res->start + 0x24; /* FLDTFIFO */
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
|
@ -1121,9 +1121,9 @@ static int flctl_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
platform_set_drvdata(pdev, flctl);
|
||||
flctl_mtd = &flctl->mtd;
|
||||
nand = &flctl->chip;
|
||||
flctl_mtd->priv = nand;
|
||||
flctl_mtd = nand_to_mtd(nand);
|
||||
nand_set_flash_node(nand, pdev->dev.of_node);
|
||||
flctl_mtd->dev.parent = &pdev->dev;
|
||||
flctl->pdev = pdev;
|
||||
flctl->hwecc = pdata->has_hwecc;
|
||||
|
@ -1163,9 +1163,7 @@ static int flctl_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_chip;
|
||||
|
||||
ppdata.of_node = pdev->dev.of_node;
|
||||
ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
|
||||
pdata->nr_parts);
|
||||
ret = mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1180,7 +1178,7 @@ static int flctl_remove(struct platform_device *pdev)
|
|||
struct sh_flctl *flctl = platform_get_drvdata(pdev);
|
||||
|
||||
flctl_release_dma(flctl);
|
||||
nand_release(&flctl->mtd);
|
||||
nand_release(nand_to_mtd(&flctl->chip));
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,13 +29,15 @@
|
|||
#include <asm/mach-types.h>
|
||||
|
||||
struct sharpsl_nand {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip chip;
|
||||
|
||||
void __iomem *io;
|
||||
};
|
||||
|
||||
#define mtd_to_sharpsl(_mtd) container_of(_mtd, struct sharpsl_nand, mtd)
|
||||
static inline struct sharpsl_nand *mtd_to_sharpsl(struct mtd_info *mtd)
|
||||
{
|
||||
return container_of(mtd_to_nand(mtd), struct sharpsl_nand, chip);
|
||||
}
|
||||
|
||||
/* register offset */
|
||||
#define ECCLPLB 0x00 /* line parity 7 - 0 bit */
|
||||
|
@ -66,7 +68,7 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
|
|||
unsigned int ctrl)
|
||||
{
|
||||
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned char bits = ctrl & 0x07;
|
||||
|
@ -109,6 +111,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
|
|||
static int sharpsl_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *r;
|
||||
int err = 0;
|
||||
struct sharpsl_nand *sharpsl;
|
||||
|
@ -143,8 +146,8 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
|
|||
this = (struct nand_chip *)(&sharpsl->chip);
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
sharpsl->mtd.priv = this;
|
||||
sharpsl->mtd.dev.parent = &pdev->dev;
|
||||
mtd = nand_to_mtd(this);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, sharpsl);
|
||||
|
||||
|
@ -173,14 +176,14 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
|
|||
this->ecc.correct = nand_correct_data;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
err = nand_scan(&sharpsl->mtd, 1);
|
||||
err = nand_scan(mtd, 1);
|
||||
if (err)
|
||||
goto err_scan;
|
||||
|
||||
/* Register the partitions */
|
||||
sharpsl->mtd.name = "sharpsl-nand";
|
||||
mtd->name = "sharpsl-nand";
|
||||
|
||||
err = mtd_device_parse_register(&sharpsl->mtd, NULL, NULL,
|
||||
err = mtd_device_parse_register(mtd, NULL, NULL,
|
||||
data->partitions, data->nr_partitions);
|
||||
if (err)
|
||||
goto err_add;
|
||||
|
@ -189,7 +192,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_add:
|
||||
nand_release(&sharpsl->mtd);
|
||||
nand_release(mtd);
|
||||
|
||||
err_scan:
|
||||
iounmap(sharpsl->io);
|
||||
|
@ -207,7 +210,7 @@ static int sharpsl_nand_remove(struct platform_device *pdev)
|
|||
struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release(&sharpsl->mtd);
|
||||
nand_release(nand_to_mtd(&sharpsl->chip));
|
||||
|
||||
iounmap(sharpsl->io);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue