[U-Boot] [PATCH v1 0/9] mtd: nand: mxs_nand: add device tree support

From: Stefan Agner stefan.agner@toradex.com
This patchset adds device tree support to the MXS NAND driver. This also allows to use fixed ECC strenght usingt he device tree properties nand-ecc-strength/nand-ecc-step-size and aligns behavior with the Linux GPMI NAND driver.
This is based on the "mtd: nand: mxs_nand: improve ECC support" patchset: https://patchwork.ozlabs.org/cover/897263/
Support for nand-ecc-strength/nand-ecc-step-size has recently been added in Linux, see: https://patchwork.kernel.org/patch/10257829/
This patchset has been tested with various ECC configurations on a Colibri iMX7.
-- Stefan
Stefan Agner (9): mtd: nand: mxs_nand: move register structs to driver data mtd: nand: mxs_nand: use more precise function name mtd: nand: mxs_nand: separate board/controller init mtd: nand: mxs_nand: add use_minimum_ecc to struct mtd: nand: mxs_nand: create separate header file mtd: nand: mxs_nand: add device tree support mtd: nand: mxs_nand: add support for specific ECC strength arm: dts: imx7: sync with Linux arm: dts: imx7: colibri: add raw NAND support
arch/arm/dts/imx7-colibri.dts | 28 ++ arch/arm/dts/imx7s.dtsi | 491 +++++++++++++++--------- drivers/mtd/nand/Kconfig | 7 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/mxs_nand.c | 195 +++++----- drivers/mtd/nand/mxs_nand.h | 72 ++++ drivers/mtd/nand/mxs_nand_dt.c | 86 +++++ include/dt-bindings/clock/imx7d-clock.h | 15 +- include/dt-bindings/power/imx7-power.h | 16 + 9 files changed, 621 insertions(+), 290 deletions(-) create mode 100644 drivers/mtd/nand/mxs_nand.h create mode 100644 drivers/mtd/nand/mxs_nand_dt.c create mode 100644 include/dt-bindings/power/imx7-power.h

From: Stefan Agner stefan.agner@toradex.com
Move GPMI and BCH register structs to the driver struct mxs_nand_info in prepartion for device tree support.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/mxs_nand.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 8305bf2302..f619a2f139 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -83,6 +83,9 @@ struct mxs_nand_info { uint8_t marking_block_bad; uint8_t raw_oob_mode;
+ struct mxs_gpmi_regs *gpmi_regs; + struct mxs_bch_regs *bch_regs; + /* Functions with altered behaviour */ int (*hooked_read_oob)(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); @@ -296,16 +299,15 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo, /* * Wait for BCH complete IRQ and clear the IRQ */ -static int mxs_nand_wait_for_bch_complete(void) +static int mxs_nand_wait_for_bch_complete(struct mxs_nand_info *nand_info) { - struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; int timeout = MXS_NAND_BCH_TIMEOUT; int ret;
- ret = mxs_wait_mask_set(&bch_regs->hw_bch_ctrl_reg, + ret = mxs_wait_mask_set(&nand_info->bch_regs->hw_bch_ctrl_reg, BCH_CTRL_COMPLETE_IRQ, timeout);
- writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr); + writel(BCH_CTRL_COMPLETE_IRQ, &nand_info->bch_regs->hw_bch_ctrl_clr);
return ret; } @@ -403,11 +405,9 @@ static int mxs_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(chip); - struct mxs_gpmi_regs *gpmi_regs = - (struct mxs_gpmi_regs *)MXS_GPMI_BASE; uint32_t tmp;
- tmp = readl(&gpmi_regs->hw_gpmi_stat); + tmp = readl(&nand_info->gpmi_regs->hw_gpmi_stat); tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
return tmp & 1; @@ -704,7 +704,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, goto rtn; }
- ret = mxs_nand_wait_for_bch_complete(); + ret = mxs_nand_wait_for_bch_complete(nand_info); if (ret) { printf("MXS NAND: BCH read timeout\n"); goto rtn; @@ -812,7 +812,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd, goto rtn; }
- ret = mxs_nand_wait_for_bch_complete(); + ret = mxs_nand_wait_for_bch_complete(nand_info); if (ret) { printf("MXS NAND: BCH write timeout\n"); goto rtn; @@ -1037,7 +1037,7 @@ static int mxs_nand_setup_ecc(struct mtd_info *mtd) struct nand_chip *nand = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(nand); struct bch_geometry *geo = &nand_info->bch_geometry; - struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; + struct mxs_bch_regs *bch_regs = nand_info->bch_regs; uint32_t tmp; int ret = -ENOTSUPP;
@@ -1138,10 +1138,6 @@ int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info) */ int mxs_nand_init(struct mxs_nand_info *info) { - struct mxs_gpmi_regs *gpmi_regs = - (struct mxs_gpmi_regs *)MXS_GPMI_BASE; - struct mxs_bch_regs *bch_regs = - (struct mxs_bch_regs *)MXS_BCH_BASE; int i = 0, j, ret = 0;
info->desc = malloc(sizeof(struct mxs_dma_desc *) * @@ -1170,14 +1166,14 @@ int mxs_nand_init(struct mxs_nand_info *info) }
/* Reset the GPMI block. */ - mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg); - mxs_reset_block(&bch_regs->hw_bch_ctrl_reg); + mxs_reset_block(&info->gpmi_regs->hw_gpmi_ctrl0_reg); + mxs_reset_block(&info->bch_regs->hw_bch_ctrl_reg);
/* * Choose NAND mode, set IRQ polarity, disable write protection and * select BCH ECC. */ - clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1, + clrsetbits_le32(&info->gpmi_regs->hw_gpmi_ctrl1, GPMI_CTRL1_GPMI_MODE, GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET | GPMI_CTRL1_BCH_MODE); @@ -1211,6 +1207,8 @@ void board_nand_init(void) } memset(nand_info, 0, sizeof(struct mxs_nand_info));
+ nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE; + nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; nand = &nand_info->chip; mtd = nand_to_mtd(nand); err = mxs_nand_alloc_buffers(nand_info);

