Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1191812 > unrolled thread
| Started by | Stefan Agner <stefan@agner.ch> |
|---|---|
| First post | 2015-07-24 15:20 +0200 |
| Last post | 2015-07-24 15:20 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v7 0/5] mtd: nand: vf610_nfc: Freescale NFC for VF610 Stefan Agner <stefan@agner.ch> - 2015-07-24 15:20 +0200
[PATCH v7 5/5] ARM: dts: vf-colibri: enable NAND flash controller Stefan Agner <stefan@agner.ch> - 2015-07-24 15:20 +0200
[PATCH v7 4/5] ARM: dts: vf610twr: add NAND flash controller peripherial Stefan Agner <stefan@agner.ch> - 2015-07-24 15:20 +0200
Re: [PATCH v7 4/5] ARM: dts: vf610twr: add NAND flash controller peripherial Shawn Guo <shawnguo@kernel.org> - 2015-07-25 05:40 +0200
[PATCH v7 3/5] mtd: nand: vf610_nfc: add device tree bindings Stefan Agner <stefan@agner.ch> - 2015-07-24 15:20 +0200
[PATCH v7 2/5] mtd: nand: vf610_nfc: add hardware BCH-ECC support Stefan Agner <stefan@agner.ch> - 2015-07-24 15:20 +0200
| From | Stefan Agner <stefan@agner.ch> |
|---|---|
| Date | 2015-07-24 15:20 +0200 |
| Subject | [PATCH v7 0/5] mtd: nand: vf610_nfc: Freescale NFC for VF610 |
| Message-ID | <pPL3j-6PY-7@gated-at.bofh.it> |
This seventh revision simplifies the config symbols somewhat, but is otherwise just a rebase version on current l2-mtd/master. I reran the MTD tests, they still all succeed. Some more information and the full test log can be found in the cover letter of the last revision v6: http://thread.gmane.org/gmane.linux.kernel/1979868 Changes since v6: - Rebased ontop of l2-mtd/master (v4.2-rc1 based) - Removed HAVE_NAND_VF610_NFC and use depends on. This made "[PATCH v6 4/6] ARM: vf610: enable NAND Flash Controller" unnecessary Changes since v5: - Removed fsl,mpc5125-nfc compatible string - Removed readl/writel_relaxed - Change interface of vf610_nfc_transfer_size to match other accessors Changes since v4: - Rebased ontop of l2-mtd/master (v4.1-rc4 based) - Eliminate unnecessary page read (NAND_CMD_SEQIN) since the driver does not support sub-page writes anyway (improves write performance) - Support ONFI by enabling READID command with offset and parameter page reads (CMD_PARAM) - Change to dedicated read_page/write_page function, enables raw writes - Use __LITTLE_ENDIAN to distingush between LE/BE relevant statements - Eliminated vf610_nfc_probe_dt in favor of common DT init code - Use wait_for_completion_timeout - Some style fixes (spaces, etc.) Changes since v3: - Make the driver selectable when COMPILE_TEST is set - Fix compile error due to superfluous ECC_STATUS configuration in initial patch (without ECC correction ECC_STATUS does not need to be configured) - Remove custom BBT pattern and switch to in-band BBT in the initial patch - Include two bug fixes, for details see the corresponding U-Boot patches: http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/215802 Changes since v2: - Updated binding documentation Changes since v1: - Nest nfc_config struct within the main nfc struct - Use assigned clock binding to specify NFC clock - Rebased ontop of MSCM IR patchset (driver parts have been merged) - Split out arch Kconfig in a separate config - Fix module license - Updated MAINTAINERS Changes since RFC (Bill Pringlemeir): - Renamed driver from fsl_nfc to vf610_nfc - Use readl/writel for all register in accessor functions - Optimized field accessor functions - Implemented PM (suspend/resume) functions - Implemented basic support for ECC strength/ECC step size from dt - Improved performance of count_written_bits by using hweight32 - Support ECC with 60-bytes to correct up to 32 bit errors - Changed to in-band BBT (NAND_BBT_NO_OOB) which also allows ECC modes which uses up to 60 bytes on 64 byte OOB - Removed custom (downstream) BBT pattern since BBT table won't be compatible anyway (due to the change above) Stefan Agner (5): mtd: nand: vf610_nfc: Freescale NFC for VF610, MPC5125 and others mtd: nand: vf610_nfc: add hardware BCH-ECC support mtd: nand: vf610_nfc: add device tree bindings ARM: dts: vf610twr: add NAND flash controller peripherial ARM: dts: vf-colibri: enable NAND flash controller .../devicetree/bindings/mtd/vf610-nfc.txt | 45 ++ MAINTAINERS | 6 + arch/arm/boot/dts/vf-colibri.dtsi | 32 + arch/arm/boot/dts/vf610-twr.dts | 44 ++ arch/arm/boot/dts/vfxxx.dtsi | 8 + drivers/mtd/nand/Kconfig | 11 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/vf610_nfc.c | 839 +++++++++++++++++++++ 8 files changed, 986 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/vf610-nfc.txt create mode 100644 drivers/mtd/nand/vf610_nfc.c -- 2.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Stefan Agner <stefan@agner.ch> |
|---|---|
| Date | 2015-07-24 15:20 +0200 |
| Subject | [PATCH v7 5/5] ARM: dts: vf-colibri: enable NAND flash controller |
| Message-ID | <pPL3j-6PY-9@gated-at.bofh.it> |
| In reply to | #1191812 |
Enable NAND access by adding pinmux and NAND flash controller node
to device tree. The NAND chips currently used on the Colibri VF61
requires 8-bit ECC per 512 byte page, hence specify 32-bit ECC
strength per 2k page size.
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
arch/arm/boot/dts/vf-colibri.dtsi | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi
index 68ca125..8d7986a 100644
--- a/arch/arm/boot/dts/vf-colibri.dtsi
+++ b/arch/arm/boot/dts/vf-colibri.dtsi
@@ -52,6 +52,19 @@
pinctrl-0 = <&pinctrl_i2c0>;
};
+&nfc {
+ assigned-clocks = <&clks VF610_CLK_NFC>;
+ assigned-clock-rates = <33000000>;
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-ecc-step-size = <2048>;
+ nand-ecc-strength = <32>;
+ nand-on-flash-bbt;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nfc_1>;
+ status = "okay";
+};
+
&pwm0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm0>;
@@ -156,6 +169,25 @@
>;
};
+ pinctrl_nfc_1: nfcgrp_1 {
+ fsl,pins = <
+ VF610_PAD_PTD23__NF_IO7 0x28df
+ VF610_PAD_PTD22__NF_IO6 0x28df
+ VF610_PAD_PTD21__NF_IO5 0x28df
+ VF610_PAD_PTD20__NF_IO4 0x28df
+ VF610_PAD_PTD19__NF_IO3 0x28df
+ VF610_PAD_PTD18__NF_IO2 0x28df
+ VF610_PAD_PTD17__NF_IO1 0x28df
+ VF610_PAD_PTD16__NF_IO0 0x28df
+ VF610_PAD_PTB24__NF_WE_B 0x28c2
+ VF610_PAD_PTB25__NF_CE0_B 0x28c2
+ VF610_PAD_PTB27__NF_RE_B 0x28c2
+ VF610_PAD_PTC26__NF_RB_B 0x283d
+ VF610_PAD_PTC27__NF_ALE 0x28c2
+ VF610_PAD_PTC28__NF_CLE 0x28c2
+ >;
+ };
+
pinctrl_pwm0: pwm0grp {
fsl,pins = <
VF610_PAD_PTB0__FTM0_CH0 0x1182
--
2.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Stefan Agner <stefan@agner.ch> |
|---|---|
| Date | 2015-07-24 15:20 +0200 |
| Subject | [PATCH v7 4/5] ARM: dts: vf610twr: add NAND flash controller peripherial |
| Message-ID | <pPL3k-6PY-23@gated-at.bofh.it> |
| In reply to | #1191812 |
This adds the NAND flash controller (NFC) peripherial. The driver
supports the SLC NAND chips found on Freescale's Vybrid Tower System
Module. The Micron NAND chip on the module needs 4-bit ECC per 512
byte page. Use 24-bit ECC per 2k page, which is supported by the
driver.
Signed-off-by: Bill Pringlemeir <bpringlemeir@nbsps.com>
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
arch/arm/boot/dts/vf610-twr.dts | 44 +++++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/vfxxx.dtsi | 8 ++++++++
2 files changed, 52 insertions(+)
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 375ab23..0b2b932 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -287,6 +287,50 @@
status = "okay";
};
+&iomuxc {
+ vf610-twr {
+ pinctrl_nfc_1: nfcgrp_1 {
+ fsl,pins = <
+ VF610_PAD_PTD31__NF_IO15 0x28df
+ VF610_PAD_PTD30__NF_IO14 0x28df
+ VF610_PAD_PTD29__NF_IO13 0x28df
+ VF610_PAD_PTD28__NF_IO12 0x28df
+ VF610_PAD_PTD27__NF_IO11 0x28df
+ VF610_PAD_PTD26__NF_IO10 0x28df
+ VF610_PAD_PTD25__NF_IO9 0x28df
+ VF610_PAD_PTD24__NF_IO8 0x28df
+ VF610_PAD_PTD23__NF_IO7 0x28df
+ VF610_PAD_PTD22__NF_IO6 0x28df
+ VF610_PAD_PTD21__NF_IO5 0x28df
+ VF610_PAD_PTD20__NF_IO4 0x28df
+ VF610_PAD_PTD19__NF_IO3 0x28df
+ VF610_PAD_PTD18__NF_IO2 0x28df
+ VF610_PAD_PTD17__NF_IO1 0x28df
+ VF610_PAD_PTD16__NF_IO0 0x28df
+ VF610_PAD_PTB24__NF_WE_B 0x28c2
+ VF610_PAD_PTB25__NF_CE0_B 0x28c2
+ VF610_PAD_PTB27__NF_RE_B 0x28c2
+ VF610_PAD_PTC26__NF_RB_B 0x283d
+ VF610_PAD_PTC27__NF_ALE 0x28c2
+ VF610_PAD_PTC28__NF_CLE 0x28c2
+ >;
+ };
+ };
+};
+
+&nfc {
+ assigned-clocks = <&clks VF610_CLK_NFC>;
+ assigned-clock-rates = <33000000>;
+ nand-bus-width = <16>;
+ nand-ecc-mode = "hw";
+ nand-ecc-step-size = <2048>;
+ nand-ecc-strength = <24>;
+ nand-on-flash-bbt;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nfc_1>;
+ status = "okay";
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 4aa3351..2f4b04d 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -520,6 +520,14 @@
status = "disabled";
};
+ nfc: nand@400e0000 {
+ compatible = "fsl,vf610-nfc";
+ reg = <0x400e0000 0x4000>;
+ interrupts = <83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks VF610_CLK_NFC>;
+ clock-names = "nfc";
+ status = "disabled";
+ };
};
};
};
--
2.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Shawn Guo <shawnguo@kernel.org> |
|---|---|
| Date | 2015-07-25 05:40 +0200 |
| Subject | Re: [PATCH v7 4/5] ARM: dts: vf610twr: add NAND flash controller peripherial |
| Message-ID | <pPYtA-Yy-7@gated-at.bofh.it> |
| In reply to | #1191817 |
On Fri, Jul 24, 2015 at 03:16:23PM +0200, Stefan Agner wrote:
> This adds the NAND flash controller (NFC) peripherial. The driver
> supports the SLC NAND chips found on Freescale's Vybrid Tower System
> Module. The Micron NAND chip on the module needs 4-bit ECC per 512
> byte page. Use 24-bit ECC per 2k page, which is supported by the
> driver.
>
> Signed-off-by: Bill Pringlemeir <bpringlemeir@nbsps.com>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
> arch/arm/boot/dts/vf610-twr.dts | 44 +++++++++++++++++++++++++++++++++++++++++
> arch/arm/boot/dts/vfxxx.dtsi | 8 ++++++++
> 2 files changed, 52 insertions(+)
>
> diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
> index 375ab23..0b2b932 100644
> --- a/arch/arm/boot/dts/vf610-twr.dts
> +++ b/arch/arm/boot/dts/vf610-twr.dts
> @@ -287,6 +287,50 @@
> status = "okay";
> };
>
> +&iomuxc {
> + vf610-twr {
> + pinctrl_nfc_1: nfcgrp_1 {
The suffix "_1" is meaningless. Please drop it here as well as patch
#5.
Shawn
> + fsl,pins = <
> + VF610_PAD_PTD31__NF_IO15 0x28df
> + VF610_PAD_PTD30__NF_IO14 0x28df
> + VF610_PAD_PTD29__NF_IO13 0x28df
> + VF610_PAD_PTD28__NF_IO12 0x28df
> + VF610_PAD_PTD27__NF_IO11 0x28df
> + VF610_PAD_PTD26__NF_IO10 0x28df
> + VF610_PAD_PTD25__NF_IO9 0x28df
> + VF610_PAD_PTD24__NF_IO8 0x28df
> + VF610_PAD_PTD23__NF_IO7 0x28df
> + VF610_PAD_PTD22__NF_IO6 0x28df
> + VF610_PAD_PTD21__NF_IO5 0x28df
> + VF610_PAD_PTD20__NF_IO4 0x28df
> + VF610_PAD_PTD19__NF_IO3 0x28df
> + VF610_PAD_PTD18__NF_IO2 0x28df
> + VF610_PAD_PTD17__NF_IO1 0x28df
> + VF610_PAD_PTD16__NF_IO0 0x28df
> + VF610_PAD_PTB24__NF_WE_B 0x28c2
> + VF610_PAD_PTB25__NF_CE0_B 0x28c2
> + VF610_PAD_PTB27__NF_RE_B 0x28c2
> + VF610_PAD_PTC26__NF_RB_B 0x283d
> + VF610_PAD_PTC27__NF_ALE 0x28c2
> + VF610_PAD_PTC28__NF_CLE 0x28c2
> + >;
> + };
> + };
> +};
> +
> +&nfc {
> + assigned-clocks = <&clks VF610_CLK_NFC>;
> + assigned-clock-rates = <33000000>;
> + nand-bus-width = <16>;
> + nand-ecc-mode = "hw";
> + nand-ecc-step-size = <2048>;
> + nand-ecc-strength = <24>;
> + nand-on-flash-bbt;
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_nfc_1>;
> + status = "okay";
> +};
> +
> &uart1 {
> pinctrl-names = "default";
> pinctrl-0 = <&pinctrl_uart1>;
> diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
> index 4aa3351..2f4b04d 100644
> --- a/arch/arm/boot/dts/vfxxx.dtsi
> +++ b/arch/arm/boot/dts/vfxxx.dtsi
> @@ -520,6 +520,14 @@
> status = "disabled";
> };
>
> + nfc: nand@400e0000 {
> + compatible = "fsl,vf610-nfc";
> + reg = <0x400e0000 0x4000>;
> + interrupts = <83 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clks VF610_CLK_NFC>;
> + clock-names = "nfc";
> + status = "disabled";
> + };
> };
> };
> };
> --
> 2.4.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Stefan Agner <stefan@agner.ch> |
|---|---|
| Date | 2015-07-24 15:20 +0200 |
| Subject | [PATCH v7 3/5] mtd: nand: vf610_nfc: add device tree bindings |
| Message-ID | <pPL3l-6PY-33@gated-at.bofh.it> |
| In reply to | #1191812 |
Signed-off-by: Bill Pringlemeir <bpringlemeir@nbsps.com>
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
.../devicetree/bindings/mtd/vf610-nfc.txt | 45 ++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/vf610-nfc.txt
diff --git a/Documentation/devicetree/bindings/mtd/vf610-nfc.txt b/Documentation/devicetree/bindings/mtd/vf610-nfc.txt
new file mode 100644
index 0000000..cae5f25
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/vf610-nfc.txt
@@ -0,0 +1,45 @@
+Freescale's NAND flash controller (NFC)
+
+This variant of the Freescale NAND flash controller (NFC) can be found on
+Vybrid (vf610), MPC5125, MCF54418 and Kinetis K70.
+
+Required properties:
+- compatible: Should be set to "fsl,vf610-nfc"
+- reg: address range of the NFC
+- interrupts: interrupt of the NFC
+- nand-bus-width: see nand.txt
+- nand-ecc-mode: see nand.txt
+- nand-on-flash-bbt: see nand.txt
+- assigned-clocks: main clock from the SoC, for Vybrid <&clks VF610_CLK_NFC>;
+- assigned-clock-rates: The NAND bus timing is derived from this clock
+ rate and should not exceed maximum timing for any NAND memory chip
+ in a board stuffing. Typical NAND memory timings derived from this
+ clock are found in the SoC hardware reference manual. Furthermore,
+ there might be restrictions on maximum rates when using hardware ECC.
+
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+ representing partitions.
+
+Required properties for hardware ECC:
+- nand-ecc-strength: supported strengths are 24 and 32 bit (see nand.txt)
+- nand-ecc-step-size: step size equals page size, currently only 2k pages are
+ supported
+
+Example:
+
+ nfc: nand@400e0000 {
+ compatible = "fsl,vf610-nfc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x400e0000 0x4000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks VF610_CLK_NFC>;
+ clock-names = "nfc";
+ assigned-clocks = <&clks VF610_CLK_NFC>;
+ assigned-clock-rates = <33000000>;
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-ecc-strength = <32>;
+ nand-ecc-step-size = <2048>;
+ nand-on-flash-bbt;
+ };
--
2.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Stefan Agner <stefan@agner.ch> |
|---|---|
| Date | 2015-07-24 15:20 +0200 |
| Subject | [PATCH v7 2/5] mtd: nand: vf610_nfc: add hardware BCH-ECC support |
| Message-ID | <pPL3l-6PY-43@gated-at.bofh.it> |
| In reply to | #1191812 |
This adds hardware ECC support using the BCH encoder in the NFC IP.
The ECC encoder supports up to 32-bit correction by using 60 error
correction bytes. There is no sub-page ECC step, ECC is calculated
always accross the whole page (up to 2k pages). Raw writes writes
are possible through the common nand_write_page_raw implementation,
however raw reads are not possible since the hardware ECC mode need
to be enabled at command time.
Signed-off-by: Bill Pringlemeir <bpringlemeir@nbsps.com>
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
drivers/mtd/nand/Kconfig | 6 +-
drivers/mtd/nand/vf610_nfc.c | 201 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 204 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8550b14..e05f53c 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -469,8 +469,10 @@ config MTD_NAND_VF610_NFC
help
Enables support for NAND Flash Controller on some Freescale
processors like the VF610, MPC5125, MCF54418 or Kinetis K70.
- The driver supports a maximum 2k page size. The driver
- currently does not support hardware ECC.
+ The driver supports a maximum 2k page size. With 2k pages and
+ 64 bytes or more of OOB, hardware ECC with up to 32-bit error
+ correction is supported. Hardware ECC is only enabled through
+ device tree.
config MTD_NAND_MXC
tristate "MXC NAND support"
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
index 0da500e..4d795a5 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -19,6 +19,8 @@
* - Untested on MPC5125 and M54418.
* - DMA not used.
* - 2K pages or less.
+ * - Only 2K page w. 64+ OOB and hardware ECC.
+ * - Raw page reads not implemented when using ECC.
*/
#include <linux/module.h>
@@ -72,6 +74,8 @@
/* NFC ECC mode define */
#define ECC_BYPASS 0
+#define ECC_45_BYTE 6
+#define ECC_60_BYTE 7
/*** Register Mask and bit definitions */
@@ -104,6 +108,8 @@
#define STATUS_BYTE1_MASK 0x000000FF
/* NFC_FLASH_CONFIG Field */
+#define CONFIG_ECC_SRAM_ADDR_MASK 0x7FC00000
+#define CONFIG_ECC_SRAM_ADDR_SHIFT 22
#define CONFIG_ECC_SRAM_REQ_BIT (1<<21)
#define CONFIG_DMA_REQ_BIT (1<<20)
#define CONFIG_ECC_MODE_MASK 0x000E0000
@@ -122,6 +128,21 @@
#define CMD_DONE_CLEAR_BIT (1<<18)
#define IDLE_CLEAR_BIT (1<<17)
+/* ECC status placed at end of buffers. */
+#define ECC_SRAM_ADDR ((PAGE_2K + 256 - 8) >> 3)
+#define ECC_STATUS_MASK 0x80
+#define ECC_ERR_COUNT 0x3F
+
+/*
+ * ECC status is stored at NFC_CFG[ECCADD] +4 for little-endian
+ * and +7 for big-endian SoCs.
+ */
+#ifdef __LITTLE_ENDIAN
+#define ECC_OFFSET 4
+#else
+#define ECC_OFFSET 7
+#endif
+
struct vf610_nfc {
struct mtd_info mtd;
struct nand_chip chip;
@@ -136,10 +157,40 @@ struct vf610_nfc {
#define ALT_BUF_STAT 2
#define ALT_BUF_ONFI 3
struct clk *clk;
+ bool use_hw_ecc;
+ u32 ecc_mode;
};
#define mtd_to_nfc(_mtd) container_of(_mtd, struct vf610_nfc, mtd)
+static struct nand_ecclayout vf610_nfc_ecc45 = {
+ .eccbytes = 45,
+ .eccpos = {19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63},
+ .oobfree = {
+ {.offset = 2,
+ .length = 17} }
+};
+
+static struct nand_ecclayout vf610_nfc_ecc60 = {
+ .eccbytes = 60,
+ .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63 },
+ .oobfree = {
+ {.offset = 2,
+ .length = 2} }
+};
+
static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg)
{
return readl(nfc->regs + reg);
@@ -281,6 +332,13 @@ static void vf610_nfc_addr_cycle(struct vf610_nfc *nfc, int column, int page)
ROW_ADDR_SHIFT, page);
}
+static inline void vf610_nfc_ecc_mode(struct vf610_nfc *nfc, int ecc_mode)
+{
+ vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG,
+ CONFIG_ECC_MODE_MASK,
+ CONFIG_ECC_MODE_SHIFT, ecc_mode);
+}
+
static inline void vf610_nfc_transfer_size(struct vf610_nfc *nfc, int size)
{
vf610_nfc_write(nfc, NFC_SECTOR_SIZE, size);
@@ -299,13 +357,20 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
case NAND_CMD_SEQIN:
/* Use valid column/page from preread... */
vf610_nfc_addr_cycle(nfc, column, page);
+ nfc->buf_offset = 0;
+
/*
* SEQIN => data => PAGEPROG sequence is done by the controller
* hence we do not need to issue the command here...
*/
return;
case NAND_CMD_PAGEPROG:
- page_sz += mtd->writesize + mtd->oobsize;
+ page_sz += nfc->page_sz;
+ if (nfc->use_hw_ecc)
+ vf610_nfc_ecc_mode(nfc, nfc->ecc_mode);
+ else
+ vf610_nfc_ecc_mode(nfc, ECC_BYPASS);
+
vf610_nfc_transfer_size(nfc, page_sz);
vf610_nfc_send_commands(nfc, NAND_CMD_SEQIN,
command, PROGRAM_PAGE_CMD_CODE);
@@ -323,11 +388,13 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
vf610_nfc_send_commands(nfc, NAND_CMD_READ0,
NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
vf610_nfc_addr_cycle(nfc, column, page);
+ vf610_nfc_ecc_mode(nfc, ECC_BYPASS);
break;
case NAND_CMD_READ0:
page_sz += mtd->writesize + mtd->oobsize;
vf610_nfc_transfer_size(nfc, page_sz);
+ vf610_nfc_ecc_mode(nfc, nfc->ecc_mode);
vf610_nfc_send_commands(nfc, NAND_CMD_READ0,
NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
vf610_nfc_addr_cycle(nfc, column, page);
@@ -339,6 +406,7 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
vf610_nfc_send_command(nfc, command, READ_ONFI_PARAM_CMD_CODE);
vf610_nfc_set_field(nfc, NFC_ROW_ADDR, ROW_ADDR_MASK,
ROW_ADDR_SHIFT, column);
+ vf610_nfc_ecc_mode(nfc, ECC_BYPASS);
break;
case NAND_CMD_ERASE1:
@@ -367,6 +435,9 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
}
vf610_nfc_done(nfc);
+
+ nfc->use_hw_ecc = false;
+ nfc->page_sz = 0;
}
static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
@@ -392,6 +463,7 @@ static void vf610_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
l = min_t(uint, len, mtd->writesize + mtd->oobsize - c);
vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l);
+ nfc->page_sz += l;
nfc->buf_offset += l;
}
@@ -459,6 +531,84 @@ static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip)
#endif
}
+/* Count the number of 0's in buff up to max_bits */
+static inline int count_written_bits(uint8_t *buff, int size, int max_bits)
+{
+ uint32_t *buff32 = (uint32_t *)buff;
+ int k, written_bits = 0;
+
+ for (k = 0; k < (size / 4); k++) {
+ written_bits += hweight32(~buff32[k]);
+ if (written_bits > max_bits)
+ break;
+ }
+
+ return written_bits;
+}
+
+static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+ u8 ecc_status;
+ u8 ecc_count;
+ int flip;
+
+ ecc_status = __raw_readb(nfc->regs + ECC_SRAM_ADDR * 8 + ECC_OFFSET);
+ ecc_count = ecc_status & ECC_ERR_COUNT;
+ if (!(ecc_status & ECC_STATUS_MASK))
+ return ecc_count;
+
+ /*
+ * On an erased page, bit count should be zero or at least
+ * less then half of the ECC strength
+ */
+ flip = count_written_bits(dat, nfc->chip.ecc.size, ecc_count);
+
+ if (flip > ecc_count && flip > (nfc->chip.ecc.strength / 2))
+ return -1;
+
+ /* Erased page. */
+ memset(dat, 0xff, nfc->chip.ecc.size);
+ return 0;
+}
+
+static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ int eccsize = chip->ecc.size;
+ int stat;
+
+ vf610_nfc_read_buf(mtd, buf, eccsize);
+
+ if (oob_required)
+ vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ stat = vf610_nfc_correct_data(mtd, buf);
+
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+
+ return 0;
+}
+
+static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required)
+{
+ struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+ vf610_nfc_write_buf(mtd, buf, mtd->writesize);
+ if (oob_required)
+ vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ /* Always write whole page including OOB due to HW ECC */
+ nfc->use_hw_ecc = true;
+ nfc->page_sz = mtd->writesize + mtd->oobsize;
+
+ return 0;
+}
+
static const struct of_device_id vf610_nfc_dt_ids[] = {
{ .compatible = "fsl,vf610-nfc" },
{ /* sentinel */ }
@@ -483,6 +633,16 @@ static int vf610_nfc_init_controller(struct vf610_nfc *nfc)
vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG, CONFIG_PAGE_CNT_MASK,
CONFIG_PAGE_CNT_SHIFT, 1);
+ if (nfc->chip.ecc.mode == NAND_ECC_HW) {
+ /* Set ECC_STATUS offset */
+ vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG,
+ CONFIG_ECC_SRAM_ADDR_MASK,
+ CONFIG_ECC_SRAM_ADDR_SHIFT, ECC_SRAM_ADDR);
+
+ /* Enable ECC_STATUS */
+ vf610_nfc_set(nfc, NFC_FLASH_CONFIG, CONFIG_ECC_SRAM_REQ_BIT);
+ }
+
return 0;
}
@@ -565,6 +725,45 @@ static int vf610_nfc_probe(struct platform_device *pdev)
goto error;
}
+ if (chip->ecc.mode == NAND_ECC_HW) {
+ if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
+ dev_err(nfc->dev, "Unsupported flash with hwecc\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ if (chip->ecc.size != mtd->writesize) {
+ dev_err(nfc->dev, "Step size needs to be page size\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ /* Only 64 byte ECC layouts known */
+ if (mtd->oobsize > 64)
+ mtd->oobsize = 64;
+
+ if (chip->ecc.strength == 32) {
+ nfc->ecc_mode = ECC_60_BYTE;
+ chip->ecc.bytes = 60;
+ chip->ecc.layout = &vf610_nfc_ecc60;
+ } else if (chip->ecc.strength == 24) {
+ nfc->ecc_mode = ECC_45_BYTE;
+ chip->ecc.bytes = 45;
+ chip->ecc.layout = &vf610_nfc_ecc45;
+ } else {
+ dev_err(nfc->dev, "Unsupported ECC strength\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ /* propagate ecc.layout to mtd_info */
+ mtd->ecclayout = chip->ecc.layout;
+ chip->ecc.read_page = vf610_nfc_read_page;
+ chip->ecc.write_page = vf610_nfc_write_page;
+
+ chip->ecc.size = PAGE_2K;
+ }
+
/* second phase scan */
if (nand_scan_tail(mtd)) {
err = -ENXIO;
--
2.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web