From: Stefan Agner stefan.agner@toradex.com
This function initializes DMA descriptors so mxs_nand_init_dma is more precise. It also frees up the rather generic name mxs_nand_init.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/mxs_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index f619a2f139..3f97da5e8f 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -1136,7 +1136,7 @@ int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info) /* * Initializes the NFC hardware. */ -int mxs_nand_init(struct mxs_nand_info *info) +int mxs_nand_init_dma(struct mxs_nand_info *info) { int i = 0, j, ret = 0;
@@ -1215,7 +1215,7 @@ void board_nand_init(void) if (err) goto err1;
- err = mxs_nand_init(nand_info); + err = mxs_nand_init_dma(nand_info); if (err) goto err2;

From: Stefan Agner stefan.agner@toradex.com
In preparation for device tree support separate board init from controller init similar to other raw NAND drivers.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/mxs_nand.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 3f97da5e8f..b5fd0fdd62 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -1193,22 +1193,12 @@ err1: return ret; }
-void board_nand_init(void) +int mxs_nand_init(struct mxs_nand_info *nand_info) { struct mtd_info *mtd; - struct mxs_nand_info *nand_info; struct nand_chip *nand; int err;
- nand_info = malloc(sizeof(struct mxs_nand_info)); - if (!nand_info) { - printf("MXS NAND: Failed to allocate private data\n"); - return; - } - memset(nand_info, 0, sizeof(struct mxs_nand_info)); - - nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE; - nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; nand = &nand_info->chip; mtd = nand_to_mtd(nand); err = mxs_nand_alloc_buffers(nand_info); @@ -1265,12 +1255,29 @@ void board_nand_init(void) if (err) goto err2;
- return; + return 0;
err2: free(nand_info->data_buf); free(nand_info->cmd_buf); err1: free(nand_info); - return; + return err; +} + +void board_nand_init(void) +{ + struct mxs_nand_info *nand_info; + + nand_info = malloc(sizeof(struct mxs_nand_info)); + if (!nand_info) { + printf("MXS NAND: Failed to allocate private data\n"); + return; + } + memset(nand_info, 0, sizeof(struct mxs_nand_info)); + + nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE; + nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; + + mxs_nand_init(nand_info); }

From: Stefan Agner stefan.agner@toradex.com
Add use_minimum_ecc as struct mxs_nand_info field in preparation for device tree support.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/mxs_nand.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index b5fd0fdd62..978f6a6893 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -70,6 +70,8 @@ struct bch_geometry {
struct mxs_nand_info { struct nand_chip chip; + unsigned int max_ecc_strength_supported; + bool use_minimum_ecc; int cur_chip;
uint32_t cmd_queue_len; @@ -214,19 +216,11 @@ static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo, return 0; }
-static inline unsigned int mxs_nand_max_ecc_strength_supported(void) -{ - /* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */ - if (is_mx6sx() || is_mx7()) - return 62; - else - return 40; -} - static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo, struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); + struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) return -ENOTSUPP; @@ -249,7 +243,7 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo, if (geo->ecc_chunk_size < mtd->oobsize) return -EINVAL;
- if (geo->ecc_strength > mxs_nand_max_ecc_strength_supported()) + if (geo->ecc_strength > nand_info->max_ecc_strength_supported) return -EINVAL;
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size; @@ -260,6 +254,9 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo, static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo, struct mtd_info *mtd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct mxs_nand_info *nand_info = nand_get_controller_data(chip); + /* The default for the length of Galois Field. */ geo->gf_len = 13;
@@ -291,7 +288,7 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo, / (geo->gf_len * geo->ecc_chunk_count);
geo->ecc_strength = min(round_down(geo->ecc_strength, 2), - mxs_nand_max_ecc_strength_supported()); + nand_info->max_ecc_strength_supported);
return 0; } @@ -1041,9 +1038,8 @@ static int mxs_nand_setup_ecc(struct mtd_info *mtd) uint32_t tmp; int ret = -ENOTSUPP;
-#ifdef CONFIG_NAND_MXS_USE_MINIMUM_ECC - ret = mxs_nand_calc_ecc_layout_by_info(geo, mtd); -#endif + if (nand_info->use_minimum_ecc) + ret = mxs_nand_calc_ecc_layout_by_info(geo, mtd);
if (ret == -ENOTSUPP) ret = mxs_nand_calc_ecc_layout(geo, mtd); @@ -1279,5 +1275,15 @@ void board_nand_init(void) nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE; nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
+ /* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */ + if (is_mx6sx() || is_mx7()) + nand_info->max_ecc_strength_supported = 62; + else + nand_info->max_ecc_strength_supported = 40; + +#ifdef CONFIG_NAND_MXS_USE_MINIMUM_ECC + nand_info->use_minimum_ecc = true; +#endif + mxs_nand_init(nand_info); }

From: Stefan Agner stefan.agner@toradex.com
Create separate header file so we can use a separate compile unit for device tree support.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/mxs_nand.c | 61 ++----------------------------- drivers/mtd/nand/mxs_nand.h | 72 +++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 58 deletions(-) create mode 100644 drivers/mtd/nand/mxs_nand.h
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 978f6a6893..5fbbb0a706 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -14,11 +14,10 @@ */
#include <common.h> -#include <linux/mtd/mtd.h> +#include <dm.h> #include <linux/mtd/rawnand.h> #include <linux/types.h> #include <malloc.h> -#include <nand.h> #include <linux/errno.h> #include <asm/io.h> #include <asm/arch/clock.h> @@ -26,7 +25,8 @@ #include <asm/mach-imx/regs-bch.h> #include <asm/mach-imx/regs-gpmi.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/dma.h> + +#include "mxs_nand.h"
#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
@@ -46,61 +46,6 @@
#define MXS_NAND_BCH_TIMEOUT 10000
-/** - * @gf_len: The length of Galois Field. (e.g., 13 or 14) - * @ecc_strength: A number that describes the strength of the ECC - * algorithm. - * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note - * the first chunk in the page includes both data and - * metadata, so it's a bit larger than this value. - * @ecc_chunk_count: The number of ECC chunks in the page, - * @block_mark_byte_offset: The byte offset in the ECC-based page view at - * which the underlying physical block mark appears. - * @block_mark_bit_offset: The bit offset into the ECC-based page view at - * which the underlying physical block mark appears. - */ -struct bch_geometry { - unsigned int gf_len; - unsigned int ecc_strength; - unsigned int ecc_chunk_size; - unsigned int ecc_chunk_count; - unsigned int block_mark_byte_offset; - unsigned int block_mark_bit_offset; -}; - -struct mxs_nand_info { - struct nand_chip chip; - unsigned int max_ecc_strength_supported; - bool use_minimum_ecc; - int cur_chip; - - uint32_t cmd_queue_len; - uint32_t data_buf_size; - struct bch_geometry bch_geometry; - - uint8_t *cmd_buf; - uint8_t *data_buf; - uint8_t *oob_buf; - - uint8_t marking_block_bad; - uint8_t raw_oob_mode; - - struct mxs_gpmi_regs *gpmi_regs; - struct mxs_bch_regs *bch_regs; - - /* Functions with altered behaviour */ - int (*hooked_read_oob)(struct mtd_info *mtd, - loff_t from, struct mtd_oob_ops *ops); - int (*hooked_write_oob)(struct mtd_info *mtd, - loff_t to, struct mtd_oob_ops *ops); - int (*hooked_block_markbad)(struct mtd_info *mtd, - loff_t ofs); - - /* DMA descriptors */ - struct mxs_dma_desc **desc; - uint32_t desc_index; -}; - struct nand_ecclayout fake_ecc_layout;
/* diff --git a/drivers/mtd/nand/mxs_nand.h b/drivers/mtd/nand/mxs_nand.h new file mode 100644 index 0000000000..ae3432357e --- /dev/null +++ b/drivers/mtd/nand/mxs_nand.h @@ -0,0 +1,72 @@ +/* + * NXP GPMI NAND flash driver + * + * Copyright (C) 2018 Toradex + * Authors: + * Stefan Agner stefan.agner@toradex.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/mtd/mtd.h> +#include <asm/cache.h> +#include <nand.h> +#include <asm/mach-imx/dma.h> + +/** + * @gf_len: The length of Galois Field. (e.g., 13 or 14) + * @ecc_strength: A number that describes the strength of the ECC + * algorithm. + * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note + * the first chunk in the page includes both data and + * metadata, so it's a bit larger than this value. + * @ecc_chunk_count: The number of ECC chunks in the page, + * @block_mark_byte_offset: The byte offset in the ECC-based page view at + * which the underlying physical block mark appears. + * @block_mark_bit_offset: The bit offset into the ECC-based page view at + * which the underlying physical block mark appears. + */ +struct bch_geometry { + unsigned int gf_len; + unsigned int ecc_strength; + unsigned int ecc_chunk_size; + unsigned int ecc_chunk_count; + unsigned int block_mark_byte_offset; + unsigned int block_mark_bit_offset; +}; + +struct mxs_nand_info { + struct nand_chip chip; + struct udevice *dev; + unsigned int max_ecc_strength_supported; + bool use_minimum_ecc; + int cur_chip; + + uint32_t cmd_queue_len; + uint32_t data_buf_size; + struct bch_geometry bch_geometry; + + uint8_t *cmd_buf; + uint8_t *data_buf; + uint8_t *oob_buf; + + uint8_t marking_block_bad; + uint8_t raw_oob_mode; + + struct mxs_gpmi_regs *gpmi_regs; + struct mxs_bch_regs *bch_regs; + + /* Functions with altered behaviour */ + int (*hooked_read_oob)(struct mtd_info *mtd, + loff_t from, struct mtd_oob_ops *ops); + int (*hooked_write_oob)(struct mtd_info *mtd, + loff_t to, struct mtd_oob_ops *ops); + int (*hooked_block_markbad)(struct mtd_info *mtd, + loff_t ofs); + + /* DMA descriptors */ + struct mxs_dma_desc **desc; + uint32_t desc_index; +}; + +int mxs_nand_init(struct mxs_nand_info *nand_info);

From: Stefan Agner stefan.agner@toradex.com
Support driver data from device tree. Also support fsl,use-minimal-ecc similar to Linux' GPMI NAND driver.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/Kconfig | 7 +++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/mxs_nand.c | 5 ++ drivers/mtd/nand/mxs_nand_dt.c | 86 ++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 drivers/mtd/nand/mxs_nand_dt.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c039b9cc60..bdc272142e 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -154,6 +154,13 @@ config NAND_MXS
if NAND_MXS
+config NAND_MXS_DT + bool "Support MXS NAND controller as a DT device" + depends on OF_CONTROL && MTD + help + Enable the driver for MXS NAND flash on platforms using + device tree. + config NAND_MXS_USE_MINIMUM_ECC bool "Use minimum ECC strength supported by the controller" default false diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 332d905a3a..86877e1592 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_NAND_LPC32XX_SLC) += lpc32xx_nand_slc.o obj-$(CONFIG_NAND_VF610_NFC) += vf610_nfc.o obj-$(CONFIG_NAND_MXC) += mxc_nand.o obj-$(CONFIG_NAND_MXS) += mxs_nand.o +obj-$(CONFIG_NAND_MXS_DT) += mxs_nand_dt.o obj-$(CONFIG_NAND_PXA3XX) += pxa3xx_nand.o obj-$(CONFIG_NAND_SPEAR) += spr_nand.o obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 5fbbb0a706..8c3f4f1871 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -1159,6 +1159,9 @@ int mxs_nand_init(struct mxs_nand_info *nand_info) nand_set_controller_data(nand, nand_info); nand->options |= NAND_NO_SUBPAGE_WRITE;
+ if (nand_info->dev) + nand->flash_node = dev_of_offset(nand_info->dev); + nand->cmd_ctrl = mxs_nand_cmd_ctrl;
nand->dev_ready = mxs_nand_device_ready; @@ -1206,6 +1209,7 @@ err1: return err; }
+#ifndef CONFIG_NAND_MXS_DT void board_nand_init(void) { struct mxs_nand_info *nand_info; @@ -1232,3 +1236,4 @@ void board_nand_init(void)
mxs_nand_init(nand_info); } +#endif diff --git a/drivers/mtd/nand/mxs_nand_dt.c b/drivers/mtd/nand/mxs_nand_dt.c new file mode 100644 index 0000000000..c7355371ac --- /dev/null +++ b/drivers/mtd/nand/mxs_nand_dt.c @@ -0,0 +1,86 @@ +/* + * NXP GPMI NAND flash driver (DT initialization) + * + * Copyright (C) 2018 Toradex + * Authors: + * Stefan Agner stefan.agner@toradex.com + * + * Based on denali_dt.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <dm.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/printk.h> + +#include "mxs_nand.h" + +struct mxs_nand_dt_data { + unsigned int max_ecc_strength_supported; +}; + +static const struct mxs_nand_dt_data mxs_nand_imx7d_data = { + .max_ecc_strength_supported = 62, +}; + +static const struct udevice_id mxs_nand_dt_ids[] = { + { + .compatible = "fsl,imx7d-gpmi-nand", + .data = (unsigned long)&mxs_nand_imx7d_data, + }, + { /* sentinel */ } +}; + +static int mxs_nand_dt_probe(struct udevice *dev) +{ + struct mxs_nand_info *info = dev_get_priv(dev); + const struct mxs_nand_dt_data *data; + struct resource res; + int ret; + + data = (void *)dev_get_driver_data(dev); + if (data) + info->max_ecc_strength_supported = data->max_ecc_strength_supported; + + info->dev = dev; + + ret = dev_read_resource_byname(dev, "gpmi-nand", &res); + if (ret) + return ret; + + info->gpmi_regs = devm_ioremap(dev, res.start, resource_size(&res)); + + + ret = dev_read_resource_byname(dev, "bch", &res); + if (ret) + return ret; + + info->bch_regs = devm_ioremap(dev, res.start, resource_size(&res)); + + info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc"); + + return mxs_nand_init(info); +} + +U_BOOT_DRIVER(mxs_nand_dt) = { + .name = "mxs-nand-dt", + .id = UCLASS_MTD, + .of_match = mxs_nand_dt_ids, + .probe = mxs_nand_dt_probe, + .priv_auto_alloc_size = sizeof(struct mxs_nand_info), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(mxs_nand_dt), + &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize MXS NAND controller. (error %d)\n", + ret); +}

From: Stefan Agner stefan.agner@toradex.com
Add support for specified ECC strength/size using device tree properties nand-ecc-strength/nand-ecc-step-size.
This aligns behavior with the mainline driver, such that: - If fsl,use-minimal-ecc is requested it will use data from data sheet/ONFI. If this is not available the driver will fail. - If nand-ecc-strength/nand-ecc-step-size are specified those value will be used. - By default maximum possible ECC strength is used
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
drivers/mtd/nand/mxs_nand.c | 44 +++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 8c3f4f1871..746444d3fd 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -162,15 +162,14 @@ static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo, }
static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo, - struct mtd_info *mtd) + struct mtd_info *mtd, + unsigned int ecc_strength, + unsigned int ecc_step) { struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
- if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) - return -ENOTSUPP; - - switch (chip->ecc_step_ds) { + switch (ecc_step) { case SZ_512: geo->gf_len = 13; break; @@ -181,8 +180,8 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo, return -EINVAL; }
- geo->ecc_chunk_size = chip->ecc_step_ds; - geo->ecc_strength = round_up(chip->ecc_strength_ds, 2); + geo->ecc_chunk_size = ecc_step; + geo->ecc_strength = round_up(ecc_strength, 2);
/* Keep the C >= O */ if (geo->ecc_chunk_size < mtd->oobsize) @@ -965,6 +964,28 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs) return 0; }
+static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_chip *nand = mtd_to_nand(mtd); + struct mxs_nand_info *nand_info = nand_get_controller_data(nand); + + if (chip->ecc.strength > 0 && chip->ecc.size > 0) + return mxs_nand_calc_ecc_layout_by_info(geo, mtd, + chip->ecc.strength, chip->ecc.size); + + if (nand_info->use_minimum_ecc || + mxs_nand_calc_ecc_layout(geo, mtd)) { + if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) + return -EINVAL; + + return mxs_nand_calc_ecc_layout_by_info(geo, mtd, + chip->ecc_strength_ds, chip->ecc_step_ds); + } + + return 0; +} + /* * At this point, the physical NAND Flash chips have been identified and * counted, so we know the physical geometry. This enables us to make some @@ -981,14 +1002,9 @@ static int mxs_nand_setup_ecc(struct mtd_info *mtd) struct bch_geometry *geo = &nand_info->bch_geometry; struct mxs_bch_regs *bch_regs = nand_info->bch_regs; uint32_t tmp; - int ret = -ENOTSUPP; - - if (nand_info->use_minimum_ecc) - ret = mxs_nand_calc_ecc_layout_by_info(geo, mtd); - - if (ret == -ENOTSUPP) - ret = mxs_nand_calc_ecc_layout(geo, mtd); + int ret;
+ ret = mxs_nand_set_geometry(mtd, geo); if (ret) return ret;

From: Stefan Agner stefan.agner@toradex.com
Sync with Linux commit 60cc43fc8884 ("Linux 4.17-rc1").
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
arch/arm/dts/imx7s.dtsi | 491 +++++++++++++++--------- include/dt-bindings/clock/imx7d-clock.h | 15 +- include/dt-bindings/power/imx7-power.h | 16 + 3 files changed, 341 insertions(+), 181 deletions(-) create mode 100644 include/dt-bindings/power/imx7-power.h
diff --git a/arch/arm/dts/imx7s.dtsi b/arch/arm/dts/imx7s.dtsi index a7d48e785d..4d42335c0d 100644 --- a/arch/arm/dts/imx7s.dtsi +++ b/arch/arm/dts/imx7s.dtsi @@ -42,6 +42,7 @@ */
#include <dt-bindings/clock/imx7d-clock.h> +#include <dt-bindings/power/imx7-power.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> @@ -57,7 +58,7 @@ * Also for U-Boot there must be a pre-existing /memory node. */ chosen {}; - memory { device_type = "memory"; reg = <0 0>; }; + memory { device_type = "memory"; };
aliases { gpio0 = &gpio1; @@ -115,11 +116,77 @@ clock-output-names = "osc"; };
+ usbphynop1: usbphynop1 { + compatible = "usb-nop-xceiv"; + clocks = <&clks IMX7D_USB_PHY1_CLK>; + clock-names = "main_clk"; + #phy-cells = <0>; + }; + + usbphynop3: usbphynop3 { + compatible = "usb-nop-xceiv"; + clocks = <&clks IMX7D_USB_HSIC_ROOT_CLK>; + clock-names = "main_clk"; + #phy-cells = <0>; + }; + + pmu { + compatible = "arm,cortex-a7-pmu"; + interrupt-parent = <&gpc>; + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&cpu0>; + }; + + replicator { + /* + * non-configurable replicators don't show up on the + * AMBA bus. As such no need to add "arm,primecell" + */ + compatible = "arm,coresight-replicator"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + /* replicator output ports */ + port@0 { + reg = <0>; + replicator_out_port0: endpoint { + remote-endpoint = <&tpiu_in_port>; + }; + }; + + port@1 { + reg = <1>; + replicator_out_port1: endpoint { + remote-endpoint = <&etr_in_port>; + }; + }; + + /* replicator input port */ + port@2 { + reg = <0>; + replicator_in_port0: endpoint { + slave-mode; + remote-endpoint = <&etf_out_port>; + }; + }; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <&intc>; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; + }; + soc { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; - interrupt-parent = <&intc>; + interrupt-parent = <&gpc>; ranges;
funnel@30041000 { @@ -259,62 +326,18 @@ }; };
- replicator { - /* - * non-configurable replicators don't show up on the - * AMBA bus. As such no need to add "arm,primecell" - */ - compatible = "arm,coresight-replicator"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* replicator output ports */ - port@0 { - reg = <0>; - replicator_out_port0: endpoint { - remote-endpoint = <&tpiu_in_port>; - }; - }; - - port@1 { - reg = <1>; - replicator_out_port1: endpoint { - remote-endpoint = <&etr_in_port>; - }; - }; - - /* replicator input port */ - port@2 { - reg = <0>; - replicator_in_port0: endpoint { - slave-mode; - remote-endpoint = <&etf_out_port>; - }; - }; - }; - }; - intc: interrupt-controller@31001000 { compatible = "arm,cortex-a7-gic"; interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; #interrupt-cells = <3>; interrupt-controller; + interrupt-parent = <&intc>; reg = <0x31001000 0x1000>, <0x31002000 0x2000>, <0x31004000 0x2000>, <0x31006000 0x2000>; };
- timer { - compatible = "arm,armv7-timer"; - interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; - }; - aips1: aips-bus@30000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; @@ -482,20 +505,49 @@ status = "disabled"; };
+ kpp: kpp@30320000 { + compatible = "fsl,imx7d-kpp", "fsl,imx21-kpp"; + reg = <0x30320000 0x10000>; + interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_KPP_ROOT_CLK>; + status = "disabled"; + }; + iomuxc: iomuxc@30330000 { compatible = "fsl,imx7d-iomuxc"; reg = <0x30330000 0x10000>; };
gpr: iomuxc-gpr@30340000 { - compatible = "fsl,imx7d-iomuxc-gpr", "syscon"; + compatible = "fsl,imx7d-iomuxc-gpr", + "fsl,imx6q-iomuxc-gpr", "syscon"; reg = <0x30340000 0x10000>; };
ocotp: ocotp-ctrl@30350000 { + #address-cells = <1>; + #size-cells = <1>; compatible = "fsl,imx7d-ocotp", "syscon"; reg = <0x30350000 0x10000>; clocks = <&clks IMX7D_OCOTP_CLK>; + + tempmon_calib: calib@3c { + reg = <0x3c 0x4>; + }; + + tempmon_temp_grade: temp-grade@10 { + reg = <0x10 0x4>; + }; + }; + + tempmon: tempmon { + compatible = "fsl,imx7d-tempmon"; + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>; + fsl,tempmon =<&anatop>; + nvmem-cells = <&tempmon_calib>, + <&tempmon_temp_grade>; + nvmem-cell-names = "calib", "temp_grade"; + clocks = <&clks IMX7D_PLL_SYS_MAIN_CLK>; };
anatop: anatop@30360000 { @@ -504,8 +556,11 @@ reg = <0x30360000 0x10000>; interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>;
- reg_1p0d: regulator-vdd1p0d { + reg_1p0d: regulator-vdd1p0d@30360210 { + reg = <0x30360210>; compatible = "fsl,anatop-regulator"; regulator-name = "vdd1p0d"; regulator-min-microvolt = <800000>; @@ -516,6 +571,7 @@ anatop-min-bit-val = <8>; anatop-min-voltage = <800000>; anatop-max-voltage = <1200000>; + anatop-enable-bit = <0>; }; };
@@ -529,12 +585,15 @@ offset = <0x34>; interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_SNVS_CLK>; + clock-names = "snvs-rtc"; };
snvs_poweroff: snvs-poweroff { compatible = "syscon-poweroff"; regmap = <&snvs>; offset = <0x38>; + value = <0x60>; mask = <0x60>; };
@@ -558,11 +617,32 @@ };
src: src@30390000 { - compatible = "fsl,imx7d-src", "fsl,imx51-src", "syscon"; + compatible = "fsl,imx7d-src", "syscon"; reg = <0x30390000 0x10000>; interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; #reset-cells = <1>; }; + + gpc: gpc@303a0000 { + compatible = "fsl,imx7d-gpc"; + reg = <0x303a0000 0x10000>; + interrupt-controller; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <3>; + interrupt-parent = <&intc>; + #power-domain-cells = <1>; + + pgc { + #address-cells = <1>; + #size-cells = <0>; + + pgc_pcie_phy: pgc-power-domain@1 { + #power-domain-cells = <0>; + reg = <1>; + power-supply = <®_1p0d>; + }; + }; + }; };
aips2: aips-bus@30400000 { @@ -609,7 +689,7 @@ clocks = <&clks IMX7D_PWM1_ROOT_CLK>, <&clks IMX7D_PWM1_ROOT_CLK>; clock-names = "ipg", "per"; - #pwm-cells = <2>; + #pwm-cells = <3>; status = "disabled"; };
@@ -620,7 +700,7 @@ clocks = <&clks IMX7D_PWM2_ROOT_CLK>, <&clks IMX7D_PWM2_ROOT_CLK>; clock-names = "ipg", "per"; - #pwm-cells = <2>; + #pwm-cells = <3>; status = "disabled"; };
@@ -631,7 +711,7 @@ clocks = <&clks IMX7D_PWM3_ROOT_CLK>, <&clks IMX7D_PWM3_ROOT_CLK>; clock-names = "ipg", "per"; - #pwm-cells = <2>; + #pwm-cells = <3>; status = "disabled"; };
@@ -642,7 +722,7 @@ clocks = <&clks IMX7D_PWM4_ROOT_CLK>, <&clks IMX7D_PWM4_ROOT_CLK>; clock-names = "ipg", "per"; - #pwm-cells = <2>; + #pwm-cells = <3>; status = "disabled"; };
@@ -664,118 +744,156 @@ reg = <0x30800000 0x400000>; ranges;
- ecspi1: ecspi@30820000 { + spba-bus@30800000 { + compatible = "fsl,spba-bus", "simple-bus"; #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; - reg = <0x30820000 0x10000>; - interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>, - <&clks IMX7D_ECSPI1_ROOT_CLK>; - clock-names = "ipg", "per"; - status = "disabled"; - }; + #size-cells = <1>; + reg = <0x30800000 0x100000>; + ranges; + + ecspi1: ecspi@30820000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; + reg = <0x30820000 0x10000>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>, + <&clks IMX7D_ECSPI1_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + };
- ecspi2: ecspi@30830000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; - reg = <0x30830000 0x10000>; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>, - <&clks IMX7D_ECSPI2_ROOT_CLK>; - clock-names = "ipg", "per"; - status = "disabled"; - }; + ecspi2: ecspi@30830000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; + reg = <0x30830000 0x10000>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>, + <&clks IMX7D_ECSPI2_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + };
- ecspi3: ecspi@30840000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; - reg = <0x30840000 0x10000>; - interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>, - <&clks IMX7D_ECSPI3_ROOT_CLK>; - clock-names = "ipg", "per"; - status = "disabled"; - }; + ecspi3: ecspi@30840000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; + reg = <0x30840000 0x10000>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>, + <&clks IMX7D_ECSPI3_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + };
- uart1: serial@30860000 { - compatible = "fsl,imx7d-uart", - "fsl,imx6q-uart"; - reg = <0x30860000 0x10000>; - interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_UART1_ROOT_CLK>, - <&clks IMX7D_UART1_ROOT_CLK>; - clock-names = "ipg", "per"; - status = "disabled"; - }; + uart1: serial@30860000 { + compatible = "fsl,imx7d-uart", + "fsl,imx6q-uart"; + reg = <0x30860000 0x10000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_UART1_ROOT_CLK>, + <&clks IMX7D_UART1_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + };
- uart2: serial@30890000 { - compatible = "fsl,imx7d-uart", - "fsl,imx6q-uart"; - reg = <0x30890000 0x10000>; - interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_UART2_ROOT_CLK>, - <&clks IMX7D_UART2_ROOT_CLK>; - clock-names = "ipg", "per"; - status = "disabled"; - }; + uart2: serial@30890000 { + compatible = "fsl,imx7d-uart", + "fsl,imx6q-uart"; + reg = <0x30890000 0x10000>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_UART2_ROOT_CLK>, + <&clks IMX7D_UART2_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + };
- uart3: serial@30880000 { - compatible = "fsl,imx7d-uart", - "fsl,imx6q-uart"; - reg = <0x30880000 0x10000>; - interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_UART3_ROOT_CLK>, - <&clks IMX7D_UART3_ROOT_CLK>; - clock-names = "ipg", "per"; - status = "disabled"; - }; + uart3: serial@30880000 { + compatible = "fsl,imx7d-uart", + "fsl,imx6q-uart"; + reg = <0x30880000 0x10000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_UART3_ROOT_CLK>, + <&clks IMX7D_UART3_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + };
- sai1: sai@308a0000 { - #sound-dai-cells = <0>; - compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai"; - reg = <0x308a0000 0x10000>; - interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_SAI1_IPG_CLK>, - <&clks IMX7D_SAI1_ROOT_CLK>, - <&clks IMX7D_CLK_DUMMY>, - <&clks IMX7D_CLK_DUMMY>; - clock-names = "bus", "mclk1", "mclk2", "mclk3"; - dma-names = "rx", "tx"; - dmas = <&sdma 8 24 0>, <&sdma 9 24 0>; - status = "disabled"; - }; + sai1: sai@308a0000 { + #sound-dai-cells = <0>; + compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai"; + reg = <0x308a0000 0x10000>; + interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_SAI1_IPG_CLK>, + <&clks IMX7D_SAI1_ROOT_CLK>, + <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CLK_DUMMY>; + clock-names = "bus", "mclk1", "mclk2", "mclk3"; + dma-names = "rx", "tx"; + dmas = <&sdma 8 24 0>, <&sdma 9 24 0>; + status = "disabled"; + };
- sai2: sai@308b0000 { - #sound-dai-cells = <0>; - compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai"; - reg = <0x308b0000 0x10000>; - interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_SAI2_IPG_CLK>, - <&clks IMX7D_SAI2_ROOT_CLK>, - <&clks IMX7D_CLK_DUMMY>, - <&clks IMX7D_CLK_DUMMY>; - clock-names = "bus", "mclk1", "mclk2", "mclk3"; - dma-names = "rx", "tx"; - dmas = <&sdma 10 24 0>, <&sdma 11 24 0>; - status = "disabled"; + sai2: sai@308b0000 { + #sound-dai-cells = <0>; + compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai"; + reg = <0x308b0000 0x10000>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_SAI2_IPG_CLK>, + <&clks IMX7D_SAI2_ROOT_CLK>, + <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CLK_DUMMY>; + clock-names = "bus", "mclk1", "mclk2", "mclk3"; + dma-names = "rx", "tx"; + dmas = <&sdma 10 24 0>, <&sdma 11 24 0>; + status = "disabled"; + }; + + sai3: sai@308c0000 { + #sound-dai-cells = <0>; + compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai"; + reg = <0x308c0000 0x10000>; + interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_SAI3_IPG_CLK>, + <&clks IMX7D_SAI3_ROOT_CLK>, + <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CLK_DUMMY>; + clock-names = "bus", "mclk1", "mclk2", "mclk3"; + dma-names = "rx", "tx"; + dmas = <&sdma 12 24 0>, <&sdma 13 24 0>; + status = "disabled"; + }; };
- sai3: sai@308c0000 { - #sound-dai-cells = <0>; - compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai"; - reg = <0x308c0000 0x10000>; - interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_SAI3_IPG_CLK>, - <&clks IMX7D_SAI3_ROOT_CLK>, - <&clks IMX7D_CLK_DUMMY>, - <&clks IMX7D_CLK_DUMMY>; - clock-names = "bus", "mclk1", "mclk2", "mclk3"; - dma-names = "rx", "tx"; - dmas = <&sdma 12 24 0>, <&sdma 13 24 0>; - status = "disabled"; + crypto: caam@30900000 { + compatible = "fsl,sec-v4.0"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x30900000 0x40000>; + ranges = <0 0x30900000 0x40000>; + interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_CAAM_CLK>, + <&clks IMX7D_AHB_CHANNEL_ROOT_CLK>; + clock-names = "ipg", "aclk"; + + sec_jr0: jr0@1000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x1000 0x1000>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; + }; + + sec_jr1: jr1@2000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x2000 0x1000>; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; + }; + + sec_jr2: jr1@3000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x3000 0x1000>; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + }; };
flexcan1: can@30a00000 { @@ -918,24 +1036,12 @@ reg = <0x30b30200 0x200>; };
- usbphynop1: usbphynop1 { - compatible = "usb-nop-xceiv"; - clocks = <&clks IMX7D_USB_PHY1_CLK>; - clock-names = "main_clk"; - }; - - usbphynop3: usbphynop3 { - compatible = "usb-nop-xceiv"; - clocks = <&clks IMX7D_USB_HSIC_ROOT_CLK>; - clock-names = "main_clk"; - }; - usdhc1: usdhc@30b40000 { compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc"; reg = <0x30b40000 0x10000>; interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_CLK_DUMMY>, - <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_IPG_ROOT_CLK>, + <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>, <&clks IMX7D_USDHC1_ROOT_CLK>; clock-names = "ipg", "ahb", "per"; bus-width = <4>; @@ -946,8 +1052,8 @@ compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc"; reg = <0x30b50000 0x10000>; interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_CLK_DUMMY>, - <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_IPG_ROOT_CLK>, + <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>, <&clks IMX7D_USDHC2_ROOT_CLK>; clock-names = "ipg", "ahb", "per"; bus-width = <4>; @@ -958,8 +1064,8 @@ compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc"; reg = <0x30b60000 0x10000>; interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_CLK_DUMMY>, - <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_IPG_ROOT_CLK>, + <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>, <&clks IMX7D_USDHC3_ROOT_CLK>; clock-names = "ipg", "ahb", "per"; bus-width = <4>; @@ -980,9 +1086,11 @@ fec1: ethernet@30be0000 { compatible = "fsl,imx7d-fec", "fsl,imx6sx-fec"; reg = <0x30be0000 0x10000>; - interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, + interrupt-names = "int0", "int1", "int2", "pps"; + interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; + <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>, <&clks IMX7D_ENET_AXI_ROOT_CLK>, <&clks IMX7D_ENET1_TIME_ROOT_CLK>, @@ -995,5 +1103,36 @@ status = "disabled"; }; }; + + dma_apbh: dma-apbh@33000000 { + compatible = "fsl,imx7d-dma-apbh", "fsl,imx28-dma-apbh"; + reg = <0x33000000 0x2000>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3"; + #dma-cells = <1>; + dma-channels = <4>; + clocks = <&clks IMX7D_NAND_USDHC_BUS_RAWNAND_CLK>; + }; + + gpmi: gpmi-nand@33002000{ + compatible = "fsl,imx7d-gpmi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x33002000 0x2000>, <0x33004000 0x4000>; + reg-names = "gpmi-nand", "bch"; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "bch"; + clocks = <&clks IMX7D_NAND_RAWNAND_CLK>, + <&clks IMX7D_NAND_USDHC_BUS_RAWNAND_CLK>; + clock-names = "gpmi_io", "gpmi_bch_apb"; + dmas = <&dma_apbh 0>; + dma-names = "rx-tx"; + status = "disabled"; + assigned-clocks = <&clks IMX7D_NAND_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_500M_CLK>; + }; }; }; diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h index a7a1a50f33..b2325d3e23 100644 --- a/include/dt-bindings/clock/imx7d-clock.h +++ b/include/dt-bindings/clock/imx7d-clock.h @@ -80,10 +80,10 @@ #define IMX7D_ARM_M4_ROOT_SRC 67 #define IMX7D_ARM_M4_ROOT_CG 68 #define IMX7D_ARM_M4_ROOT_DIV 69 -#define IMX7D_ARM_M0_ROOT_CLK 70 -#define IMX7D_ARM_M0_ROOT_SRC 71 -#define IMX7D_ARM_M0_ROOT_CG 72 -#define IMX7D_ARM_M0_ROOT_DIV 73 +#define IMX7D_ARM_M0_ROOT_CLK 70 /* unused */ +#define IMX7D_ARM_M0_ROOT_SRC 71 /* unused */ +#define IMX7D_ARM_M0_ROOT_CG 72 /* unused */ +#define IMX7D_ARM_M0_ROOT_DIV 73 /* unused */ #define IMX7D_MAIN_AXI_ROOT_CLK 74 #define IMX7D_MAIN_AXI_ROOT_SRC 75 #define IMX7D_MAIN_AXI_ROOT_CG 76 @@ -450,5 +450,10 @@ #define IMX7D_CLK_ARM 437 #define IMX7D_CKIL 438 #define IMX7D_OCOTP_CLK 439 -#define IMX7D_CLK_END 440 +#define IMX7D_NAND_RAWNAND_CLK 440 +#define IMX7D_NAND_USDHC_BUS_RAWNAND_CLK 441 +#define IMX7D_SNVS_CLK 442 +#define IMX7D_CAAM_CLK 443 +#define IMX7D_KPP_ROOT_CLK 444 +#define IMX7D_CLK_END 445 #endif /* __DT_BINDINGS_CLOCK_IMX7D_H */ diff --git a/include/dt-bindings/power/imx7-power.h b/include/dt-bindings/power/imx7-power.h new file mode 100644 index 0000000000..3a181e4105 --- /dev/null +++ b/include/dt-bindings/power/imx7-power.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2017 Impinj + * + * 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 __DT_BINDINGS_IMX7_POWER_H__ +#define __DT_BINDINGS_IMX7_POWER_H__ + +#define IMX7_POWER_DOMAIN_MIPI_PHY 0 +#define IMX7_POWER_DOMAIN_PCIE_PHY 1 +#define IMX7_POWER_DOMAIN_USB_HSIC_PHY 2 + +#endif

From: Stefan Agner stefan.agner@toradex.com
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
arch/arm/dts/imx7-colibri.dts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/arch/arm/dts/imx7-colibri.dts b/arch/arm/dts/imx7-colibri.dts index f6c21052ae..a3b5618b45 100644 --- a/arch/arm/dts/imx7-colibri.dts +++ b/arch/arm/dts/imx7-colibri.dts @@ -17,6 +17,15 @@ }; };
+&gpmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpmi_nand>; + fsl,use-minimum-ecc; + nand-on-flash-bbt; + nand-ecc-mode = "hw"; + status = "okay"; +}; + &i2c1 { pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; @@ -49,6 +58,25 @@ };
&iomuxc { + pinctrl_gpmi_nand: gpmi-nand-grp { + fsl,pins = < + MX7D_PAD_SD3_CLK__NAND_CLE 0x71 + MX7D_PAD_SD3_CMD__NAND_ALE 0x71 + MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B 0x71 + MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74 + MX7D_PAD_SD3_STROBE__NAND_RE_B 0x71 + MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71 + MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71 + MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71 + MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71 + MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71 + MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71 + MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71 + MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71 + MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71 + >; + }; + pinctrl_i2c4: i2c4-grp { fsl,pins = < MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA 0x4000007f

On 04/20/2018 10:53 AM, Stefan Agner wrote:
From: Stefan Agner stefan.agner@toradex.com
Signed-off-by: Stefan Agner stefan.agner@toradex.com
arch/arm/dts/imx7-colibri.dts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/arch/arm/dts/imx7-colibri.dts b/arch/arm/dts/imx7-colibri.dts index f6c21052ae..a3b5618b45 100644 --- a/arch/arm/dts/imx7-colibri.dts +++ b/arch/arm/dts/imx7-colibri.dts @@ -17,6 +17,15 @@ }; };
+&gpmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpmi_nand>;
- fsl,use-minimum-ecc;
enable minimum ecc may cause no backward compatible since previous implementation use oob space for ecc as much as possible. May consider mention this in docs and don't enable it by default?
- nand-on-flash-bbt;
- nand-ecc-mode = "hw";
- status = "okay";
+};
- &i2c1 { pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>;
@@ -49,6 +58,25 @@ };
&iomuxc {
- pinctrl_gpmi_nand: gpmi-nand-grp {
fsl,pins = <
MX7D_PAD_SD3_CLK__NAND_CLE 0x71
MX7D_PAD_SD3_CMD__NAND_ALE 0x71
MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B 0x71
MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74
MX7D_PAD_SD3_STROBE__NAND_RE_B 0x71
MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71
MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71
MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71
MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71
MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71
MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71
MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71
MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71
MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71
>;
- };
- pinctrl_i2c4: i2c4-grp { fsl,pins = < MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA 0x4000007f

On 26.06.2018 23:24, Han Xu wrote:
On 04/20/2018 10:53 AM, Stefan Agner wrote:
From: Stefan Agner stefan.agner@toradex.com
Signed-off-by: Stefan Agner stefan.agner@toradex.com
arch/arm/dts/imx7-colibri.dts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/arch/arm/dts/imx7-colibri.dts b/arch/arm/dts/imx7-colibri.dts index f6c21052ae..a3b5618b45 100644 --- a/arch/arm/dts/imx7-colibri.dts +++ b/arch/arm/dts/imx7-colibri.dts @@ -17,6 +17,15 @@ }; };
+&gpmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpmi_nand>;
- fsl,use-minimum-ecc;
enable minimum ecc may cause no backward compatible since previous implementation use oob space for ecc as much as possible. May consider mention this in docs and don't enable it by default?
Yes I am aware of that.
Unfortunately, we ship already lots of products with downstream kernels. And those kernels seem to default to a behavior which is similar to mainlines "fsl,use-minimum-ecc". So with this change I only make sure that upstream kernels work with the layout used in downstream U-Boot/Linux.
-- Stefan
- nand-on-flash-bbt;
- nand-ecc-mode = "hw";
- status = "okay";
+};
- &i2c1 { pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>;
@@ -49,6 +58,25 @@ };
&iomuxc {
- pinctrl_gpmi_nand: gpmi-nand-grp {
fsl,pins = <
MX7D_PAD_SD3_CLK__NAND_CLE 0x71
MX7D_PAD_SD3_CMD__NAND_ALE 0x71
MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B 0x71
MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74
MX7D_PAD_SD3_STROBE__NAND_RE_B 0x71
MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71
MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71
MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71
MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71
MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71
MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71
MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71
MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71
MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71
>;
- };
- pinctrl_i2c4: i2c4-grp { fsl,pins = < MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA 0x4000007f
participants (2)
-
Han Xu
-
Stefan Agner